Skip to content
Permalink
Newer
Older
100644 2893 lines (2679 sloc) 87.2 KB
Sep 5, 2014
1
;(function($B){
2
3
var _b_ = $B.builtins
Sep 5, 2014
4
5
// build tables from data in unicode_data.js
6
var unicode_tables = $B.unicode_tables
Sep 5, 2014
7
8
9
$B.has_surrogate = function(s){
10
// Check if there are "surrogate pairs" characters in string s
11
for(var i = 0; i < s.length; i++){
12
code = s.charCodeAt(i)
13
if(code >= 0xD800 && code <= 0xDBFF){
14
return true
15
}
16
}
17
return false
18
}
19
20
$B.String = function(s){
21
var codepoints = [],
22
surrogates = [],
23
j = 0
24
for(var i = 0, len = s.length; i < len; i++){
25
var cp = s.codePointAt(i)
26
if(cp >= 0x10000){
27
surrogates.push(j)
32
if(surrogates.length == 0){
33
return s
35
var res = new String(s)
36
res.__class__ = str
37
res.surrogates = surrogates
38
return res
39
}
40
41
function pypos2jspos(s, pypos){
42
// convert Python position to JS position
43
if(s.surrogates === undefined){
44
return pypos
45
}
46
var nb = 0
47
while(s.surrogates[nb] < pypos){
48
nb++
49
}
50
return pypos + nb
str
Feb 10, 2018
53
var str = {
Mar 19, 2018
54
__class__: _b_.type,
55
__dir__: _b_.object.__dir__,
56
$infos: {
57
__module__: "builtins",
58
__name__: "str"
59
},
str
Feb 10, 2018
60
$is_class: true,
Mar 19, 2018
61
$native: true
Sep 5, 2014
62
}
63
65
if(typeof $.self == "string"){
66
$.self = $B.String($.self)
67
}
68
var len = str.__len__($.self)
69
if($.start === null || $.start === _b_.None){
70
$.start = 0
71
}else if($.start < 0){
72
$.start += len
Mar 19, 2018
73
$.start = Math.max(0, $.start)
74
}
75
if($.end === null || $.end === _b_.None){
76
$.end = len
77
}else if($.end < 0){
78
$.end += len
Mar 19, 2018
79
$.end = Math.max(0, $.end)
80
}
82
if(! _b_.isinstance($.start, _b_.int) || ! _b_.isinstance($.end, _b_.int)){
Mar 19, 2018
83
throw _b_.TypeError.$factory("slice indices must be integers " +
84
"or None or have an __index__ method")
85
}
86
$.js_start = pypos2jspos($.self, $.start)
87
$.js_end = pypos2jspos($.self, $.end)
90
function reverse(s){
91
// Reverse a string
Mar 19, 2018
92
return s.split("").reverse().join("")
93
}
94
95
function check_str(obj, prefix){
Mar 19, 2018
96
if(! _b_.isinstance(obj, str)){
97
throw _b_.TypeError.$factory((prefix || '') +
98
"must be str, not " + $B.class_name(obj))
Mar 19, 2018
99
}
102
function to_chars(s){
103
// Transform Javascript string s into a list of Python characters
104
// (2 JS chars if surrogate, 1 otherwise)
105
var chars = []
106
for(var i = 0, len = s.length; i < len; i++){
107
var code = s.charCodeAt(i)
108
if(code >= 0xD800 && code <= 0xDBFF){
109
chars.push(s.substr(i, 2))
110
i++
111
}else{
112
chars.push(s.charAt(i))
113
}
114
}
115
return chars
116
}
117
118
function to_codepoints(s){
119
// Transform Javascript string s into a list of codepoints
120
if(s.codepoints){
121
return s.codepoints
122
}
123
var cps = []
124
for(var i = 0, len = s.length; i < len; i++){
125
var code = s.charCodeAt(i)
126
if(code >= 0xD800 && code <= 0xDBFF){
127
var v = 0x10000
128
v += (code & 0x03FF) << 10
129
v += (s.charCodeAt(i + 1) & 0x03FF)
130
cps.push(v)
131
i++
132
}else{
133
cps.push(code)
134
}
135
}
136
return s.codepoints = cps
137
}
138
139
str.__add__ = function(self, other){
140
if(! _b_.isinstance(other, str)){
141
try{
142
return $B.$getattr(other, "__radd__")(self)
143
}catch(err){
Mar 19, 2018
144
throw _b_.TypeError.$factory("Can't convert " +
145
$B.class_name(other) + " to str implicitly")}
Sep 5, 2014
146
}
147
return $B.String(self + other)
Sep 5, 2014
148
}
149
Mar 19, 2018
150
str.__contains__ = function(self, item){
151
if(! _b_.isinstance(item, str)){
Mar 19, 2018
152
throw _b_.TypeError.$factory("'in <string>' requires " +
153
"string as left operand, not " + item.__class__)
154
}
155
if(item.__class__ === str || _b_.isinstance(item, str)){
156
var nbcar = item.length
157
}else{
158
var nbcar = _b_.len(item)
159
}
160
if(nbcar == 0){
161
// a string contains the empty string
162
return true
163
}
164
var len = self.length
165
if(len == 0){
Mar 19, 2018
168
for(var i = 0, len = self.length; i < len; i++){
169
if(self.substr(i, nbcar) == item){
170
return true
171
}
Sep 5, 2014
172
}
173
return false
174
}
175
str
Feb 10, 2018
176
str.__delitem__ = function(){
177
throw _b_.TypeError.$factory("'str' object doesn't support item deletion")
Sep 5, 2014
178
}
179
Mar 19, 2018
180
// __dir__must be assigned explicitely because attribute resolution for
181
// builtin classes doesn't use __mro__
182
str.__dir__ = _b_.object.__dir__
184
str.__eq__ = function(self, other){
Mar 23, 2018
185
if(_b_.isinstance(other, _b_.str)){
186
return other.valueOf() == self.valueOf()
187
}
188
return _b_.NotImplemented
Sep 5, 2014
189
}
190
191
function preformat(self, fmt){
str
Feb 10, 2018
192
if(fmt.empty){return _b_.str.$factory(self)}
Mar 19, 2018
193
if(fmt.type && fmt.type != "s"){
194
throw _b_.ValueError.$factory("Unknown format code '" + fmt.type +
195
"' for object of type 'str'")
197
return self
198
}
199
str
Feb 10, 2018
200
str.__format__ = function(self, format_spec) {
201
var fmt = new $B.parse_format_spec(format_spec)
Mar 19, 2018
202
if(fmt.sign !== undefined){
203
throw _b_.ValueError.$factory(
204
"Sign not allowed in string format specifier")
206
if(fmt.precision){
207
self = self.substr(0, fmt.precision)
208
}
209
// For strings, alignment default to left
Mar 19, 2018
210
fmt.align = fmt.align || "<"
211
return $B.format_width(preformat(self, fmt), fmt)
Sep 5, 2014
212
}
213
214
str.__getitem__ = function(self, arg){
215
var len = str.__len__(self)
216
if(_b_.isinstance(arg, _b_.int)){
Sep 5, 2014
217
var pos = arg
219
pos += len
221
if(pos >= 0 && pos < len){
222
var jspos = pypos2jspos(self, pos)
223
if(self.codePointAt(jspos) >= 0x10000){
224
return $B.String(self.substr(jspos, 2))
225
}else{
226
return $B.String(self[jspos])
227
}
Mar 19, 2018
229
throw _b_.IndexError.$factory("string index out of range")
230
}
231
if(_b_.isinstance(arg, _b_.slice)){
232
var s = _b_.slice.$conv_for_seq(arg, len),
233
start = pypos2jspos(self, s.start),
234
stop = pypos2jspos(self, s.stop),
Mar 19, 2018
235
step = s.step
236
var res = "",
Mar 19, 2018
237
i = null
Mar 19, 2018
238
if(step > 0){
239
if(stop <= start){
240
return ""
241
}
242
for(var i = start; i < stop; i += step){
243
res += self[i]
Mar 23, 2018
245
}else{
246
if(stop >= start){
247
return ''
248
}
249
for(var i = start; i > stop; i += step){
250
res += self[i]
253
return $B.String(res)
Sep 5, 2014
254
}
255
if(_b_.isinstance(arg, _b_.bool)){
256
return self.__getitem__(_b_.int.$factory(arg))
257
}
Mar 19, 2018
258
throw _b_.TypeError.$factory("string indices must be integers")
Sep 5, 2014
259
}
260
261
var prefix = 2,
262
suffix = 3,
Jun 12, 2020
263
mask = (2 ** 32 - 1),
264
str_hash_cache = {}
265
266
str.$nb_str_hash_cache = 0
Jun 12, 2020
267
268
function fnv(p){
269
if(p.length == 0){
270
return 0
271
}
Sep 5, 2014
272
273
var x = prefix
274
x = (x ^ (p[0] << 7)) & mask
275
for(var i = 0, len = p.length; i < len; i++){
276
x = ((1000003 * x) ^ p[i]) & mask
277
}
278
x = (x ^ p.length) & mask
279
x = (x ^ suffix) & mask
Sep 5, 2014
280
281
if(x == -1){
282
x = -2
283
}
284
return x
285
}
287
str.__hash__ = function(self) {
Jun 12, 2020
288
if(str_hash_cache[self] !== undefined){
289
return str_hash_cache[self]
290
}
291
str.$nb_str_hash_cache++
292
if(str.$nb_str_hash_cache > 100000){
293
// Avoid memory overflow
294
str.$nb_str_hash_cache = 0
295
str_hash_cache = {}
296
}
297
try{
298
return str_hash_cache[self] = fnv(to_codepoints(self))
299
}catch(err){
300
console.log('error hash, cps', self, to_codepoints(self))
301
throw err
302
}
Sep 5, 2014
303
}
304
Mar 19, 2018
305
str.__init__ = function(self, arg){
Sep 5, 2014
306
self.valueOf = function(){return arg}
307
self.toString = function(){return arg}
Sep 5, 2014
309
}
310
311
var str_iterator = $B.make_iterator_class("str_iterator")
str
Feb 10, 2018
312
str.__iter__ = function(self){
313
return str_iterator.$factory(to_chars(self))
Sep 5, 2014
314
}
315
316
str.__len__ = function(self){
317
if(self.surrogates === undefined){
318
return self.length
320
if(self.len !== undefined){
321
return self.len
322
}
323
var len = self.len = self.valueOf().length - self.surrogates.length
324
return len
Sep 5, 2014
326
327
// Start of section for legacy formatting (with %)
328
Mar 19, 2018
329
var kwarg_key = new RegExp("([^\\)]*)\\)")
330
331
var NotANumber = function() {
Mar 19, 2018
332
this.name = "NotANumber"
333
}
334
Mar 19, 2018
335
var number_check = function(s){
336
if(! _b_.isinstance(s, [_b_.int, _b_.float])){
337
throw new NotANumber()
338
}
339
}
340
Mar 19, 2018
341
var get_char_array = function(size, char){
342
if(size <= 0){
343
return ""
344
}
345
return new Array(size + 1).join(char)
346
}
347
Mar 19, 2018
348
var format_padding = function(s, flags, minus_one){
349
var padding = flags.padding
Mar 23, 2018
350
if(! padding){ // undefined
351
return s
352
}
353
s = s.toString()
354
padding = parseInt(padding, 10)
Mar 23, 2018
355
if(minus_one){ // numeric formatting where sign goes in front of padding
356
padding -= 1
357
}
Mar 19, 2018
358
if(! flags.left){
359
return get_char_array(padding - s.length, flags.pad_char) + s
Mar 19, 2018
360
}else{
361
// left adjusted
362
return s + get_char_array(padding - s.length, flags.pad_char)
363
}
364
}
365
Mar 19, 2018
366
var format_int_precision = function(val, flags){
367
var precision = flags.precision
Mar 19, 2018
368
if(!precision){
369
return val.toString()
370
}
371
precision = parseInt(precision, 10)
Mar 19, 2018
373
if(val.__class__ === $B.long_int){
374
s = $B.long_int.to_base(val, 10)
375
}else{
376
s = val.toString()
Mar 19, 2018
378
if(s[0] === "-"){
379
return "-" + get_char_array(precision - s.length + 1, "0") + s.slice(1)
Mar 19, 2018
381
return get_char_array(precision - s.length, "0") + s
382
}
383
Mar 19, 2018
384
var format_float_precision = function(val, upper, flags, modifier){
385
var precision = flags.precision
386
// val is a float
Mar 19, 2018
387
if(isFinite(val)){
388
return modifier(val, precision, flags, upper)
Mar 19, 2018
390
if(val === Infinity){
391
val = "inf"
392
}else if(val === -Infinity){
393
val = "-inf"
394
}else{
395
val = "nan"
Mar 19, 2018
397
if(upper){
398
return val.toUpperCase()
399
}
400
return val
402
}
403
Mar 19, 2018
404
var format_sign = function(val, flags){
405
if(flags.sign){
406
if(val >= 0){
407
return "+"
Sep 5, 2014
408
}
Mar 19, 2018
409
}else if (flags.space){
410
if(val >= 0){
411
return " "
412
}
413
}
414
return ""
415
}
Sep 5, 2014
416
417
var str_format = function(val, flags) {
418
// string format supports left and right padding
419
flags.pad_char = " " // even if 0 padding is defined, don't use it
str
Feb 10, 2018
420
return format_padding(str.$factory(val), flags)
Sep 5, 2014
422
423
var num_format = function(val, flags) {
424
number_check(val)
Mar 19, 2018
425
if(val.__class__ === $B.long_int){
426
val = $B.long_int.to_base(val, 10)
427
}else{
428
val = parseInt(val)
431
var s = format_int_precision(val, flags)
Mar 19, 2018
432
if(flags.pad_char === "0"){
433
if(val < 0){
434
s = s.substring(1)
Mar 19, 2018
435
return "-" + format_padding(s, flags, true)
436
}
437
var sign = format_sign(val, flags)
Mar 19, 2018
438
if(sign !== ""){
439
return sign + format_padding(s, flags, true)
440
}
441
}
443
return format_padding(format_sign(val, flags) + s, flags)
444
}
Sep 5, 2014
445
446
var repr_format = function(val, flags) {
447
flags.pad_char = " " // even if 0 padding is defined, don't use it
448
return format_padding(_b_.repr(val), flags)
Sep 5, 2014
450
451
var ascii_format = function(val, flags) {
452
flags.pad_char = " " // even if 0 padding is defined, don't use it
453
return format_padding(_b_.ascii(val), flags)
Sep 5, 2014
455
456
// converts val to float and sets precision if missing
Mar 19, 2018
457
var _float_helper = function(val, flags){
458
number_check(val)
Mar 19, 2018
459
if(! flags.precision){
460
if(! flags.decimal_point){
461
flags.precision = 6
Mar 19, 2018
462
}else{
463
flags.precision = 0
464
}
Mar 19, 2018
465
}else{
466
flags.precision = parseInt(flags.precision, 10)
467
validate_precision(flags.precision)
468
}
469
return parseFloat(val)
470
}
Sep 5, 2014
471
472
// used to capture and remove trailing zeroes
Mar 19, 2018
473
var trailing_zeros = /(.*?)(0+)([eE].*)/,
474
leading_zeros = /\.(0*)/,
475
trailing_dot = /\.$/
Sep 5, 2014
476
477
var validate_precision = function(precision) {
478
// force precision to limits of javascript
Mar 19, 2018
479
if(precision > 20){precision = 20}
480
}
481
482
// gG
Mar 19, 2018
483
var floating_point_format = function(val, upper, flags){
484
val = _float_helper(val, flags),
485
v = val.toString(),
486
v_len = v.length,
487
dot_idx = v.indexOf('.')
488
if(dot_idx < 0){dot_idx = v_len}
489
if(val < 1 && val > -1){
490
var zeros = leading_zeros.exec(v),
491
numzeros
492
if(zeros){
493
numzeros = zeros[1].length
Mar 19, 2018
494
}else{
495
numzeros = 0
496
}
Mar 19, 2018
497
if(numzeros >= 4){
498
val = format_sign(val, flags) + format_float_precision(val, upper,
499
flags, _floating_g_exp_helper)
500
if(!flags.alternate){
501
var trl = trailing_zeros.exec(val)
Mar 19, 2018
502
if(trl){
503
val = trl[1].replace(trailing_dot, "") + trl[3] // remove trailing
Mar 19, 2018
505
}else{
506
if(flags.precision <= 1){
507
val = val[0] + "." + val.substring(1)
509
}
510
return format_padding(val, flags)
511
}
512
flags.precision = (flags.precision || 0) + numzeros
Mar 19, 2018
513
return format_padding(format_sign(val, flags) +
514
format_float_precision(val, upper, flags,
515
function(val, precision) {
516
return val.toFixed(_b_.min(precision, v_len - dot_idx) +
Mar 19, 2018
517
numzeros)
518
}),
519
flags
520
)
521
}
522
523
if(dot_idx > flags.precision){
524
val = format_sign(val, flags) + format_float_precision(val, upper,
525
flags, _floating_g_exp_helper)
526
if(! flags.alternate){
527
var trl = trailing_zeros.exec(val)
Mar 19, 2018
528
if(trl){
529
val = trl[1].replace(trailing_dot, "") + trl[3] // remove trailing
Mar 19, 2018
531
}else{
532
if(flags.precision <= 1){
533
val = val[0] + "." + val.substring(1)
534
}
535
}
536
return format_padding(val, flags)
537
}
Mar 19, 2018
538
return format_padding(format_sign(val, flags) +
539
format_float_precision(val, upper, flags,
540
function(val, precision) {
541
if(!flags.decimal_point){
542
precision = _b_.min(v_len - 1, 6)
Mar 19, 2018
543
}else if (precision > v_len){
544
if(! flags.alternate){
545
precision = v_len
546
}
Sep 5, 2014
547
}
Mar 19, 2018
548
if(precision < dot_idx){
549
precision = dot_idx
550
}
551
return val.toFixed(precision - dot_idx)
552
}),
553
flags
554
)
Sep 5, 2014
556
Mar 19, 2018
557
var _floating_g_exp_helper = function(val, precision, flags, upper){
558
if(precision){--precision}
559
val = val.toExponential(precision)
560
// pad exponent to two digits
Mar 19, 2018
561
var e_idx = val.lastIndexOf("e")
562
if(e_idx > val.length - 4){
563
val = val.substring(0, e_idx + 2) + "0" + val.substring(e_idx + 2)
Mar 19, 2018
565
if(upper){return val.toUpperCase()}
566
return val
567
}
568
569
// fF
570
var floating_point_decimal_format = function(val, upper, flags) {
571
val = _float_helper(val, flags)
Mar 19, 2018
572
return format_padding(format_sign(val, flags) +
573
format_float_precision(val, upper, flags,
574
function(val, precision, flags) {
575
val = val.toFixed(precision)
576
if(precision === 0 && flags.alternate){
577
val += '.'
578
}
579
return val
580
}),
581
flags
582
)
583
}
584
585
var _floating_exp_helper = function(val, precision, flags, upper) {
586
val = val.toExponential(precision)
587
// pad exponent to two digits
Mar 19, 2018
588
var e_idx = val.lastIndexOf("e")
Mar 23, 2018
589
if(e_idx > val.length - 4){
Mar 19, 2018
590
val = val.substring(0, e_idx + 2) + "0" + val.substring(e_idx + 2)
Mar 19, 2018
592
if(upper){return val.toUpperCase()}
593
return val
594
}
595
596
// eE
Mar 19, 2018
597
var floating_point_exponential_format = function(val, upper, flags){
598
val = _float_helper(val, flags)
Mar 19, 2018
600
return format_padding(format_sign(val, flags) +
601
format_float_precision(val, upper, flags, _floating_exp_helper), flags)
602
}
603
Mar 19, 2018
604
var signed_hex_format = function(val, upper, flags){
606
number_check(val)
Mar 23, 2018
608
if(val.__class__ === $B.long_int){
Mar 19, 2018
609
ret = $B.long_int.to_base(val, 16)
610
}else{
611
ret = parseInt(val)
612
ret = ret.toString(16)
613
}
614
ret = format_int_precision(ret, flags)
Mar 19, 2018
615
if(upper){ret = ret.toUpperCase()}
Mar 23, 2018
616
if(flags.pad_char === "0"){
Mar 19, 2018
617
if(val < 0){
618
ret = ret.substring(1)
Mar 19, 2018
619
ret = "-" + format_padding(ret, flags, true)
620
}
621
var sign = format_sign(val, flags)
Mar 19, 2018
622
if(sign !== ""){
623
ret = sign + format_padding(ret, flags, true)
Sep 5, 2014
624
}
Mar 19, 2018
627
if(flags.alternate){
628
if(ret.charAt(0) === "-"){
629
if(upper){ret = "-0X" + ret.slice(1)}
630
else{ret = "-0x" + ret.slice(1)}
631
}else{
632
if(upper){ret = "0X" + ret}
633
else{ret = "0x" + ret}
634
}
635
}
636
return format_padding(format_sign(val, flags) + ret, flags)
637
}
Sep 5, 2014
638
639
var octal_format = function(val, flags) {
640
number_check(val)
Mar 19, 2018
643
if(val.__class__ === $B.long_int){
644
ret = $B.long_int.to_base(8)
645
}else{
646
ret = parseInt(val)
647
ret = ret.toString(8)
650
ret = format_int_precision(ret, flags)
Mar 19, 2018
652
if(flags.pad_char === "0"){
653
if(val < 0){
654
ret = ret.substring(1)
Mar 19, 2018
655
ret = "-" + format_padding(ret, flags, true)
656
}
657
var sign = format_sign(val, flags)
Mar 19, 2018
658
if(sign !== ""){
659
ret = sign + format_padding(ret, flags, true)
660
}
Sep 5, 2014
661
}
Mar 19, 2018
663
if(flags.alternate){
664
if(ret.charAt(0) === "-"){ret = "-0o" + ret.slice(1)}
665
else{ret = "0o" + ret}
Sep 5, 2014
666
}
667
return format_padding(ret, flags)
668
}
669
670
function series_of_bytes(val, flags){
671
if(val.__class__ && val.__class__.$buffer_protocol){
672
var it = _b_.iter(val),
673
ints = []
674
while(true){
675
try{
676
ints.push(_b_.next(it))
677
}catch(err){
678
if(err.__class__ === _b_.StopIteration){
679
var b = _b_.bytes.$factory(ints)
680
return format_padding(_b_.bytes.decode(b, "ascii"), flags)
681
}
682
throw err
683
}
684
}
685
}else{
686
try{
687
bytes_obj = $B.$getattr(val, "__bytes__")
688
return format_padding(_b_.bytes.decode(bytes_obj), flags)
689
}catch(err){
690
if(err.__class__ === _b_.AttributeError){
691
throw _b_.TypeError.$factory("%b does not accept '" +
692
$B.class_name(val) + "'")
693
}
694
throw err
695
}
696
}
697
}
698
Mar 19, 2018
699
var single_char_format = function(val, flags){
700
if(_b_.isinstance(val, str) && val.length == 1){
702
}else if(_b_.isinstance(val, _b_.bytes) && val.source.length == 1){
703
val = val.source[0]
704
}else{
705
try{
706
val = _b_.int.$factory(val) // yes, floats are valid (they are cast to int)
707
}catch (err){
708
throw _b_.TypeError.$factory("%c requires int or char")
709
}
711
return format_padding(_b_.chr(val), flags)
712
}
713
Mar 19, 2018
714
var num_flag = function(c, flags){
715
if(c === "0" && ! flags.padding && ! flags.decimal_point && ! flags.left){
716
flags.pad_char = "0"
717
return
718
}
Mar 19, 2018
719
if(!flags.decimal_point){
720
flags.padding = (flags.padding || "") + c
Mar 19, 2018
721
}else{
722
flags.precision = (flags.precision || "") + c
723
}
724
}
725
726
var decimal_point_flag = function(val, flags) {
Mar 23, 2018
727
if(flags.decimal_point){
728
// can only have one decimal point
729
throw new UnsupportedChar()
730
}
731
flags.decimal_point = true
732
}
733
Mar 19, 2018
734
var neg_flag = function(val, flags){
735
flags.pad_char = " " // overrides '0' flag
736
flags.left = true
737
}
738
Mar 19, 2018
739
var space_flag = function(val, flags){
740
flags.space = true
741
}
742
Mar 19, 2018
743
var sign_flag = function(val, flags){
744
flags.sign = true
745
}
746
Mar 19, 2018
747
var alternate_flag = function(val, flags){
748
flags.alternate = true
749
}
750
751
var char_mapping = {
Mar 19, 2018
753
"s": str_format,
754
"d": num_format,
755
"i": num_format,
756
"u": num_format,
757
"o": octal_format,
758
"r": repr_format,
759
"a": ascii_format,
760
"g": function(val, flags){
761
return floating_point_format(val, false, flags)
762
},
763
"G": function(val, flags){return floating_point_format(val, true, flags)},
764
"f": function(val, flags){
765
return floating_point_decimal_format(val, false, flags)
766
},
767
"F": function(val, flags){
768
return floating_point_decimal_format(val, true, flags)
769
},
770
"e": function(val, flags){
771
return floating_point_exponential_format(val, false, flags)
772
},
773
"E": function(val, flags){
774
return floating_point_exponential_format(val, true, flags)
775
},
776
"x": function(val, flags){return signed_hex_format(val, false, flags)},
777
"X": function(val, flags){return signed_hex_format(val, true, flags)},
778
"c": single_char_format,
779
"0": function(val, flags){return num_flag("0", flags)},
780
"1": function(val, flags){return num_flag("1", flags)},
781
"2": function(val, flags){return num_flag("2", flags)},
782
"3": function(val, flags){return num_flag("3", flags)},
783
"4": function(val, flags){return num_flag("4", flags)},
784
"5": function(val, flags){return num_flag("5", flags)},
785
"6": function(val, flags){return num_flag("6", flags)},
786
"7": function(val, flags){return num_flag("7", flags)},
787
"8": function(val, flags){return num_flag("8", flags)},
788
"9": function(val, flags){return num_flag("9", flags)},
789
"-": neg_flag,
790
" ": space_flag,
791
"+": sign_flag,
792
".": decimal_point_flag,
793
"#": alternate_flag
794
}
795
796
// exception thrown when an unsupported char is encountered in legacy format
Mar 19, 2018
797
var UnsupportedChar = function(){
798
this.name = "UnsupportedChar"
799
}
800
801
str.__mod__ = function(self, args){
802
var length = self.length,
Mar 19, 2018
803
pos = 0 | 0,
804
argpos = null,
805
getitem
Mar 19, 2018
806
if(_b_.isinstance(args, _b_.tuple)){
807
argpos = 0 | 0
809
getitem = $B.$getattr(args, "__getitem__", _b_.None)
810
}
811
var ret = ''
812
var $get_kwarg_string = function(s) {
813
// returns [self, newpos]
814
++pos
815
var rslt = kwarg_key.exec(s.substring(newpos))
Mar 19, 2018
816
if(! rslt){
817
throw _b_.ValueError.$factory("incomplete format key")
818
}
819
var key = rslt[1]
820
newpos += rslt[0].length
Mar 23, 2018
821
try{
822
var self = getitem(key)
Mar 19, 2018
823
}catch(err){
824
if(err.__class__ === _b_.KeyError){
825
throw err
826
}
827
throw _b_.TypeError.$factory("format requires a mapping")
829
return get_string_value(s, self)
830
}
831
832
var $get_arg_string = function(s) {
833
// returns [self, newpos]
834
var self
836
// non-tuple args
Mar 19, 2018
837
if(argpos === null){
838
// args is the value
Mar 19, 2018
840
}else{
841
self = args[argpos++]
Mar 19, 2018
842
if(self === undefined){
843
throw _b_.TypeError.$factory(
844
"not enough arguments for format string")
Sep 5, 2014
845
}
846
}
847
return get_string_value(s, self)
849
var get_string_value = function(s, self) {
850
// todo: get flags, type
851
// todo: string value based on flags, type, value
Mar 19, 2018
852
var flags = {"pad_char": " "}
853
do{
854
var func = char_mapping[s[newpos]]
Mar 23, 2018
855
try{
Mar 19, 2018
856
if(func === undefined){
857
throw new UnsupportedChar()
Mar 19, 2018
858
}else{
859
var ret = func(self, flags)
Mar 19, 2018
860
if(ret !== undefined){
861
return ret
862
}
863
++newpos
864
}
Mar 19, 2018
865
}catch (err){
866
if(err.name == "UnsupportedChar"){
867
invalid_char = s[newpos]
Mar 19, 2018
868
if(invalid_char === undefined){
869
throw _b_.ValueError.$factory("incomplete format")
Mar 19, 2018
871
throw _b_.ValueError.$factory(
872
"unsupported format character '" + invalid_char +
873
"' (0x" + invalid_char.charCodeAt(0).toString(16) +
874
") at index " + newpos)
875
}else if(err.name === "NotANumber"){
876
var try_char = s[newpos],
877
cls = self.__class__
878
if(!cls){
879
if(typeof(self) === "string"){
880
cls = "str"
881
}else{
882
cls = typeof(self)
Mar 19, 2018
884
}else{
Mar 19, 2018
887
throw _b_.TypeError.$factory("%" + try_char +
888
" format: a number is required, not " + cls)
889
}else{
890
throw err
891
}
Sep 5, 2014
892
}
Mar 19, 2018
893
}while (true)
Sep 5, 2014
894
}
895
var nbph = 0 // number of placeholders
Mar 19, 2018
896
do{
897
var newpos = self.indexOf("%", pos)
898
if(newpos < 0){
899
ret += self.substring(pos)
900
break
901
}
902
ret += self.substring(pos, newpos)
903
++newpos
Mar 19, 2018
904
if(newpos < length){
905
if(self[newpos] === "%"){
906
ret += "%"
907
}else{
Mar 19, 2018
909
if(self[newpos] === "("){
910
++newpos
911
ret += $get_kwarg_string(self)
Mar 23, 2018
912
}else{
913
ret += $get_arg_string(self)
914
}
915
}
Mar 19, 2018
916
}else{
917
// % at end of string
918
throw _b_.ValueError.$factory("incomplete format")
919
}
920
pos = newpos + 1
Mar 19, 2018
921
}while(pos < length)
922
923
if(argpos !== null){
924
if(args.length > argpos){
925
throw _b_.TypeError.$factory(
926
"not enough arguments for format string")
927
}else if(args.length < argpos){
928
throw _b_.TypeError.$factory(
929
"not all arguments converted during string formatting")
Mar 19, 2018
931
}else if(nbph == 0){
932
throw _b_.TypeError.$factory(
933
"not all arguments converted during string formatting")
Sep 5, 2014
937
Sep 5, 2014
939
str
Feb 10, 2018
940
str.__mul__ = function(){
Mar 19, 2018
941
var $ = $B.args("__mul__", 2, {self: null, other: null},
942
["self", "other"], arguments, {}, null, null)
943
if(! _b_.isinstance($.other, _b_.int)){throw _b_.TypeError.$factory(
Mar 19, 2018
944
"Can't multiply sequence by non-int of type '" +
946
return $.self.valueOf().repeat($.other)
Sep 5, 2014
947
}
948
949
str.__ne__ = function(self, other){
950
return other.valueOf() !== self.valueOf()
Sep 5, 2014
952
953
function __newobj__(){
954
// __newobj__ is called with a generator as only argument
955
var $ = $B.args('__newobj__', 0, {}, [], arguments, {}, 'args', null),
956
args = $.args
957
var res = args[1]
958
res.__class__ = args[0]
959
return res
960
}
961
962
str.__reduce_ex__ = function(self){
963
return $B.fast_tuple([
964
__newobj__,
965
$B.fast_tuple([self.__class__ || _b_.str, self]),
966
_b_.None,
967
_b_.None])
968
}
969
str
Feb 10, 2018
970
str.__repr__ = function(self){
972
var t = {
973
8: "\\x08",
974
9: "\\t",
975
10: "\\n",
976
11: "\\x0b",
977
12: "\\x0c",
978
13: "\\r",
979
92: "\\\\"
980
}
981
var repl = '',
982
chars = to_chars(self)
983
for(var i = 0; i < chars.length; i++){
984
var cp = _b_.ord(chars[i])
985
if(t[cp] !== undefined){
986
repl += t[cp]
987
}else if($B.is_unicode_cn(cp)){
988
var s = cp.toString(16)
989
while(s.length < 4){
990
s = '0' + s
991
}
992
repl += '\\u' + s
993
}else if(cp < 0x20 || (cp >= 0x7f && cp < 0xa0)){
994
cp = cp.toString(16)
995
if(cp.length < 2){
996
cp = '0' + cp
997
}
998
repl += '\\x' + cp
999
}else if(cp >= 0x300 && cp <= 0x36F){
1000
repl += "\u200B" + chars[i]
Mar 19, 2018
1006
if(res.search('"') == -1 && res.search("'") == -1){
1007
return "'" + res + "'"
1008
}else if(self.search('"') == -1){
1009
return '"' + res + '"'
1010
}
1011
var qesc = new RegExp("'", "g") // to escape single quote
1012
res = "'" + res.replace(qesc, "\\'") + "'"
Sep 5, 2014
1013
return res
1014
}
1015
1016
str.__rmul__ = function(self, other){
1017
if(_b_.isinstance(other, _b_.int)){
1018
other = _b_.int.numerator(other)
1019
var res = ''
1020
while(other > 0){
1021
res += self
1022
other--
1023
}
1024
return res
1025
}
1026
return _b_.NotImplemented
1027
}
1028
1029
str.__setattr__ = function(self, attr, value){
1030
if(typeof self === "string"){
1031
if(str.hasOwnProperty(attr)){
1032
throw _b_.AttributeError.$factory("'str' object attribute '" +
1033
attr + "' is read-only")
1034
}else{
1035
throw _b_.AttributeError.$factory(
1036
"'str' object has no attribute '" + attr + "'")
1037
}
1038
}
1039
// str subclass : use __dict__
1040
_b_.dict.$setitem(self.__dict__, attr, value)
1041
return $N
1042
}
1043
Mar 19, 2018
1044
str.__setitem__ = function(self, attr, value){
1045
throw _b_.TypeError.$factory(
1046
"'str' object does not support item assignment")
Sep 5, 2014
1047
}
Mar 27, 2019
1049
var combining = []
1050
for(var cp = 0x300; cp <= 0x36F; cp++){
1051
combining.push(String.fromCharCode(cp))
1052
}
1053
var combining_re = new RegExp("(" + combining.join("|") + ")", "g")
str
Feb 10, 2018
1055
str.__str__ = function(self){
1056
var repl = '',
1057
chars = to_chars(self)
1058
if(chars.length == self.length){
1059
return self.replace(combining_re, "\u200B$1")
1060
}
1061
for(var i = 0; i < chars.length; i++){
1062
var cp = _b_.ord(chars[i])
1063
if(cp >= 0x300 && cp <= 0x36F){
1064
repl += "\u200B" + chars[i]
1065
}else{
1066
repl += chars[i]
1067
}
1068
}
1069
return repl
Sep 5, 2014
1070
}
Mar 19, 2018
1072
str.toString = function(){return "string!"}
Sep 5, 2014
1073
1074
// generate comparison methods
1075
var $comp_func = function(self,other){
1076
if(typeof other !== "string"){return _b_.NotImplemented}
Sep 5, 2014
1077
return self > other
1078
}
Mar 19, 2018
1079
$comp_func += "" // source code
1080
var $comps = {">": "gt", ">=": "ge", "<": "lt", "<=": "le"}
Sep 5, 2014
1081
for(var $op in $comps){
Mar 19, 2018
1082
eval("str.__" + $comps[$op] + '__ = ' + $comp_func.replace(/>/gm,$op))
Sep 5, 2014
1083
}
1084
1085
// unsupported operations
Mar 19, 2018
1086
var $notimplemented = function(self, other){
1087
throw _b_.NotImplementedError.$factory(
Mar 19, 2018
1088
"OPERATOR not implemented for class str")
Sep 5, 2014
1089
}
1090
1091
str.capitalize = function(self){
1092
var $ = $B.args("capitalize", 1, {self}, ["self"],
1093
arguments, {}, null, null)
1094
if(self.length == 0){
1095
return ""
1096
}
1097
return self.charAt(0).toUpperCase() + self.substr(1)
1098
}
1099
1100
str.casefold = function(self){
1101
var $ = $B.args("casefold", 1, {self}, ["self"],
1102
arguments, {}, null, null),
1103
res = "",
1104
char,
1105
cf,
1106
chars = to_chars($.self)
1107
1108
for(var i = 0, len = chars.length; i < len; i++){
1109
char = chars[i]
1110
cf = $B.unicode_casefold[char]
1111
if(cf){
1112
cf.forEach(function(cp){
1113
res += String.fromCharCode(cp)
1114
})
1115
}else{
1117
}
1118
}
1119
return res
1120
}
Sep 5, 2014
1121
Mar 19, 2018
1122
str.center = function(){
1123
var $ = $B.args("center", 3, {self: null, width: null, fillchar: null},
1124
["self", "width", "fillchar"],
1125
arguments, {fillchar:" "}, null, null),
1126
self = $.self
Mar 19, 2018
1128
if($.width <= self.length) {return self}
Mar 19, 2018
1130
var pad = parseInt(($.width - self.length) / 2),
1131
res = $.fillchar.repeat(pad)
Sep 5, 2014
1132
res += self + res
1133
if(res.length < $.width){
1134
res += $.fillchar
1135
}
Sep 5, 2014
1136
return res
1137
}
1138
str
Feb 10, 2018
1139
str.count = function(){
Mar 19, 2018
1140
var $ = $B.args("count", 4, {self:null, sub:null, start:null, stop:null},
1141
["self", "sub", "start", "stop"], arguments, {start:null, stop:null},
1143
if(!(typeof $.sub.valueOf() == "string")){
1144
throw _b_.TypeError.$factory("Can't convert '" + $B.class_name($.sub) +
1145
"' object to str implicitly")
1146
}
Mar 19, 2018
1148
if($.start !== null){
1150
if($.stop !== null){
1151
_slice = _b_.slice.$factory($.start, $.stop)
1152
}else{
1153
_slice = _b_.slice.$factory($.start, $.self.length)
1154
}
str
Feb 10, 2018
1155
substr = str.__getitem__.apply(null, [$.self].concat(_slice))
1157
if($.self.length + $.sub.length == 0){
1158
return 1
1159
}
Mar 19, 2018
1161
if($.sub.length == 0){
1162
if($.start == $.self.length){
1163
return 1
1164
}else if(substr.length == 0){
1165
return 0
1166
}
Mar 19, 2018
1167
return substr.length + 1
Mar 19, 2018
1169
var n = 0,
1170
pos = 0
1171
while(pos < substr.length){
1172
pos = substr.indexOf($.sub, pos)
1173
if(pos >= 0){
1174
n++
1175
pos += $.sub.length
1176
}else{
1177
break
1178
}
Sep 5, 2014
1179
}
1180
return n
1181
}
1182
1183
str.encode = function(){
1184
var $ = $B.args("encode", 3, {self: null, encoding: null, errors: null},
1185
["self", "encoding", "errors"], arguments,
1186
{encoding: "utf-8", errors: "strict"}, null, null)
1187
if($.encoding == "rot13" || $.encoding == "rot_13"){
1188
// Special case : returns a string
Mar 19, 2018
1189
var res = ""
1190
for(var i = 0, len = $.self.length; i < len ; i++){
1191
var char = $.self.charAt(i)
Mar 19, 2018
1192
if(("a" <= char && char <= "m") || ("A" <= char && char <= "M")){
1193
res += String.fromCharCode(String.charCodeAt(char) + 13)
1194
}else if(("m" < char && char <= "z") ||
1195
("M" < char && char <= "Z")){
1196
res += String.fromCharCode(String.charCodeAt(char) - 13)
1197
}else{res += char}
1198
}
1199
return res
1200
}
1201
return _b_.bytes.__new__(_b_.bytes, $.self, $.encoding, $.errors)
Sep 5, 2014
1202
}
1203
str
Feb 10, 2018
1204
str.endswith = function(){
1205
// Return True if the string ends with the specified suffix, otherwise
1206
// return False. suffix can also be a tuple of suffixes to look for.
1207
// With optional start, test beginning at that position. With optional
Sep 5, 2014
1208
// end, stop comparing at that position.
Mar 19, 2018
1209
var $ = $B.args("endswith", 4,
1210
{self:null, suffix:null, start:null, end:null},
Mar 19, 2018
1211
["self", "suffix", "start", "end"],
1212
arguments, {start: 0, end: null}, null, null)
Sep 20, 2015
1213
1214
normalize_start_end($)
1215
1216
var suffixes = $.suffix
1217
if(! _b_.isinstance(suffixes,_b_.tuple)){
1218
suffixes = [suffixes]
1219
}
1221
var chars = to_chars($.self),
1222
s = chars.slice($.start, $.end)
Mar 19, 2018
1223
for(var i = 0, len = suffixes.length; i < len; i++){
1224
var suffix = suffixes[i]
1225
if(! _b_.isinstance(suffix, str)){
1226
throw _b_.TypeError.$factory(
1227
"endswith first arg must be str or a tuple of str, not int")
1228
}
Mar 19, 2018
1229
if(suffix.length <= s.length &&
1230
s.slice(s.length - suffix.length).join('') == suffix){
1231
return true
1232
}
Sep 5, 2014
1233
}
1234
return false
1235
}
1236
str
Feb 10, 2018
1237
str.expandtabs = function(self, tabsize) {
Mar 19, 2018
1238
var $ = $B.args("expandtabs", 2, {self: null, tabsize: null},
1239
["self", "tabsize"], arguments, {tabsize: 8}, null, null)
1240
var s = $B.$GetInt($.tabsize),
1241
col = 0,
1242
pos = 0,
1243
res = "",
1244
chars = to_chars(self)
1245
if(s == 1){
1246
return self.replace(/\t/g," ")
1247
}
1248
while(pos < chars.length){
1249
var car = chars[pos]
Mar 19, 2018
1251
case "\t":
1252
while(col % s > 0){
1253
res += " ";
1254
col++
1255
}
Mar 19, 2018
1257
case "\r":
1258
case "\n":
1259
res += car
1260
col = 0
1261
break
1262
default:
1263
res += car
1264
col++
1265
break
1266
}
1267
pos++
1268
}
1269
return res
Sep 5, 2014
1270
}
1271
str
Feb 10, 2018
1272
str.find = function(){
1273
// Return the lowest index in the string where substring sub is found,
1274
// such that sub is contained in the slice s[start:end]. Optional
1275
// arguments start and end are interpreted as in slice notation.
Sep 5, 2014
1276
// Return -1 if sub is not found.
Mar 19, 2018
1277
var $ = $B.args("str.find", 4,
1278
{self: null, sub: null, start: null, end: null},
1279
["self", "sub", "start", "end"],
1280
arguments, {start: 0, end: null}, null, null)
1281
check_str($.sub)
1284
var len = str.__len__($.self),
1285
sub_len = str.__len__($.sub)
1287
if(sub_len == 0 && $.start == len){
1290
if(len + sub_len == 0){
1294
var last_search = len - sub_len
1295
for(var i = $.start; i <= last_search; i++){
1296
var js_pos = pypos2jspos($.self, i)
1297
if($.self.substr(js_pos, $.sub.length) == $.sub){
1298
return i
Sep 5, 2014
1300
}
Sep 5, 2014
1302
}
1303
1304
// Next function used by method .format()
1305
1306
$B.parse_format = function(fmt_string){
Sep 5, 2014
1307
1308
// Parse a "format string", as described in the Python documentation
1309
// Return a format object. For the format string
1310
// a.x[z]!r:...
1311
// the object has attributes :
1312
// - name : "a"
1313
// - name_ext : [".x", "[z]"]
1314
// - conv : r
1315
// - spec : rest of string after :
Sep 5, 2014
1316
Mar 19, 2018
1317
var elts = fmt_string.split(":"),
1318
name,
1319
conv,
1320
spec,
Mar 19, 2018
1321
name_ext = []
Mar 19, 2018
1322
if(elts.length == 1){
1323
// No : in the string : it only contains a name
1324
name = fmt_string
1325
}else{
1326
// name is before the first ":"
1327
// spec (the format specification) is after
1328
name = elts[0]
Mar 19, 2018
1329
spec = elts.splice(1).join(":")
Mar 19, 2018
1332
var elts = name.split("!")
1333
if(elts.length > 1){
1334
name = elts[0]
1335
conv = elts[1] // conversion flag
Sep 5, 2014
1337
Mar 19, 2018
1338
if(name !== undefined){
1339
// "name' may be a subscription or attribute
1340
// Put these "extensions" in the list "name_ext"
1341
function name_repl(match){
1342
name_ext.push(match)
Mar 19, 2018
1343
return ""
1344
}
1345
var name_ext_re = /\.[_a-zA-Z][_a-zA-Z0-9]*|\[[_a-zA-Z][_a-zA-Z0-9]*\]|\[[0-9]+\]/g
1346
name = name.replace(name_ext_re, name_repl)
1347
}
Sep 5, 2014
1348
1349
return {name: name, name_ext: name_ext,
1350
conv: conv, spec: spec || "", string: fmt_string}
Sep 5, 2014
1352
1353
$B.split_format = function(self){
1354
// Parse self to detect formatting instructions
1355
// Create a list "parts" made of sections of the string :
1356
// - elements of even rank are literal text
1357
// - elements of odd rank are "format objects", built from the
1358
// format strings in self (of the form {...})
Mar 19, 2018
1359
var pos = 0,
1360
_len = self.length,
Mar 19, 2018
1362
text = "",
1363
parts = [],
1364
rank = 0
1365
while(pos < _len){
1366
car = self.charAt(pos)
Mar 21, 2018
1367
if(car == "{" && self.charAt(pos + 1) == "{"){
1368
// replace {{ by literal {
Mar 19, 2018
1369
text += "{"
1370
pos += 2
1371
}else if(car == "}" && self.charAt(pos + 1) == "}"){
1372
// replace }} by literal }
Mar 19, 2018
1373
text += "}"
1374
pos += 2
1375
}else if(car == "{"){
1376
// Start of a format string
1378
// Store current literal text
1379
parts.push(text)
1380
1381
// Search the end of the format string, ie the } closing the
1382
// opening {. Since the string can contain other pairs {} for
1383
// nested formatting, an integer nb is incremented for each { and
1384
// decremented for each } ; the end of the format string is
Mar 19, 2018
1385
// reached when nb == 0
1386
var end = pos + 1,
1387
nb = 1
1388
while(end < _len){
1389
if(self.charAt(end) == "{"){nb++; end++}
1390
else if(self.charAt(end) == "}"){
1391
nb--; end++
1392
if(nb == 0){
1393
// End of format string
Mar 19, 2018
1394
var fmt_string = self.substring(pos + 1, end - 1)
1395
1396
// Create a format object, by function parse_format
1397
var fmt_obj = $B.parse_format(fmt_string)
1398
fmt_obj.raw_name = fmt_obj.name
1399
fmt_obj.raw_spec = fmt_obj.spec
1400
1401
// If no name is explicitely provided, use the rank
1402
if(!fmt_obj.name){
Mar 19, 2018
1403
fmt_obj.name = rank + ""
Sep 5, 2014
1406
Mar 19, 2018
1407
if(fmt_obj.spec !== undefined){
1408
// "spec" may contain "nested replacement fields"
1409
// Replace empty fields by the rank in positional
1410
// arguments
1411
function replace_nested(name, key){
1412
if(key == ""){
1413
// Use implicit rank
1414
return "{" + rank++ + "}"
1418
fmt_obj.spec = fmt_obj.spec.replace(/\{(.*?)\}/g,
1419
replace_nested)
1420
}
1422
// Store format object in list "parts"
1423
parts.push(fmt_obj)
Mar 19, 2018
1424
text = ""
1425
break
1426
}
1427
}else{end++}
Sep 5, 2014
1428
}
1429
if(nb > 0){
1430
throw _b_.ValueError.$factory("wrong format " + self)
1431
}
1433
}else{
1434
text += car
1435
pos++
1436
}
1437
}
1438
if(text){
1439
parts.push(text)
Sep 5, 2014
1440
}
1441
return parts
1442
}
1443
1444
str.format = function(self) {
1445
// Special management of keyword arguments if str.format is called by
1446
// str.format_map(mapping) : the argument "mapping" might not be a
1447
// dictionary
1448
var last_arg = $B.last(arguments)
1449
if(last_arg.$nat == "mapping"){
1450
var mapping = last_arg.mapping,
1451
getitem = $B.$getattr(mapping, "__getitem__")
1452
// Get the rest of the arguments
1453
var args = []
1454
for(var i = 0, len = arguments.length - 1; i < len; i++){
1455
args.push(arguments[i])
1456
}
1457
var $ = $B.args("format", 1, {self: null}, ["self"],
1458
args, {}, "$args", null)
1459
}else{
1460
var $ = $B.args("format", 1, {self: null}, ["self"],
1461
arguments, {}, "$args", "$kw"),
1462
mapping = $.$kw, // dictionary
1463
getitem = function(key){
1464
return _b_.dict.$getitem(mapping, key)
1465
}
1466
}
1467
var parts = $B.split_format($.self)
1468
1469
// Apply formatting to the values passed to format()
Mar 19, 2018
1470
var res = "",
1471
fmt
Mar 19, 2018
1473
for(var i = 0; i < parts.length; i++){
1474
// Literal text is added unchanged
1475
if(typeof parts[i] == "string"){
1476
res += parts[i];
1477
continue
1478
}
1480
// Format objects
1481
fmt = parts[i]
1482
1483
if(fmt.spec !== undefined){
1484
// "spec" may contain "nested replacement fields"
1485
// In this case, evaluate them using the positional
1486
// or keyword arguments passed to format()
1487
function replace_nested(name, key){
1488
if(/\d+/.exec(key)){
1489
// If key is numeric, search in positional
1490
// arguments
1491
return _b_.tuple.__getitem__($.$args,
1492
parseInt(key))
1493
}else{
1494
// Else try in keyword arguments
1495
return _b_.dict.__getitem__($.$kw, key)
1496
}
1497
}
1498
fmt.spec = fmt.spec.replace(/\{(.*?)\}/g,
1499
replace_nested)
1500
}
Mar 21, 2018
1501
if(fmt.name.charAt(0).search(/\d/) > -1){
1502
// Numerical reference : use positional arguments
1503
var pos = parseInt(fmt.name),
Feb 11, 2018
1504
value = _b_.tuple.__getitem__($.$args, pos)
1505
}else{
1506
// Use keyword arguments
1507
var value = getitem(fmt.name)
1508
}
1509
// If name has extensions (attributes or subscriptions)
Mar 19, 2018
1510
for(var j = 0; j < fmt.name_ext.length; j++){
1511
var ext = fmt.name_ext[j]
Mar 19, 2018
1512
if(ext.charAt(0) == "."){
1514
value = $B.$getattr(value, ext.substr(1))
1515
}else{
1516
// Subscription
Mar 19, 2018
1517
var key = ext.substr(1, ext.length - 2)
1518
// An index made of digits is transformed into an integer
Mar 19, 2018
1519
if(key.charAt(0).search(/\d/) > -1){key = parseInt(key)}
1520
value = $B.$getattr(value, "__getitem__")(key)
Feb 12, 2018
1523
1524
// If the conversion flag is set, first call a function to convert
1525
// the value
Mar 19, 2018
1526
if(fmt.conv == "a"){value = _b_.ascii(value)}
1527
else if(fmt.conv == "r"){value = _b_.repr(value)}
1528
else if(fmt.conv == "s"){value = _b_.str.$factory(value)}
1530
// Call attribute __format__ to perform the actual formatting
1531
if(value.$is_class || value.$factory){
1532
// For classes, don't use the class __format__ method
1533
res += value.__class__.__format__(value, fmt.spec)
1535
res += $B.$getattr(value, "__format__")(fmt.spec)
Sep 5, 2014
1537
}
Sep 5, 2014
1539
}
1540
1541
str.format_map = function(self, mapping){
1542
var $ = $B.args("format_map", 2, {self: null, mapping: null},
1543
['self', 'mapping'], arguments, {}, null, null)
1544
return str.format(self, {$nat: 'mapping', mapping})
Sep 5, 2014
1545
}
1546
str
Feb 10, 2018
1547
str.index = function(self){
Sep 5, 2014
1548
// Like find(), but raise ValueError when the substring is not found.
1549
var res = str.find.apply(null, arguments)
1550
if(res === -1){
1551
throw _b_.ValueError.$factory("substring not found")
1552
}
Sep 5, 2014
1553
return res
1554
}
1555
1556
str.isascii = function(self){
1557
/* Return true if the string is empty or all characters in the string are
1558
ASCII, false otherwise. ASCII characters have code points in the range
1559
U+0000-U+007F. */
1560
for(var i = 0, len = self.length; i < len; i++){
1561
if(self.charCodeAt(i) > 127){
1562
return false
1563
}
1564
}
1565
return true
1566
}
1567
1568
str.isalnum = function(self){
1569
/* Return true if all characters in the string are alphanumeric and there
1570
is at least one character, false otherwise. A character c is alphanumeric
1571
if one of the following returns True: c.isalpha(), c.isdecimal(),
1572
c.isdigit(), or c.isnumeric(). */
1573
var $ = $B.args("isalnum", 1, {self: null}, ["self"],
1574
arguments, {}, null, null),
1575
cp
1576
for(var char of to_chars(self)){
1577
cp = _b_.ord(char)
1578
if(unicode_tables.Ll[cp] ||
1579
unicode_tables.Lu[cp] ||
1580
unicode_tables.Lm[cp] ||
1581
unicode_tables.Lt[cp] ||
1582
unicode_tables.Lo[cp] ||
1583
unicode_tables.Nd[cp] ||
1584
unicode_tables.digits[cp] ||
1585
unicode_tables.numeric[cp]){
1586
continue
1587
}
1588
return false
1589
}
1590
return true
1591
}
1592
1593
str.isalpha = function(self){
1594
/* Return true if all characters in the string are alphabetic and there is
1595
at least one character, false otherwise. Alphabetic characters are those
1596
characters defined in the Unicode character database as "Letter", i.e.,
1597
those with general category property being one of "Lm", "Lt", "Lu", "Ll",
1598
or "Lo". */
1599
var $ = $B.args("isalpha", 1, {self: null}, ["self"],
1600
arguments, {}, null, null),
1601
cp
1602
for(var char of to_chars(self)){
1603
cp = _b_.ord(char)
1604
if(unicode_tables.Ll[cp] ||
1605
unicode_tables.Lu[cp] ||
1606
unicode_tables.Lm[cp] ||
1607
unicode_tables.Lt[cp] ||
1608
unicode_tables.Lo[cp]){
1609
continue
1610
}
1611
return false
1612
}
1613
return true
1614
}
1615
1616
str.isdecimal = function(self){
1617
/* Return true if all characters in the string are decimal characters and
1618
there is at least one character, false otherwise. Decimal characters are
1619
those that can be used to form numbers in base 10, e.g. U+0660,
1620
ARABIC-INDIC DIGIT ZERO. Formally a decimal character is a character in
1621
the Unicode General Category "Nd". */
1622
var $ = $B.args("isdecimal", 1, {self: null}, ["self"],
1623
arguments, {}, null, null),
1624
cp
1625
for(var char of to_chars(self)){
1626
cp = _b_.ord(char)
1627
if(! unicode_tables.Nd[cp]){
1628
return false
1629
}
1630
}
1631
return self.length > 0
1632
}
1633
1634
str.isdigit = function(self){
1635
/* Return true if all characters in the string are digits and there is at
1636
least one character, false otherwise. */
1637
var $ = $B.args("isdigit", 1, {self: null}, ["self"],
1638
arguments, {}, null, null),
1639
cp
1640
for(var char of to_chars(self)){
1641
cp = _b_.ord(char)
1642
if(! unicode_tables.digits[cp]){
1643
return false
1644
}
1645
}
1646
return self.length > 0
1647
}
1648
1649
str.isidentifier = function(self){
1650
/* Return true if the string is a valid identifier according to the
1651
language definition. */
1652
var $ = $B.args("isidentifier", 1, {self: null}, ["self"],
1654
if(self.length == 0){
1655
return false
1656
}
1657
var chars = to_chars(self)
1658
if(unicode_tables.XID_Start[_b_.ord(chars[0])] === undefined){
1661
for(var char of chars){
1662
var cp = _b_.ord(char)
1663
if(unicode_tables.XID_Continue[cp] === undefined){
1664
return false
1665
}
1666
}
1667
}
1668
return true
1669
}
1670
1671
str.islower = function(self){
1672
/* Return true if all cased characters 4 in the string are lowercase and
1673
there is at least one cased character, false otherwise. */
1674
var $ = $B.args("islower", 1, {self: null}, ["self"],
1675
arguments, {}, null, null),
1676
has_cased = false,
1679
for(var char of to_chars(self)){
1680
cp = _b_.ord(char)
1681
if(unicode_tables.Ll[cp]){
1682
has_cased = true
1683
continue
1684
}else if(unicode_tables.Lu[cp] || unicode_tables.Lt[cp]){
1685
return false
1686
}
1687
}
1688
return has_cased
1689
}
1690
1691
str.isnumeric = function(self){
1692
/* Return true if all characters in the string are numeric characters, and
1693
there is at least one character, false otherwise. Numeric characters
1694
include digit characters, and all characters that have the Unicode numeric
1695
value property, e.g. U+2155, VULGAR FRACTION ONE FIFTH. Formally, numeric
1696
characters are those with the property value Numeric_Type=Digit,
1697
Numeric_Type=Decimal or Numeric_Type=Numeric.*/
1698
var $ = $B.args("isnumeric", 1, {self: null}, ["self"],
1699
arguments, {}, null, null)
1700
for(var char of to_chars(self)){
1701
if(! unicode_tables.numeric[_b_.ord(char)]){
1702
return false
1703
}
1704
}
1705
return self.length > 0
1706
}
1707
1708
var unprintable = {},
1709
unprintable_gc = ['Cc', 'Cf', 'Co', 'Cs','Zl', 'Zp', 'Zs']
1710
1711
str.isprintable = function(self){
1712
/* Return true if all characters in the string are printable or the string
1713
is empty, false otherwise. Nonprintable characters are those characters
1714
defined in the Unicode character database as "Other" or "Separator",
1715
excepting the ASCII space (0x20) which is considered printable. */
1716
1717
// Set unprintable if not set yet
1718
if(Object.keys(unprintable).length == 0){
1719
for(var i = 0; i < unprintable_gc.length; i++){
1720
var table = unicode_tables[unprintable_gc[i]]
1722
unprintable[cp] = true
1725
unprintable[32] = true
1726
}
1727
var $ = $B.args("isprintable", 1, {self: null}, ["self"],
1728
arguments, {}, null, null)
1729
for(var char of to_chars(self)){
1730
if(unprintable[_b_.ord(char)]){
1731
return false
1732
}
1733
}
1734
return true
1735
}
1736
1737
str.isspace = function(self){
1738
/* Return true if there are only whitespace characters in the string and
1739
there is at least one character, false otherwise.
1740
1741
A character is whitespace if in the Unicode character database, either its
1742
general category is Zs ("Separator, space"), or its bidirectional class is
1743
one of WS, B, or S.*/
1744
var $ = $B.args("isspace", 1, {self: null}, ["self"],
1745
arguments, {}, null, null),
1746
cp
1747
for(var char of to_chars(self)){
1748
cp = _b_.ord(char)
1749
if(! unicode_tables.Zs[cp] &&
1750
$B.unicode_bidi_whitespace.indexOf(cp) == -1){
1751
return false
1752
}
1753
}
1754
return self.length > 0
1755
}
1756
1757
str.istitle = function(self){
1758
/* Return true if the string is a titlecased string and there is at least
1759
one character, for example uppercase characters may only follow uncased
1760
characters and lowercase characters only cased ones. Return false
1761
otherwise. */
1762
var $ = $B.args("istitle", 1, {self: null}, ["self"],
1763
arguments, {}, null, null)
1764
return self.length > 0 && str.title(self) == self
1765
}
1766
1767
str.isupper = function(self){
1768
/* Return true if all cased characters 4 in the string are lowercase and
1769
there is at least one cased character, false otherwise. */
1770
var $ = $B.args("islower", 1, {self: null}, ["self"],
1771
arguments, {}, null, null),
1775
for(var char of to_chars(self)){
1776
cp = _b_.ord(char)
1777
if(unicode_tables.Lu[cp]){
1778
is_upper = true
1779
continue
1780
}else if(unicode_tables.Ll[cp] || unicode_tables.Lt[cp]){
str
Feb 10, 2018
1788
str.join = function(){
Mar 19, 2018
1789
var $ = $B.args("join", 2, {self: null, iterable: null},
Mar 19, 2018
1790
["self", "iterable"], arguments, {}, null, null)
Mar 19, 2018
1792
var iterable = _b_.iter($.iterable),
Mar 19, 2018
1793
res = [],
Sep 5, 2014
1795
while(1){
1796
try{
1797
var obj2 = _b_.next(iterable)
1798
if(! _b_.isinstance(obj2, str)){
1799
throw _b_.TypeError.$factory("sequence item " + count +
1800
": expected str instance, " + $B.class_name(obj2) +
1801
" found")
1802
}
1803
res.push(obj2)
Sep 5, 2014
1804
}catch(err){
1805
if(_b_.isinstance(err, _b_.StopIteration)){
1806
break
1807
}
Sep 5, 2014
1808
else{throw err}
1809
}
1810
}
1811
return res.join($.self)
Sep 5, 2014
1812
}
1813
str
Feb 10, 2018
1814
str.ljust = function(self) {
Mar 19, 2018
1815
var $ = $B.args("ljust", 3, {self: null, width: null, fillchar:null},
1816
["self", "width", "fillchar"],
1817
arguments, {fillchar: " "}, null, null),
1818
len = str.__len__(self)
1820
if($.width <= len){
1821
return self
1822
}
1823
return self + $.fillchar.repeat($.width - len)
Sep 5, 2014
1824
}
1825
1826
str.lower = function(self){
1827
var $ = $B.args("lower", 1, {self: null}, ["self"],
1828
arguments, {}, null, null)
1829
return self.toLowerCase()
1830
}
1831
1832
str.lstrip = function(self, x){
Mar 19, 2018
1833
var $ = $B.args("lstrip", 2, {self: null, chars: null}, ["self", "chars"],
1834
arguments, {chars:_b_.None}, null, null)
1835
if($.chars === _b_.None){
1836
return $.self.trimLeft()
1837
}
1838
var chars = to_chars(self)
1839
for(var i = 0, len = chars.length; i < len; i++){
1840
if($.chars.indexOf(chars[i]) === -1){
1841
return chars.slice(i).join('')
Mar 19, 2018
1844
return ""
Sep 5, 2014
1845
}
1846
1847
// note, maketrans should be a static function.
str
Feb 10, 2018
1848
str.maketrans = function() {
Mar 19, 2018
1849
var $ = $B.args("maketrans", 3, {x: null, y: null, z: null},
1850
["x", "y", "z"], arguments, {y: null, z: null}, null, null)
Mar 19, 2018
1854
if($.y === null && $.z === null){
1855
// If there is only one argument, it must be a dictionary mapping
1856
// Unicode ordinals (integers) or characters (strings of length 1) to
1857
// Unicode ordinals, strings (of arbitrary lengths) or None. Character
1858
// keys will then be converted to ordinals.
Mar 19, 2018
1859
if(! _b_.isinstance($.x, _b_.dict)){
1860
throw _b_.TypeError.$factory(
1861
"maketrans only argument must be a dict")
Feb 11, 2018
1863
var items = _b_.list.$factory(_b_.dict.items($.x))
Mar 19, 2018
1864
for(var i = 0, len = items.length; i < len; i++){
1865
var k = items[i][0],
1866
v = items[i][1]
1867
if(! _b_.isinstance(k, _b_.int)){
1868
if(_b_.isinstance(k, _b_.str) && k.length == 1){
1869
k = _b_.ord(k)
1870
}else{throw _b_.TypeError.$factory("dictionary key " + k +
1871
" is not int or 1-char string")}
1872
}
Mar 19, 2018
1873
if(v !== _b_.None && ! _b_.isinstance(v, [_b_.int, _b_.str])){
1874
throw _b_.TypeError.$factory("dictionary value " + v +
1875
" is not None, integer or string")
1876
}
1877
_b_.dict.$setitem(_t, k, v)
1878
}
1879
return _t
1880
}else{
1881
// If there are two arguments, they must be strings of equal length,
1882
// and in the resulting dictionary, each character in x will be mapped
1883
// to the character at the same position in y
Mar 19, 2018
1884
if(! (_b_.isinstance($.x, _b_.str) && _b_.isinstance($.y, _b_.str))){
1885
throw _b_.TypeError.$factory("maketrans arguments must be strings")
Mar 19, 2018
1886
}else if($.x.length !== $.y.length){
1887
throw _b_.TypeError.$factory(
1888
"maketrans arguments must be strings or same length")
1889
}else{
1890
var toNone = {}
Mar 19, 2018
1891
if($.z !== null){
1892
// If there is a third argument, it must be a string, whose
1893
// characters will be mapped to None in the result
Mar 19, 2018
1894
if(! _b_.isinstance($.z, _b_.str)){
1895
throw _b_.TypeError.$factory(
1896
"maketrans third argument must be a string")
Mar 19, 2018
1898
for(var i = 0, len = $.z.length; i < len; i++){
1899
toNone[_b_.ord($.z.charAt(i))] = true
1900
}
Mar 19, 2018
1902
for(var i = 0, len = $.x.length; i < len; i++){
1903
var key = _b_.ord($.x.charAt(i)),
1905
_b_.dict.$setitem(_t, key, value)
1906
}
1907
for(var k in toNone){
1908
_b_.dict.$setitem(_t, parseInt(k), _b_.None)
1909
}
1910
return _t
1911
}
1912
}
Sep 5, 2014
1913
}
1914
1915
str.maketrans.$type = "staticmethod"
1916
str
Feb 10, 2018
1917
str.partition = function() {
Mar 19, 2018
1918
var $ = $B.args("partition", 2, {self: null, sep: null}, ["self", "sep"],
1919
arguments, {}, null, null)
1920
if($.sep == ""){
1921
throw _b_.ValueError.$factory("empty separator")
1922
}
Mar 19, 2018
1923
check_str($.sep)
1924
var chars = to_chars($.self),
1925
i = $.self.indexOf($.sep)
1926
if(i == -1){
1927
return _b_.tuple.$factory([$.self, "", ""])
1928
}
1929
return _b_.tuple.$factory([chars.slice(0, i).join(''), $.sep,
1930
chars.slice(i + $.sep.length).join('')])
Mar 19, 2018
1931
}
1932
1933
str.removeprefix = function(){
1934
var $ = $B.args("removeprefix", 2, {self: null, prefix: null},
1935
["self", "prefix"], arguments, {}, null, null)
1936
if(!_b_.isinstance($.prefix, str)){
1937
throw _b_.ValueError.$factory("prefix should be str, not " +
1938
`'${$B.class_name($.prefix)}'`)
1939
}
1940
if(str.startswith($.self, $.prefix)){
1941
return $.self.substr($.prefix.length)
1942
}
1943
return $.self.substr(0)
1944
}
1945
1946
str.removesuffix = function(){
1947
var $ = $B.args("removesuffix", 2, {self: null, prefix: null},
1948
["self", "suffix"], arguments, {}, null, null)
1949
if(!_b_.isinstance($.suffix, str)){
1950
throw _b_.ValueError.$factory("suffix should be str, not " +
1951
`'${$B.class_name($.prefix)}'`)
1952
}
1953
if($.suffix.length > 0 && str.endswith($.self, $.suffix)){
1954
return $.self.substr(0, $.self.length - $.suffix.length)
1955
}
1956
return $.self.substr(0)
1957
}
1958
Mar 19, 2018
1959
function $re_escape(str){
1960
var specials = "[.*+?|()$^"
1961
for(var i = 0, len = specials.length; i < len; i++){
1962
var re = new RegExp("\\"+specials.charAt(i), "g")
1963
str = str.replace(re, "\\"+specials.charAt(i))
1964
}
1965
return str
Sep 5, 2014
1966
}
1967
str
Feb 10, 2018
1968
str.replace = function(self, old, _new, count) {
1969
// Replaces occurrences of 'old' by '_new'. Count references
1970
// the number of times to replace. In CPython, negative or undefined
1971
// values of count means replace all.
Mar 19, 2018
1972
var $ = $B.args("replace", 4,
1973
{self: null, old: null, $$new: null, count: null},
1974
["self", "old", "$$new", "count"],
1975
arguments, {count: -1}, null, null),
1976
count = $.count,
1977
self = $.self,
1978
old = $.old,
1979
_new = $.$$new
1980
// Validate type of old
1981
check_str(old, "replace() argument 1 ")
1982
check_str(_new, "replace() argument 2 ")
1983
// Validate instance type of 'count'
1984
if(! _b_.isinstance(count,[_b_.int, _b_.float])){
1985
throw _b_.TypeError.$factory("'" + $B.class_name(count) +
Mar 19, 2018
1986
"' object cannot be interpreted as an integer")
1987
}else if(_b_.isinstance(count, _b_.float)){
Mar 19, 2018
1988
throw _b_.TypeError.$factory("integer argument expected, got float")
1989
}
1990
if(count == 0){
1991
return self
1992
}
1993
if(count.__class__ == $B.long_int){
1994
count = parseInt(count.value)
1995
}
Mar 19, 2018
1996
if(old == ""){
1997
if(_new == ""){
1998
return self
1999
}
2000
if(self == ""){
2001
return _new
2002
}
Mar 19, 2018
2003
var elts = self.split("")
2004
if(count > -1 && elts.length >= count){
2005
var rest = elts.slice(count).join("")
2006
return _new + elts.slice(0, count).join(_new) + rest
2007
}else{
2008
return _new + elts.join(_new) + _new
2009
}
Mar 19, 2018
2011
var elts = str.split(self, old, count)
Sep 5, 2014
2012
}
Mar 19, 2018
2014
var res = self,
2015
pos = -1
2016
if(old.length == 0){
Mar 19, 2018
2018
for(var i = 0; i < elts.length; i++){
2019
res += elts[i] + _new
Mar 19, 2018
2021
return res + rest
2024
if(count < 0){
2025
count = res.length
2026
}
Mar 19, 2018
2027
while(count > 0){
2028
pos = res.indexOf(old, pos)
2029
if(pos < 0){
2030
break
2031
}
Mar 19, 2018
2032
res = res.substr(0, pos) + _new + res.substr(pos + old.length)
2033
pos = pos + _new.length
2034
count--
Mar 19, 2018
2036
return res
Sep 5, 2014
2037
}
2038
2039
str.rfind = function(self, substr){
2040
// Return the highest index in the string where substring sub is found,
2041
// such that sub is contained within s[start:end]. Optional arguments
Sep 5, 2014
2042
// start and end are interpreted as in slice notation. Return -1 on failure.
2043
if(arguments.length == 2 && typeof substr == "string"){
2044
return self.lastIndexOf(substr)
2045
}
Mar 19, 2018
2046
var $ = $B.args("rfind", 4,
Mar 19, 2018
2047
{self: null, sub: null, start: null, end: null},
2048
["self", "sub", "start", "end"],
2049
arguments, {start: 0, end: null}, null, null)
Sep 5, 2014
2050
2052
check_str($.sub)
2054
var len = str.__len__($.self),
2055
sub_len = str.__len__($.sub)
2056
2057
if(sub_len == 0){
2058
if($.js_start > len){
2059
return -1
2060
}else{
2061
return str.__len__($.self)
2062
}
2065
for(var py_pos = $.end - sub_len; py_pos >= $.start; py_pos--){
2066
var js_pos = pypos2jspos($.self, py_pos)
2067
if($.self.substr(js_pos, $.sub.length) == $.sub){
2068
return py_pos
Sep 5, 2014
2072
}
2073
str
Feb 10, 2018
2074
str.rindex = function(){
Sep 5, 2014
2075
// Like rfind() but raises ValueError when the substring sub is not found
Mar 19, 2018
2076
var res = str.rfind.apply(null, arguments)
2077
if(res == -1){
2078
throw _b_.ValueError.$factory("substring not found")
2079
}
Sep 5, 2014
2080
return res
2081
}
2082
str
Feb 10, 2018
2083
str.rjust = function(self) {
Mar 19, 2018
2084
var $ = $B.args("rjust",3,
2085
{self: null, width: null, fillchar: null},
2086
["self", "width", "fillchar"],
2087
arguments, {fillchar: " "}, null, null)
Sep 5, 2014
2088
2089
if($.width <= self.length){
2090
return self
2091
}
Sep 5, 2014
2092
2093
return $.fillchar.repeat($.width - self.length) + self
Sep 5, 2014
2094
}
2095
str
Feb 10, 2018
2096
str.rpartition = function(self,sep) {
Mar 19, 2018
2097
var $ = $B.args("rpartition", 2, {self: null, sep: null}, ["self", "sep"],
2098
arguments, {}, null, null)
2099
check_str($.sep)
2100
var self = reverse($.self),
2101
sep = reverse($.sep)
Mar 19, 2018
2102
var items = str.partition(self, sep).reverse()
2103
for(var i = 0; i < items.length; i++){
2104
items[i] = items[i].split("").reverse().join("")
2105
}
2106
return items
Sep 5, 2014
2107
}
2108
str
Feb 10, 2018
2109
str.rsplit = function(self) {
Mar 19, 2018
2110
var $ = $B.args("rsplit", 3, {self: null, sep: null, maxsplit: null},
2111
["self", "sep", "maxsplit"], arguments,
2112
{sep: _b_.None, maxsplit: -1}, null, null),
2113
sep = $.sep
2114
2115
// Use split on the reverse of the string and of separator
2116
var rev_str = reverse($.self),
2117
rev_sep = sep === _b_.None ? sep : reverse($.sep),
str
Feb 10, 2018
2118
rev_res = str.split(rev_str, rev_sep, $.maxsplit)
2120
// Reverse the list, then each string inside the list
2121
rev_res.reverse()
Mar 19, 2018
2122
for(var i = 0; i < rev_res.length; i++){
2123
rev_res[i] = reverse(rev_res[i])
Sep 5, 2014
2126
}
2127
Mar 19, 2018
2128
str.rstrip = function(self, x){
2129
var $ = $B.args("rstrip", 2, {self: null, chars: null}, ["self", "chars"],
Mar 19, 2018
2130
arguments, {chars: _b_.None}, null, null)
2131
if($.chars === _b_.None){
2132
return $.self.trimRight()
2133
}
2134
var chars = to_chars(self)
2135
for(var j = chars.length - 1; j >= 0; j--){
2136
if($.chars.indexOf(chars[j]) == -1){
2137
return chars.slice(0, j + 1).join('')
Mar 19, 2018
2140
return ""
Sep 5, 2014
2141
}
2142
str
Feb 10, 2018
2143
str.split = function(){
Mar 19, 2018
2144
var $ = $B.args("split", 3, {self: null, sep: null, maxsplit: null},
2145
["self", "sep", "maxsplit"], arguments,
2146
{sep: _b_.None, maxsplit: -1}, null, null),
2147
sep = $.sep,
2148
maxsplit = $.maxsplit,
2149
self = $.self,
2150
pos = 0
2151
if(maxsplit.__class__ === $B.long_int){
2152
maxsplit = parseInt(maxsplit.value)
2153
}
2154
if(sep == ""){
2155
throw _b_.ValueError.$factory("empty separator")
2156
}
Mar 19, 2018
2158
if(sep === _b_.None){
Sep 5, 2014
2159
var res = []
2160
while(pos < self.length && self.charAt(pos).search(/\s/) > -1){
2161
pos++
2162
}
2163
if(pos === self.length - 1){
2164
return [self]
2165
}
Mar 19, 2018
2166
var name = ""
Sep 5, 2014
2167
while(1){
Mar 19, 2018
2168
if(self.charAt(pos).search(/\s/) == -1){
2169
if(name == ""){
2170
name = self.charAt(pos)
2171
}else{
2172
name += self.charAt(pos)
2173
}
Sep 5, 2014
2174
}else{
Mar 19, 2018
2175
if(name !== ""){
Sep 5, 2014
2176
res.push(name)
Mar 19, 2018
2177
if(maxsplit !== -1 && res.length == maxsplit + 1){
Sep 5, 2014
2178
res.pop()
Mar 19, 2018
2179
res.push(name + self.substr(pos))
Sep 5, 2014
2180
return res
2181
}
Mar 19, 2018
2182
name = ""
Sep 5, 2014
2183
}
2184
}
2185
pos++
Mar 19, 2018
2186
if(pos > self.length - 1){
2187
if(name){
2188
res.push(name)
2189
}
Sep 5, 2014
2190
break
2191
}
2192
}
2193
return res.map($B.String)
Sep 5, 2014
2194
}else{
Mar 19, 2018
2195
var res = [],
2196
s = "",
2197
seplen = sep.length
2198
if(maxsplit == 0){
2199
return [self]
2200
}
Mar 19, 2018
2201
while(pos < self.length){
2202
if(self.substr(pos, seplen) == sep){
Mar 19, 2018
2205
if(maxsplit > -1 && res.length >= maxsplit){
2207
return res.map($B.String)
Mar 19, 2018
2209
s = ""
2210
}else{
2211
s += self.charAt(pos)
2212
pos++
Sep 5, 2014
2213
}
2214
}
2216
return res.map($B.String)
Sep 5, 2014
2217
}
2218
}
2219
2220
str.splitlines = function(self) {
2221
var $ = $B.args('splitlines', 2, {self: null, keepends: null},
2222
['self','keepends'], arguments, {keepends: false},
2223
null, null)
2224
if(!_b_.isinstance($.keepends,[_b_.bool, _b_.int])){
2225
throw _b_.TypeError('integer argument expected, got '+
2226
$B.get_class($.keepends).__name)
2227
}
2228
var keepends = _b_.int.$factory($.keepends),
2229
res = [],
2230
self = $.self,
2231
start = 0,
2232
pos = 0
2233
if(!self.length){
2234
return res
2235
}
2237
if(self.substr(pos, 2) == '\r\n'){
2238
res.push(self.slice(start, keepends ? pos + 2 : pos))
2239
start = pos = pos+2
2240
}else if(self[pos] == '\r' || self[pos] == '\n'){
2241
res.push(self.slice(start, keepends ? pos+1 : pos))
2242
start = pos = pos+1
2243
}else{
2244
pos++
2245
}
2246
}
2247
if(start < self.length){
2248
res.push(self.slice(start))
2249
}
2250
return res
2251
}
Sep 5, 2014
2252
str
Feb 10, 2018
2253
str.startswith = function(){
2254
// Return True if string starts with the prefix, otherwise return False.
2255
// prefix can also be a tuple of prefixes to look for. With optional
2256
// start, test string beginning at that position. With optional end,
Sep 5, 2014
2257
// stop comparing string at that position.
Mar 19, 2018
2258
var $ = $B.args("startswith", 4,
2259
{self: null, prefix: null, start: null, end: null},
2260
["self", "prefix", "start", "end"],
2261
arguments, {start: 0, end: null}, null, null)
Sep 5, 2014
2262
2263
normalize_start_end($)
2264
2265
var prefixes = $.prefix
2266
if(! _b_.isinstance(prefixes, _b_.tuple)){
2267
prefixes = [prefixes]
2268
}
2269
var s = $.self.substring($.js_start, $.js_end)
2270
for(var prefix of prefixes){
2271
if(! _b_.isinstance(prefix, str)){
2272
throw _b_.TypeError.$factory("endswith first arg must be str " +
2273
"or a tuple of str, not int")
2274
}
2275
if(s.substr(0, prefix.length) == prefix){
2276
return true
2277
}
Sep 5, 2014
2278
}
2279
return false
2280
}
2281
str
Feb 10, 2018
2282
str.strip = function(){
Mar 19, 2018
2283
var $ = $B.args("strip", 2, {self: null, chars: null}, ["self", "chars"],
2284
arguments, {chars: _b_.None}, null, null)
2285
if($.chars === _b_.None){
2286
return $.self.trim()
2287
}
2288
var chars = to_chars($.self)
2289
for(var i = 0; i < chars.length; i++){
2290
if($.chars.indexOf(chars[i]) == -1){
Mar 19, 2018
2291
break
2294
for(var j = chars.length - 1; j >= i; j--){
2295
if($.chars.indexOf(chars[j]) == -1){
Mar 19, 2018
2296
break
2299
return chars.slice(i, j + 1).join('')
Sep 5, 2014
2300
}
2301
2302
str.swapcase = function(self){
2303
var $ = $B.args("swapcase", 1, {self}, ["self"],
2304
arguments, {}, null, null),
2305
res = "",
2306
cp
2307
2308
for(var char of to_chars(self)){
2309
cp = _b_.ord(char)
2310
if(unicode_tables.Ll[cp]){
2311
res += char.toUpperCase()
2312
}else if(unicode_tables.Lu[cp]){
2313
res += char.toLowerCase()
2316
}
2317
}
2318
return res
2319
}
2320
2321
str.title = function(self){
2322
var $ = $B.args("title", 1, {self}, ["self"],
2323
arguments, {}, null, null),
2324
state,
2327
for(var char of to_chars(self)){
2328
cp = _b_.ord(char)
2329
if(unicode_tables.Ll[cp]){
2336
}else if(unicode_tables.Lu[cp] || unicode_tables.Lt[cp]){
2337
res += state ? char.toLowerCase() : char
2338
state = "word"
2339
}else{
2340
state = null
2342
}
2343
}
2344
return res
2345
}
2346
2347
str.translate = function(self, table){
Mar 19, 2018
2348
var res = [],
2349
getitem = $B.$getattr(table, "__getitem__"),
2350
cp
2351
for(var char of to_chars(self)){
2352
cp = _b_.ord(char)
2355
if(repl !== _b_.None){
2356
if(typeof repl == "string"){
2357
res.push(repl)
2358
}else if(typeof repl == "number"){
2359
res.push(String.fromCharCode(repl))
2360
}
2361
}
2362
}catch(err){
Sep 5, 2014
2365
}
Mar 19, 2018
2366
return res.join("")
Sep 5, 2014
2367
}
2368
2369
str.upper = function(self){
2370
var $ = $B.args("upper", 1, {self: null}, ["self"],
2371
arguments, {}, null, null)
2372
return self.toUpperCase()
2373
}
2374
Mar 19, 2018
2375
str.zfill = function(self, width){
Mar 19, 2018
2376
var $ = $B.args("zfill", 2, {self: null, width: null},
2377
["self", "width"], arguments, {}, null, null),
2378
len = str.__len__(self)
2379
if($.width <= len){
2380
return self
2381
}
Mar 19, 2018
2383
case "+":
2384
case "-":
2385
return self.charAt(0) +
2386
"0".repeat($.width - len) + self.substr(1)
2388
return "0".repeat($.width - len) + self
Sep 5, 2014
2390
}
2391
2392
str.$factory = function(arg, encoding, errors){
2393
if(arguments.length == 0){
2394
return ""
2395
}
2397
return $B.UndefinedClass.__str__()
2398
}else if(arg === null){
2399
return '<Javascript null>'
2401
if(encoding !== undefined){
2402
// Arguments may be passed as keywords (cf. issue #1060)
2403
var $ = $B.args("str", 3, {arg: null, encoding: null, errors: null},
2404
["arg", "encoding", "errors"], arguments,
2405
{encoding: "utf-8", errors: "strict"}, null, null),
2406
encoding = $.encoding,
2407
errors = $.errors
2408
}
2409
if(typeof arg == "string" || arg instanceof String ||
2410
typeof arg == "number"){
2411
if(isFinite(arg)){
2412
return arg.toString()
2413
}
2416
if(arg.$is_class || arg.$factory){
2417
// arg is a class
2418
// In this case, str() doesn't use the attribute __str__ of the
2419
// class or its subclasses, but the attribute __str__ of the
2420
// class metaclass (usually "type") or its subclasses (usually
2421
// "object")
2422
// The metaclass is the attribute __class__ of the class dictionary
Mar 19, 2018
2423
var func = $B.$getattr(arg.__class__, "__str__")
2425
}
2427
if(arg.__class__ && arg.__class__ === _b_.bytes &&
2428
encoding !== undefined){
2429
// str(bytes, encoding, errors) is equal to
2430
// bytes.decode(encoding, errors)
2431
return _b_.bytes.decode(arg, $.encoding, $.errors)
2433
// Implicit invocation of __str__ uses method __str__ on the class,
2434
// even if arg has an attribute __str__
2435
var klass = arg.__class__ || $B.get_class(arg)
2437
return $B.JSObj.__str__($B.JSObj.$factory(arg))
2439
var method = $B.$getattr(klass , "__str__", null)
2440
if(method === null ||
2441
// if not better than object.__str__, try __repr__
2442
(arg.__class__ && arg.__class__ !== _b_.object &&
2443
method.$infos && method.$infos.__func__ === _b_.object.__str__)){
2444
var method = $B.$getattr(klass, "__repr__")
Sep 5, 2014
2446
}
2447
catch(err){
2448
console.log("no __str__ for", arg)
Mar 19, 2018
2449
console.log("err ", err)
2450
if($B.debug > 1){console.log(err)}
2451
console.log("Warning - no method __str__ or __repr__, " +
2452
"default to toString", arg)
May 20, 2019
2453
throw err
Sep 5, 2014
2454
}
2455
return $B.$call(method)(arg)
Sep 5, 2014
2456
}
str
Feb 10, 2018
2457
2458
str.__new__ = function(cls){
Mar 19, 2018
2459
if(cls === undefined){
2460
throw _b_.TypeError.$factory("str.__new__(): not enough arguments")
Sep 5, 2014
2461
}
Mar 19, 2018
2462
return {__class__: cls}
Sep 5, 2014
2463
}
2464
str
Feb 10, 2018
2465
$B.set_func_names(str, "builtins")
Sep 5, 2014
2467
// dictionary and factory for subclasses of string
str
Feb 10, 2018
2468
var StringSubclass = $B.StringSubclass = {
Mar 19, 2018
2469
__class__: _b_.type,
2470
__mro__: [_b_.object],
2471
$infos: {
2472
__module__: "builtins",
2473
__name__: "str"
2474
},
str
Feb 10, 2018
2475
$is_class: true
Sep 5, 2014
2476
}
2477
str
Feb 10, 2018
2478
// the methods in subclass apply the methods in str to the
Sep 5, 2014
2479
// result of instance.valueOf(), which is a Javascript string
str
Feb 10, 2018
2480
for(var $attr in str){
Mar 19, 2018
2481
if(typeof str[$attr] == "function"){
Mar 19, 2018
2482
StringSubclass[$attr] = (function(attr){
Sep 5, 2014
2483
return function(){
Mar 19, 2018
2484
var args = [],
2485
pos = 0
2486
if(arguments.length > 0){
2487
var args = [arguments[0].valueOf()],
2488
pos = 1
2489
for(var i = 1, len = arguments.length; i < len; i++){
2490
args[pos++] = arguments[i]
Sep 5, 2014
2491
}
2492
}
Mar 19, 2018
2493
return str[attr].apply(null, args)
Sep 5, 2014
2494
}
2495
})($attr)
2496
}
2497
}
2498
str
Feb 10, 2018
2499
StringSubclass.__new__ = function(cls){
Sep 5, 2014
2502
str
Feb 10, 2018
2503
$B.set_func_names(StringSubclass, "builtins")
Sep 5, 2014
2505
_b_.str = str
2506
2507
// Function to parse the 2nd argument of format()
2508
$B.parse_format_spec = function(spec){
2509
if(spec == ""){
2510
this.empty = true
2511
}else{
Mar 19, 2018
2512
var pos = 0,
2513
aligns = "<>=^",
2514
digits = "0123456789",
2515
types = "bcdeEfFgGnosxX%",
2516
align_pos = aligns.indexOf(spec.charAt(0))
Mar 19, 2018
2517
if(align_pos != -1){
2518
if(spec.charAt(1) && aligns.indexOf(spec.charAt(1)) != -1){
2519
// If the second char is also an alignment specifier, the
2520
// first char is the fill value
2521
this.fill = spec.charAt(0)
2522
this.align = spec.charAt(1)
2523
pos = 2
2524
}else{
2525
// The first character defines alignment : fill defaults to ' '
Mar 19, 2018
2526
this.align = aligns[align_pos]
2527
this.fill = " "
2528
pos++
2529
}
2530
}else{
2531
align_pos = aligns.indexOf(spec.charAt(1))
Mar 19, 2018
2532
if(spec.charAt(1) && align_pos != -1){
2533
// The second character defines alignment : fill is the first one
Mar 19, 2018
2534
this.align = aligns[align_pos]
2535
this.fill = spec.charAt(0)
2536
pos = 2
2537
}
2538
}
2539
var car = spec.charAt(pos)
Mar 19, 2018
2540
if(car == "+" || car == "-" || car == " "){
2541
this.sign = car
2542
pos++
2543
car = spec.charAt(pos)
2545
if(car == "#"){
2546
this.alternate = true; pos++; car = spec.charAt(pos)
2547
}
Mar 19, 2018
2548
if(car == "0"){
Mar 19, 2018
2549
// sign-aware : equivalent to fill = 0 and align == "="
Mar 19, 2018
2550
this.fill = "0"
2551
if(align_pos == -1){
2552
this.align = "="
2553
}
Mar 19, 2018
2554
pos++
2555
car = spec.charAt(pos)
2556
}
Mar 19, 2018
2557
while(car && digits.indexOf(car) > -1){
2558
if(this.width === undefined){
2559
this.width = car
2560
}else{
2561
this.width += car
2562
}
Mar 19, 2018
2563
pos++
2564
car = spec.charAt(pos)
2566
if(this.width !== undefined){
2567
this.width = parseInt(this.width)
2568
}
2569
if(this.width === undefined && car == "{"){
2570
// Width is determined by a parameter
2571
var end_param_pos = spec.substr(pos).search("}")
2572
this.width = spec.substring(pos, end_param_pos)
2573
console.log("width", "[" + this.width + "]")
2574
pos += end_param_pos + 1
2575
}
2576
if(car == ","){
2577
this.comma = true
2578
pos++
2579
car = spec.charAt(pos)
2580
}
Mar 19, 2018
2581
if(car == "."){
2582
if(digits.indexOf(spec.charAt(pos + 1)) == -1){
2583
throw _b_.ValueError.$factory(
2584
"Missing precision in format spec")
Mar 19, 2018
2586
this.precision = spec.charAt(pos + 1)
2587
pos += 2
2588
car = spec.charAt(pos)
2589
while(car && digits.indexOf(car) > -1){
Mar 21, 2018
2590
this.precision += car
Mar 19, 2018
2591
pos++
2592
car = spec.charAt(pos)
2593
}
2594
this.precision = parseInt(this.precision)
2595
}
Mar 19, 2018
2596
if(car && types.indexOf(car) > -1){
2597
this.type = car
2598
pos++
2599
car = spec.charAt(pos)
2600
}
2601
if(pos !== spec.length){
2602
throw _b_.ValueError.$factory("Invalid format specifier: " + spec)
2606
this.toString = function(){
Mar 19, 2018
2607
return (this.fill === undefined ? "" : _b_.str.$factory(this.fill)) +
2608
(this.align || "") +
2609
(this.sign || "") +
2610
(this.alternate ? "#" : "") +
2611
(this.sign_aware ? "0" : "") +
2612
(this.width || "") +
2613
(this.comma ? "," : "") +
2614
(this.precision ? "." + this.precision : "") +
2615
(this.type || "")
2616
}
2617
}
2618
2619
$B.format_width = function(s, fmt){
Mar 19, 2018
2620
if(fmt.width && s.length < fmt.width){
2621
var fill = fmt.fill || " ",
2622
align = fmt.align || "<",
2623
missing = fmt.width - s.length
2624
switch(align){
Mar 19, 2018
2625
case "<":
2626
return s + fill.repeat(missing)
2627
case ">":
2628
return fill.repeat(missing) + s
2629
case "=":
2630
if("+-".indexOf(s.charAt(0)) > -1){
2631
return s.charAt(0) + fill.repeat(missing) + s.substr(1)
2632
}else{
Mar 19, 2018
2633
return fill.repeat(missing) + s
Mar 19, 2018
2635
case "^":
2636
var left = parseInt(missing / 2)
2637
return fill.repeat(left) + s + fill.repeat(missing - left)
2638
}
2639
}
2640
return s
2641
}
2642
2643
function fstring_expression(){
Mar 19, 2018
2644
this.type = "expression"
2645
this.expression = ""
2646
this.conversion = null
2647
this.fmt = null
2648
}
2649
2650
function fstring_error(msg, pos){
2651
error = Error(msg)
2652
error.position = pos
2653
throw error
2654
}
2655
2656
$B.parse_fstring = function(string){
2657
// Parse a f-string
2658
var elts = [],
2659
pos = 0,
Mar 19, 2018
2660
current = "",
2661
ctype = null,
2662
nb_braces = 0,
2663
expr_start,
2664
car
2665
Mar 19, 2018
2666
while(pos < string.length){
2667
if(ctype === null){
2668
car = string.charAt(pos)
Mar 19, 2018
2669
if(car == "{"){
Mar 21, 2018
2670
if(string.charAt(pos + 1) == "{"){
Mar 19, 2018
2671
ctype = "string"
2672
current = "{"
2673
pos += 2
2674
}else{
Mar 19, 2018
2675
ctype = "expression"
2676
expr_start = pos + 1
2677
nb_braces = 1
2678
pos++
2679
}
Mar 19, 2018
2680
}else if(car == "}"){
Mar 21, 2018
2681
if(string.charAt(pos + 1) == car){
Mar 19, 2018
2682
ctype = "string"
2683
current = "}"
2684
pos += 2
2685
}else{
2686
fstring_error(" f-string: single '}' is not allowed",
2687
pos)
2688
}
2689
}else{
Mar 19, 2018
2690
ctype = "string"
2691
current = car
2692
pos++
Mar 19, 2018
2694
}else if(ctype == "string"){
2695
// end of string is the first single { or end of string
Mar 19, 2018
2696
var i = pos
2697
while(i < string.length){
2698
car = string.charAt(i)
Mar 19, 2018
2699
if(car == "{"){
Mar 21, 2018
2700
if(string.charAt(i + 1) == "{"){
Mar 19, 2018
2701
current += "{"
2702
i += 2
2703
}else{
2704
elts.push(current)
Mar 19, 2018
2705
ctype = "expression"
2706
expr_start = i + 1
Mar 19, 2018
2707
pos = i + 1
2708
break
2709
}
Mar 19, 2018
2710
}else if(car == "}"){
2711
if(string.charAt(i + 1) == car){
2712
current += car
2713
i += 2
2714
}else{
2715
fstring_error(" f-string: single '}' is not allowed",
2716
pos)
2717
}
2718
}else{
2719
current += car
2720
i++
2721
}
2722
}
Mar 19, 2018
2723
pos = i + 1
2724
}else if(ctype == "debug"){
2725
// after the equal sign, whitespace are ignored and the only
2726
// valid characters are } and :
2727
while(string.charAt(i) == " "){i++}
2728
if(string.charAt(i) == "}"){
2729
// end of debug expression
2730
console.log('end of debug', current)
2731
elts.push(current)
2732
ctype = null
2733
current = ""
2734
pos = i + 1
2735
}
2736
}else{
2737
// End of expression is the } matching the opening {
2738
// There may be nested braces
2739
var i = pos,
2740
nb_braces = 1,
2741
nb_paren = 0,
2742
current = new fstring_expression()
Mar 19, 2018
2743
while(i < string.length){
2744
car = string.charAt(i)
Mar 19, 2018
2745
if(car == "{" && nb_paren == 0){
2746
nb_braces++
2747
current.expression += car
2748
i++
Mar 19, 2018
2749
}else if(car == "}" && nb_paren == 0){
2750
nb_braces -= 1
Mar 19, 2018
2751
if(nb_braces == 0){
2752
// end of expression
2753
if(current.fmt){
2754
current.format = string.substring(fmt_start, i)
2755
}
2756
if(current.expression == ""){
2757
fstring_error("f-string: empty expression not allowed",
2758
pos)
2759
}
2760
elts.push(current)
2761
ctype = null
Mar 19, 2018
2762
current = ""
2763
pos = i + 1
2766
current.expression += car
2767
i++
Mar 19, 2018
2768
}else if(car == "\\"){
2769
// backslash is not allowed in expressions
2770
throw Error("f-string expression part cannot include a" +
2771
" backslash")
Mar 19, 2018
2772
}else if(nb_paren == 0 && car == "!" && current.fmt === null &&
2773
":}".indexOf(string.charAt(i + 2)) > -1){
Mar 19, 2018
2774
if(current.expression.length == 0){
2775
throw Error("f-string: empty expression not allowed")
2776
}
Mar 19, 2018
2777
if("ars".indexOf(string.charAt(i + 1)) == -1){
2778
throw Error("f-string: invalid conversion character:" +
2779
" expected 's', 'r', or 'a'")
2780
}else{
Mar 19, 2018
2781
current.conversion = string.charAt(i + 1)
2782
i += 2
2783
}
Mar 19, 2018
2784
}else if(car == "("){
2785
nb_paren++
2786
current.expression += car
2787
i++
Mar 19, 2018
2788
}else if(car == ")"){
2789
nb_paren--
2790
current.expression += car
2791
i++
Mar 19, 2018
2792
}else if(car == '"'){
2793
// triple string ?
Mar 19, 2018
2794
if(string.substr(i, 3) == '"""'){
2795
var end = string.indexOf('"""', i + 3)
2796
if(end == -1){
2797
fstring_error("f-string: unterminated string", pos)
Mar 19, 2018
2798
}else{
2799
var trs = string.substring(i, end + 3)
2800
trs = trs.replace("\n", "\\n\\")
2801
current.expression += trs
Mar 19, 2018
2802
i = end + 3
2803
}
2804
}else{
Mar 19, 2018
2805
var end = string.indexOf('"', i + 1)
2806
if(end == -1){
2807
fstring_error("f-string: unterminated string", pos)
Mar 19, 2018
2808
}else{
2809
current.expression += string.substring(i, end + 1)
2810
i = end + 1
2811
}
2812
}
Mar 19, 2018
2813
}else if(nb_paren == 0 && car == ":"){
2814
current.fmt = true
2815
var fmt_start = i
2816
current.expression += car
2817
i++
2818
}else if(car == "="){
2819
// might be a "debug expression", eg f"{x=}"
2820
var ce = current.expression,
2821
last_char = ce.charAt(ce.length - 1),
2822
last_char_re = ('()'.indexOf(last_char) > -1 ? "\\" : "") + last_char
2826
string.charAt(i + 1) == "=" ||
2827
"=!<>:".search(last_char_re) > -1){
2828
// not a debug expression
2831
}else{
2832
// add debug string
2833
tail = car
2834
while(string.charAt(i + 1).match(/\s/)){
2835
tail += string.charAt(i + 1)
2836
i++
2837
}
2838
// push simple string
2839
elts.push(current.expression + tail)
2840
// remove trailing whitespace from expression
2841
while(ce.match(/\s$/)){
2842
ce = ce.substr(0, ce.length - 1)
2843
}
2844
current.expression = ce
2845
ctype = "debug"
2846
i++
2847
}
2848
}else{
2849
current.expression += car
2850
i++
2851
}
2852
}
Mar 21, 2018
2853
if(nb_braces > 0){
2854
fstring_error("f-string: expected '}'", pos)
2855
}
2856
}
2857
}
2858
if(current.length > 0){
2859
elts.push(current)
2860
}
2861
for(var elt of elts){
2862
if(typeof elt == "object"){
2863
if(elt.fmt_pos !== undefined &&
2864
elt.expression.charAt(elt.fmt_pos) != ':'){
2865
console.log('mauvais format', string, elts)
2866
throw Error()
2867
}
2868
}
2869
}
2870
return elts
2871
}
2872
2873
var _chr = $B.codepoint2jsstring = function(i){
2874
if(i >= 0x10000 && i <= 0x10FFFF){
2875
var code = (i - 0x10000)
2876
return String.fromCodePoint(0xD800 | (code >> 10)) +
2877
String.fromCodePoint(0xDC00 | (code & 0x3FF))
2878
}else{
2879
return String.fromCodePoint(i)
2880
}
2881
}
2883
var _ord = $B.jsstring2codepoint = function(c){
2884
if(c.length == 1){
2885
return c.charCodeAt(0)
2886
}
2887
var code = 0x10000
2888
code += (c.charCodeAt(0) & 0x03FF) << 10
2889
code += (c.charCodeAt(1) & 0x03FF)
2890
return code
2891
}
2892
Sep 5, 2014
2893
})(__BRYTHON__)