Permalink
Mar 6, 2021
Aug 7, 2021
Mar 19, 2018
Apr 5, 2021
Mar 6, 2021
Mar 19, 2018
Mar 19, 2018
Mar 19, 2018
Mar 19, 2018
Jan 14, 2015
Mar 19, 2018
Mar 19, 2018
Mar 19, 2018
Jan 14, 2015
Mar 19, 2018
Jan 14, 2015
Jan 14, 2015
Jan 14, 2015
Mar 19, 2018
Jan 14, 2015
Mar 19, 2018
Mar 19, 2018
Mar 19, 2018
Mar 19, 2018
Mar 19, 2018
Mar 19, 2018
Mar 19, 2018
Mar 19, 2018
Mar 19, 2018
Jan 14, 2015
Mar 19, 2018
Jan 14, 2015
Mar 19, 2018
Mar 19, 2018
Mar 19, 2018
Mar 19, 2018
Dec 18, 2019
Dec 18, 2019
Mar 19, 2018
Jan 14, 2015
Jan 14, 2015
Mar 19, 2018
Mar 19, 2018
Jan 14, 2015
Mar 19, 2018
Mar 19, 2018
Mar 19, 2018
Mar 19, 2018
Mar 19, 2018
Mar 19, 2018
Mar 6, 2021
Mar 19, 2018
Mar 16, 2021
Mar 16, 2021
Mar 19, 2018
Mar 27, 2019
Mar 6, 2021
Mar 19, 2018
Mar 6, 2021
Mar 19, 2018
Mar 19, 2018
Mar 19, 2018
Mar 6, 2021
Mar 6, 2021
Mar 6, 2021
Mar 19, 2018
Apr 2, 2019
Apr 2, 2019
Mar 19, 2018
Aug 31, 2017
Mar 19, 2018
Mar 6, 2021
Mar 19, 2018
Mar 6, 2021
Aug 31, 2017
Apr 16, 2019
Mar 19, 2018
Mar 19, 2018
Mar 19, 2018
Nov 12, 2018
Nov 22, 2020
Nov 12, 2018
Mar 19, 2018
Nov 22, 2020
Mar 6, 2021
Mar 6, 2021
Mar 6, 2021
Mar 6, 2021
Mar 6, 2021
Mar 6, 2021
Mar 6, 2021
Sep 27, 2020
Sep 27, 2020
Mar 6, 2021
Mar 6, 2021
Mar 6, 2021
Mar 19, 2018
Mar 6, 2021
Mar 19, 2018
Aug 31, 2017
Mar 19, 2018
Mar 19, 2018
Mar 19, 2018
Jan 6, 2016
Mar 19, 2018
Mar 19, 2018
Mar 19, 2018
Mar 6, 2021
Jun 11, 2020
Mar 19, 2018
Mar 19, 2018
Apr 5, 2021
Mar 6, 2021
Mar 6, 2021
Mar 19, 2018
Mar 19, 2018
Aug 31, 2017
Mar 19, 2018
Mar 19, 2018
Mar 19, 2018
Mar 19, 2018
Mar 19, 2018
Mar 19, 2018
Mar 19, 2018
Mar 6, 2021
Mar 6, 2021
Mar 6, 2021
Feb 27, 2020
Feb 27, 2020
Feb 27, 2020
Aug 31, 2017
Mar 19, 2018
Mar 6, 2021
Mar 19, 2018
Mar 6, 2021
Mar 6, 2021
Mar 6, 2021
Mar 6, 2021
Jan 26, 2020
Mar 6, 2021
Nov 15, 2019
Jul 28, 2018
Oct 27, 2019
Nov 2, 2018
Oct 27, 2019
Nov 2, 2018
Mar 19, 2018
Mar 19, 2018
Mar 19, 2018
Mar 19, 2018
Mar 19, 2018
Mar 6, 2021
Nov 12, 2018
Mar 6, 2021
Mar 19, 2018
Mar 19, 2018
Mar 19, 2018
Mar 19, 2018
Mar 19, 2018
Mar 19, 2018
Mar 19, 2018
Dec 12, 2020
Jun 29, 2017
Oct 13, 2019
Jun 29, 2017
Dec 12, 2020
Jul 10, 2017
Jul 10, 2017
Mar 19, 2018
Mar 19, 2018
Jun 20, 2020
Oct 13, 2019
Oct 13, 2019
Jul 31, 2021
Jan 18, 2021
Jan 18, 2021
Newer
100644
2938 lines (2725 sloc)
88.6 KB
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
24
for(var i = 0, len = s.length; i < len; i++){
25
var cp = s.codePointAt(i)
26
if(cp >= 0x10000){
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
53
function jspos2pypos(s, jspos){
54
// convert JS position to Python position
55
if(s.surrogates === undefined){
56
return jspos
57
}
58
var nb = 0
59
while(s.surrogates[nb] + nb < jspos){
60
nb++
61
}
62
return jspos - nb
63
}
64
82
}
83
if($.start === null || $.start === _b_.None){
84
$.start = 0
85
}else if($.start < 0){
86
$.start += len
89
if($.end === null || $.end === _b_.None){
90
$.end = len
91
}else if($.end < 0){
92
$.end += len
97
throw _b_.TypeError.$factory("slice indices must be integers " +
98
"or None or have an __index__ method")
99
}
100
if($.self.surrogates){
101
$.js_start = pypos2jspos($.self, $.start)
102
$.js_end = pypos2jspos($.self, $.end)
103
}
116
throw _b_.TypeError.$factory((prefix || '') +
117
"must be str, not " + $B.class_name(obj))
121
function to_chars(s){
122
// Transform Javascript string s into a list of Python characters
123
// (2 JS chars if surrogate, 1 otherwise)
124
var chars = []
125
for(var i = 0, len = s.length; i < len; i++){
126
var code = s.charCodeAt(i)
127
if(code >= 0xD800 && code <= 0xDBFF){
128
chars.push(s.substr(i, 2))
129
i++
130
}else{
131
chars.push(s.charAt(i))
132
}
133
}
134
return chars
135
}
136
137
function to_codepoints(s){
138
// Transform Javascript string s into a list of codepoints
142
var cps = []
143
for(var i = 0, len = s.length; i < len; i++){
144
var code = s.charCodeAt(i)
145
if(code >= 0xD800 && code <= 0xDBFF){
146
var v = 0x10000
147
v += (code & 0x03FF) << 10
148
v += (s.charCodeAt(i + 1) & 0x03FF)
149
cps.push(v)
150
i++
151
}else{
152
cps.push(code)
153
}
154
}
159
if(! _b_.isinstance(other, str)){
160
try{
161
return $B.$getattr(other, "__radd__")(self)
162
}catch(err){
171
throw _b_.TypeError.$factory("'in <string>' requires " +
172
"string as left operand, not " + item.__class__)
173
}
199
// __dir__must be assigned explicitely because attribute resolution for
200
// builtin classes doesn't use __mro__
214
if(fmt.type && fmt.type != "s"){
215
throw _b_.ValueError.$factory("Unknown format code '" + fmt.type +
223
if(fmt.sign !== undefined){
224
throw _b_.ValueError.$factory(
225
"Sign not allowed in string format specifier")
242
if(pos >= 0 && pos < len){
243
var jspos = pypos2jspos(self, pos)
244
if(self.codePointAt(jspos) >= 0x10000){
245
return $B.String(self.substr(jspos, 2))
246
}else{
253
var s = _b_.slice.$conv_for_seq(arg, len),
254
start = pypos2jspos(self, s.start),
255
stop = pypos2jspos(self, s.stop),
318
try{
319
return str_hash_cache[self] = fnv(to_codepoints(self))
320
}catch(err){
321
console.log('error hash, cps', self, to_codepoints(self))
322
throw err
323
}
341
if(self.len !== undefined){
342
return self.len
343
}
344
var len = self.len = self.valueOf().length - self.surrogates.length
345
return len
382
// left adjusted
383
return s + get_char_array(padding - s.length, flags.pad_char)
384
}
385
}
386
394
if(val.__class__ === $B.long_int){
395
s = $B.long_int.to_base(val, 10)
396
}else{
397
s = val.toString()
399
if(s[0] === "-"){
400
return "-" + get_char_array(precision - s.length + 1, "0") + s.slice(1)
411
if(val === Infinity){
412
val = "inf"
413
}else if(val === -Infinity){
414
val = "-inf"
415
}else{
416
val = "nan"
438
var str_format = function(val, flags) {
439
// string format supports left and right padding
440
flags.pad_char = " " // even if 0 padding is defined, don't use it
446
if(val.__class__ === $B.long_int){
447
val = $B.long_int.to_base(val, 10)
448
}else{
449
val = parseInt(val)
467
var repr_format = function(val, flags) {
468
flags.pad_char = " " // even if 0 padding is defined, don't use it
472
var ascii_format = function(val, flags) {
473
flags.pad_char = " " // even if 0 padding is defined, don't use it
487
flags.precision = parseInt(flags.precision, 10)
488
validate_precision(flags.precision)
489
}
490
return parseFloat(val)
491
}
494
var trailing_zeros = /(.*?)(0+)([eE].*)/,
495
leading_zeros = /\.(0*)/,
496
trailing_dot = /\.$/
498
var validate_precision = function(precision) {
499
// force precision to limits of javascript
504
var floating_point_format = function(val, upper, flags){
505
val = _float_helper(val, flags),
506
v = val.toString(),
507
v_len = v.length,
508
dot_idx = v.indexOf('.')
509
if(dot_idx < 0){dot_idx = v_len}
510
if(val < 1 && val > -1){
511
var zeros = leading_zeros.exec(v),
512
numzeros
513
if(zeros){
518
if(numzeros >= 4){
519
val = format_sign(val, flags) + format_float_precision(val, upper,
520
flags, _floating_g_exp_helper)
521
if(!flags.alternate){
534
return format_padding(format_sign(val, flags) +
535
format_float_precision(val, upper, flags,
536
function(val, precision) {
538
numzeros)
539
}),
540
flags
541
)
542
}
543
544
if(dot_idx > flags.precision){
545
val = format_sign(val, flags) + format_float_precision(val, upper,
546
flags, _floating_g_exp_helper)
547
if(! flags.alternate){
559
return format_padding(format_sign(val, flags) +
560
format_float_precision(val, upper, flags,
561
function(val, precision) {
562
if(!flags.decimal_point){
564
}else if (precision > v_len){
565
if(! flags.alternate){
566
precision = v_len
567
}
569
if(precision < dot_idx){
570
precision = dot_idx
571
}
572
return val.toFixed(precision - dot_idx)
573
}),
574
flags
575
)
578
var _floating_g_exp_helper = function(val, precision, flags, upper){
579
if(precision){--precision}
582
var e_idx = val.lastIndexOf("e")
583
if(e_idx > val.length - 4){
584
val = val.substring(0, e_idx + 2) + "0" + val.substring(e_idx + 2)
587
return val
588
}
589
590
// fF
591
var floating_point_decimal_format = function(val, upper, flags) {
592
val = _float_helper(val, flags)
593
return format_padding(format_sign(val, flags) +
594
format_float_precision(val, upper, flags,
595
function(val, precision, flags) {
596
val = val.toFixed(precision)
597
if(precision === 0 && flags.alternate){
598
val += '.'
599
}
600
return val
601
}),
602
flags
603
)
604
}
605
606
var _floating_exp_helper = function(val, precision, flags, upper) {
607
val = val.toExponential(precision)
608
// pad exponent to two digits
621
return format_padding(format_sign(val, flags) +
622
format_float_precision(val, upper, flags, _floating_exp_helper), flags)
648
if(flags.alternate){
649
if(ret.charAt(0) === "-"){
650
if(upper){ret = "-0X" + ret.slice(1)}
651
else{ret = "-0x" + ret.slice(1)}
652
}else{
653
if(upper){ret = "0X" + ret}
654
else{ret = "0x" + ret}
664
if(val.__class__ === $B.long_int){
665
ret = $B.long_int.to_base(8)
666
}else{
667
ret = parseInt(val)
668
ret = ret.toString(8)
684
if(flags.alternate){
685
if(ret.charAt(0) === "-"){ret = "-0o" + ret.slice(1)}
686
else{ret = "0o" + ret}
691
function series_of_bytes(val, flags){
692
if(val.__class__ && val.__class__.$buffer_protocol){
693
var it = _b_.iter(val),
694
ints = []
695
while(true){
696
try{
697
ints.push(_b_.next(it))
698
}catch(err){
699
if(err.__class__ === _b_.StopIteration){
700
var b = _b_.bytes.$factory(ints)
701
return format_padding(_b_.bytes.decode(b, "ascii"), flags)
702
}
703
throw err
704
}
705
}
706
}else{
707
try{
708
bytes_obj = $B.$getattr(val, "__bytes__")
709
return format_padding(_b_.bytes.decode(bytes_obj), flags)
710
}catch(err){
711
if(err.__class__ === _b_.AttributeError){
712
throw _b_.TypeError.$factory("%b does not accept '" +
713
$B.class_name(val) + "'")
714
}
715
throw err
716
}
717
}
718
}
719
724
val = val.source[0]
725
}else{
726
try{
727
val = _b_.int.$factory(val) // yes, floats are valid (they are cast to int)
728
}catch (err){
729
throw _b_.TypeError.$factory("%c requires int or char")
730
}
735
var num_flag = function(c, flags){
736
if(c === "0" && ! flags.padding && ! flags.decimal_point && ! flags.left){
737
flags.pad_char = "0"
743
flags.precision = (flags.precision || "") + c
744
}
745
}
746
747
var decimal_point_flag = function(val, flags) {
749
// can only have one decimal point
750
throw new UnsupportedChar()
751
}
752
flags.decimal_point = true
753
}
754
755
var neg_flag = function(val, flags){
756
flags.pad_char = " " // overrides '0' flag
774
"s": str_format,
775
"d": num_format,
776
"i": num_format,
777
"u": num_format,
778
"o": octal_format,
779
"r": repr_format,
780
"a": ascii_format,
781
"g": function(val, flags){
782
return floating_point_format(val, false, flags)
783
},
784
"G": function(val, flags){return floating_point_format(val, true, flags)},
785
"f": function(val, flags){
786
return floating_point_decimal_format(val, false, flags)
787
},
788
"F": function(val, flags){
789
return floating_point_decimal_format(val, true, flags)
790
},
791
"e": function(val, flags){
792
return floating_point_exponential_format(val, false, flags)
793
},
794
"E": function(val, flags){
795
return floating_point_exponential_format(val, true, flags)
796
},
797
"x": function(val, flags){return signed_hex_format(val, false, flags)},
798
"X": function(val, flags){return signed_hex_format(val, true, flags)},
799
"c": single_char_format,
800
"0": function(val, flags){return num_flag("0", flags)},
801
"1": function(val, flags){return num_flag("1", flags)},
802
"2": function(val, flags){return num_flag("2", flags)},
803
"3": function(val, flags){return num_flag("3", flags)},
804
"4": function(val, flags){return num_flag("4", flags)},
805
"5": function(val, flags){return num_flag("5", flags)},
806
"6": function(val, flags){return num_flag("6", flags)},
807
"7": function(val, flags){return num_flag("7", flags)},
808
"8": function(val, flags){return num_flag("8", flags)},
809
"9": function(val, flags){return num_flag("9", flags)},
810
"-": neg_flag,
811
" ": space_flag,
812
"+": sign_flag,
813
".": decimal_point_flag,
814
"#": alternate_flag
815
}
816
817
// exception thrown when an unsupported char is encountered in legacy format
863
if(self === undefined){
864
throw _b_.TypeError.$factory(
865
"not enough arguments for format string")
892
throw _b_.ValueError.$factory(
893
"unsupported format character '" + invalid_char +
894
"' (0x" + invalid_char.charCodeAt(0).toString(16) +
895
") at index " + newpos)
896
}else if(err.name === "NotANumber"){
897
var try_char = s[newpos],
898
cls = self.__class__
899
if(!cls){
900
if(typeof(self) === "string"){
901
cls = "str"
902
}else{
908
throw _b_.TypeError.$factory("%" + try_char +
909
" format: a number is required, not " + cls)
910
}else{
942
}while(pos < length)
943
944
if(argpos !== null){
945
if(args.length > argpos){
946
throw _b_.TypeError.$factory(
947
"not enough arguments for format string")
948
}else if(args.length < argpos){
949
throw _b_.TypeError.$factory(
950
"not all arguments converted during string formatting")
952
}else if(nbph == 0){
953
throw _b_.TypeError.$factory(
954
"not all arguments converted during string formatting")
962
var $ = $B.args("__mul__", 2, {self: null, other: null},
963
["self", "other"], arguments, {}, null, null)
974
function __newobj__(){
975
// __newobj__ is called with a generator as only argument
976
var $ = $B.args('__newobj__', 0, {}, [], arguments, {}, 'args', null),
977
args = $.args
978
var res = args[1]
979
res.__class__ = args[0]
980
return res
981
}
982
983
str.__reduce_ex__ = function(self){
984
return $B.fast_tuple([
985
__newobj__,
986
$B.fast_tuple([self.__class__ || _b_.str, self]),
987
_b_.None,
988
_b_.None])
989
}
990
993
var t = {
994
8: "\\x08",
995
9: "\\t",
996
10: "\\n",
997
11: "\\x0b",
998
12: "\\x0c",
999
13: "\\r",
1000
92: "\\\\"
1001
}
1002
var repl = '',
1003
chars = to_chars(self)
1004
for(var i = 0; i < chars.length; i++){
1005
var cp = _b_.ord(chars[i])
1006
if(t[cp] !== undefined){
1007
repl += t[cp]
1008
}else if($B.is_unicode_cn(cp)){
1027
if(res.search('"') == -1 && res.search("'") == -1){
1028
return "'" + res + "'"
1029
}else if(self.search('"') == -1){
1030
return '"' + res + '"'
1031
}
1032
var qesc = new RegExp("'", "g") // to escape single quote
1033
res = "'" + res.replace(qesc, "\\'") + "'"
1037
str.__rmul__ = function(self, other){
1038
if(_b_.isinstance(other, _b_.int)){
1039
other = _b_.int.numerator(other)
1040
var res = ''
1041
while(other > 0){
1042
res += self
1043
other--
1044
}
1045
return res
1046
}
1047
return _b_.NotImplemented
1048
}
1049
1050
str.__setattr__ = function(self, attr, value){
1051
if(typeof self === "string"){
1052
if(str.hasOwnProperty(attr)){
1054
attr + "' is read-only")
1055
}else{
1056
throw _b_.AttributeError.$factory(
1057
"'str' object has no attribute '" + attr + "'")
1058
}
1059
}
1060
// str subclass : use __dict__
1061
_b_.dict.$setitem(self.__dict__, attr, value)
1062
return $N
1063
}
1064
1065
str.__setitem__ = function(self, attr, value){
1066
throw _b_.TypeError.$factory(
1067
"'str' object does not support item assignment")
1070
var combining = []
1071
for(var cp = 0x300; cp <= 0x36F; cp++){
1072
combining.push(String.fromCharCode(cp))
1073
}
1077
var repl = '',
1078
chars = to_chars(self)
1079
if(chars.length == self.length){
1080
return self.replace(combining_re, "\u200B$1")
1081
}
1082
for(var i = 0; i < chars.length; i++){
1083
var cp = _b_.ord(chars[i])
1084
if(cp >= 0x300 && cp <= 0x36F){
1085
repl += "\u200B" + chars[i]
1086
}else{
1087
repl += chars[i]
1088
}
1089
}
1090
return repl
1100
$comp_func += "" // source code
1101
var $comps = {">": "gt", ">=": "ge", "<": "lt", "<=": "le"}
1112
str.capitalize = function(self){
1113
var $ = $B.args("capitalize", 1, {self}, ["self"],
1114
arguments, {}, null, null)
1118
return self.charAt(0).toUpperCase() + self.substr(1)
1119
}
1120
1121
str.casefold = function(self){
1122
var $ = $B.args("casefold", 1, {self}, ["self"],
1123
arguments, {}, null, null),
1124
res = "",
1125
char,
1126
cf,
1127
chars = to_chars($.self)
1128
1129
for(var i = 0, len = chars.length; i < len; i++){
1130
char = chars[i]
1131
cf = $B.unicode_casefold[char]
1132
if(cf){
1133
cf.forEach(function(cp){
1134
res += String.fromCharCode(cp)
1135
})
1136
}else{
1143
str.center = function(){
1144
var $ = $B.args("center", 3, {self: null, width: null, fillchar: null},
1145
["self", "width", "fillchar"],
1146
arguments, {fillchar:" "}, null, null),
1147
self = $.self
1151
var pad = parseInt(($.width - self.length) / 2),
1152
res = $.fillchar.repeat(pad)
1161
var $ = $B.args("count", 4, {self:null, sub:null, start:null, stop:null},
1162
["self", "sub", "start", "stop"], arguments, {start:null, stop:null},
1165
throw _b_.TypeError.$factory("Can't convert '" + $B.class_name($.sub) +
1166
"' object to str implicitly")
1167
}
1171
if($.stop !== null){
1172
_slice = _b_.slice.$factory($.start, $.stop)
1173
}else{
1174
_slice = _b_.slice.$factory($.start, $.self.length)
1175
}
1183
if($.start == $.self.length){
1184
return 1
1185
}else if(substr.length == 0){
1186
return 0
1187
}
1190
var n = 0,
1191
pos = 0
1192
while(pos < substr.length){
1193
pos = substr.indexOf($.sub, pos)
1204
str.encode = function(){
1205
var $ = $B.args("encode", 3, {self: null, encoding: null, errors: null},
1206
["self", "encoding", "errors"], arguments,
1207
{encoding: "utf-8", errors: "strict"}, null, null)
1208
if($.encoding == "rot13" || $.encoding == "rot_13"){
1211
for(var i = 0, len = $.self.length; i < len ; i++){
1212
var char = $.self.charAt(i)
1213
if(("a" <= char && char <= "m") || ("A" <= char && char <= "M")){
1214
res += String.fromCharCode(String.charCodeAt(char) + 13)
1215
}else if(("m" < char && char <= "z") ||
1216
("M" < char && char <= "Z")){
1217
res += String.fromCharCode(String.charCodeAt(char) - 13)
1226
// Return True if the string ends with the specified suffix, otherwise
1227
// return False. suffix can also be a tuple of suffixes to look for.
1228
// With optional start, test beginning at that position. With optional
1232
["self", "suffix", "start", "end"],
1233
arguments, {start: 0, end: null}, null, null)
1246
if(! _b_.isinstance(suffix, str)){
1247
throw _b_.TypeError.$factory(
1248
"endswith first arg must be str or a tuple of str, not int")
1249
}
1259
var $ = $B.args("expandtabs", 2, {self: null, tabsize: null},
1260
["self", "tabsize"], arguments, {tabsize: 8}, null, null)
1261
var s = $B.$GetInt($.tabsize),
1262
col = 0,
1263
pos = 0,
1264
res = "",
1265
chars = to_chars(self)
1266
if(s == 1){
1267
return self.replace(/\t/g," ")
1268
}
1269
while(pos < chars.length){
1270
var car = chars[pos]
1280
res += car
1281
col = 0
1282
break
1283
default:
1284
res += car
1285
col++
1286
break
1287
}
1288
pos++
1289
}
1290
return res
1294
// Return the lowest index in the string where substring sub is found,
1295
// such that sub is contained in the slice s[start:end]. Optional
1296
// arguments start and end are interpreted as in slice notation.
1299
{self: null, sub: null, start: null, end: null},
1300
["self", "sub", "start", "end"],
1301
arguments, {start: 0, end: null}, null, null)
1314
// Use .indexOf(), not .search(), to avoid conversion to reg exp
1315
var js_start = pypos2jspos($.self, $.start),
1316
js_end = pypos2jspos($.self, $.end),
1317
ix = $.self.substring(js_start, js_end).indexOf($.sub)
1318
if(ix == -1){
1319
return -1
1330
// a.x[z]!r:...
1331
// the object has attributes :
1332
// - name : "a"
1333
// - name_ext : [".x", "[z]"]
1334
// - conv : r
1335
// - spec : rest of string after :
1343
// No : in the string : it only contains a name
1344
name = fmt_string
1345
}else{
1346
// name is before the first ":"
1347
// spec (the format specification) is after
1348
name = elts[0]
1352
var elts = name.split("!")
1353
if(elts.length > 1){
1354
name = elts[0]
1355
conv = elts[1] // conversion flag
1359
// "name' may be a subscription or attribute
1360
// Put these "extensions" in the list "name_ext"
1361
function name_repl(match){
1362
name_ext.push(match)
1364
}
1365
var name_ext_re = /\.[_a-zA-Z][_a-zA-Z0-9]*|\[[_a-zA-Z][_a-zA-Z0-9]*\]|\[[0-9]+\]/g
1366
name = name.replace(name_ext_re, name_repl)
1367
}
1374
// Parse self to detect formatting instructions
1375
// Create a list "parts" made of sections of the string :
1376
// - elements of even rank are literal text
1377
// - elements of odd rank are "format objects", built from the
1378
// format strings in self (of the form {...})
1389
text += "{"
1390
pos += 2
1391
}else if(car == "}" && self.charAt(pos + 1) == "}"){
1398
// Store current literal text
1399
parts.push(text)
1400
1401
// Search the end of the format string, ie the } closing the
1402
// opening {. Since the string can contain other pairs {} for
1403
// nested formatting, an integer nb is incremented for each { and
1404
// decremented for each } ; the end of the format string is
1405
// reached when nb == 0
1406
var end = pos + 1,
1407
nb = 1
1408
while(end < _len){
1409
if(self.charAt(end) == "{"){nb++; end++}
1410
else if(self.charAt(end) == "}"){
1411
nb--; end++
1412
if(nb == 0){
1417
var fmt_obj = $B.parse_format(fmt_string)
1418
fmt_obj.raw_name = fmt_obj.name
1419
fmt_obj.raw_spec = fmt_obj.spec
1453
}else{
1454
text += car
1455
pos++
1456
}
1457
}
1458
if(text){
1459
parts.push(text)
1465
// Special management of keyword arguments if str.format is called by
1466
// str.format_map(mapping) : the argument "mapping" might not be a
1467
// dictionary
1468
var last_arg = $B.last(arguments)
1469
if(last_arg.$nat == "mapping"){
1470
var mapping = last_arg.mapping,
1471
getitem = $B.$getattr(mapping, "__getitem__")
1472
// Get the rest of the arguments
1473
var args = []
1474
for(var i = 0, len = arguments.length - 1; i < len; i++){
1475
args.push(arguments[i])
1476
}
1477
var $ = $B.args("format", 1, {self: null}, ["self"],
1478
args, {}, "$args", null)
1479
}else{
1480
var $ = $B.args("format", 1, {self: null}, ["self"],
1481
arguments, {}, "$args", "$kw"),
1482
mapping = $.$kw, // dictionary
1483
getitem = function(key){
1484
return _b_.dict.$getitem(mapping, key)
1485
}
1486
}
1502
1503
if(fmt.spec !== undefined){
1504
// "spec" may contain "nested replacement fields"
1505
// In this case, evaluate them using the positional
1506
// or keyword arguments passed to format()
1507
function replace_nested(name, key){
1508
if(/\d+/.exec(key)){
1509
// If key is numeric, search in positional
1510
// arguments
1511
return _b_.tuple.__getitem__($.$args,
1512
parseInt(key))
1513
}else{
1514
// Else try in keyword arguments
1515
return _b_.dict.__getitem__($.$kw, key)
1516
}
1517
}
1518
fmt.spec = fmt.spec.replace(/\{(.*?)\}/g,
1519
replace_nested)
1520
}
1522
// Numerical reference : use positional arguments
1523
var pos = parseInt(fmt.name),
1544
// If the conversion flag is set, first call a function to convert
1545
// the value
1546
if(fmt.conv == "a"){value = _b_.ascii(value)}
1547
else if(fmt.conv == "r"){value = _b_.repr(value)}
1548
else if(fmt.conv == "s"){value = _b_.str.$factory(value)}
1561
str.format_map = function(self, mapping){
1562
var $ = $B.args("format_map", 2, {self: null, mapping: null},
1563
['self', 'mapping'], arguments, {}, null, null)
1564
return str.format(self, {$nat: 'mapping', mapping})
1577
/* Return true if the string is empty or all characters in the string are
1578
ASCII, false otherwise. ASCII characters have code points in the range
1579
U+0000-U+007F. */
1588
str.isalnum = function(self){
1589
/* Return true if all characters in the string are alphanumeric and there
1590
is at least one character, false otherwise. A character c is alphanumeric
1591
if one of the following returns True: c.isalpha(), c.isdecimal(),
1592
c.isdigit(), or c.isnumeric(). */
1593
var $ = $B.args("isalnum", 1, {self: null}, ["self"],
1594
arguments, {}, null, null),
1595
cp
1596
for(var char of to_chars(self)){
1597
cp = _b_.ord(char)
1598
if(unicode_tables.Ll[cp] ||
1599
unicode_tables.Lu[cp] ||
1600
unicode_tables.Lm[cp] ||
1601
unicode_tables.Lt[cp] ||
1602
unicode_tables.Lo[cp] ||
1603
unicode_tables.Nd[cp] ||
1604
unicode_tables.digits[cp] ||
1605
unicode_tables.numeric[cp]){
1606
continue
1607
}
1608
return false
1609
}
1610
return true
1611
}
1612
1613
str.isalpha = function(self){
1614
/* Return true if all characters in the string are alphabetic and there is
1615
at least one character, false otherwise. Alphabetic characters are those
1616
characters defined in the Unicode character database as "Letter", i.e.,
1617
those with general category property being one of "Lm", "Lt", "Lu", "Ll",
1618
or "Lo". */
1619
var $ = $B.args("isalpha", 1, {self: null}, ["self"],
1620
arguments, {}, null, null),
1621
cp
1622
for(var char of to_chars(self)){
1623
cp = _b_.ord(char)
1624
if(unicode_tables.Ll[cp] ||
1625
unicode_tables.Lu[cp] ||
1626
unicode_tables.Lm[cp] ||
1627
unicode_tables.Lt[cp] ||
1628
unicode_tables.Lo[cp]){
1629
continue
1630
}
1631
return false
1632
}
1633
return true
1634
}
1635
1636
str.isdecimal = function(self){
1637
/* Return true if all characters in the string are decimal characters and
1638
there is at least one character, false otherwise. Decimal characters are
1639
those that can be used to form numbers in base 10, e.g. U+0660,
1640
ARABIC-INDIC DIGIT ZERO. Formally a decimal character is a character in
1641
the Unicode General Category "Nd". */
1642
var $ = $B.args("isdecimal", 1, {self: null}, ["self"],
1643
arguments, {}, null, null),
1644
cp
1645
for(var char of to_chars(self)){
1646
cp = _b_.ord(char)
1647
if(! unicode_tables.Nd[cp]){
1648
return false
1649
}
1650
}
1651
return self.length > 0
1652
}
1653
1654
str.isdigit = function(self){
1655
/* Return true if all characters in the string are digits and there is at
1656
least one character, false otherwise. */
1657
var $ = $B.args("isdigit", 1, {self: null}, ["self"],
1658
arguments, {}, null, null),
1659
cp
1660
for(var char of to_chars(self)){
1661
cp = _b_.ord(char)
1662
if(! unicode_tables.digits[cp]){
1663
return false
1664
}
1665
}
1666
return self.length > 0
1667
}
1668
1669
str.isidentifier = function(self){
1670
/* Return true if the string is a valid identifier according to the
1671
language definition. */
1672
var $ = $B.args("isidentifier", 1, {self: null}, ["self"],
1676
}
1677
var chars = to_chars(self)
1678
if(unicode_tables.XID_Start[_b_.ord(chars[0])] === undefined){
1681
for(var char of chars){
1682
var cp = _b_.ord(char)
1683
if(unicode_tables.XID_Continue[cp] === undefined){
1684
return false
1685
}
1686
}
1687
}
1688
return true
1689
}
1690
1691
str.islower = function(self){
1692
/* Return true if all cased characters 4 in the string are lowercase and
1693
there is at least one cased character, false otherwise. */
1694
var $ = $B.args("islower", 1, {self: null}, ["self"],
1695
arguments, {}, null, null),
1696
has_cased = false,
1699
for(var char of to_chars(self)){
1700
cp = _b_.ord(char)
1701
if(unicode_tables.Ll[cp]){
1702
has_cased = true
1703
continue
1704
}else if(unicode_tables.Lu[cp] || unicode_tables.Lt[cp]){
1705
return false
1706
}
1707
}
1708
return has_cased
1709
}
1710
1711
str.isnumeric = function(self){
1712
/* Return true if all characters in the string are numeric characters, and
1713
there is at least one character, false otherwise. Numeric characters
1714
include digit characters, and all characters that have the Unicode numeric
1715
value property, e.g. U+2155, VULGAR FRACTION ONE FIFTH. Formally, numeric
1716
characters are those with the property value Numeric_Type=Digit,
1717
Numeric_Type=Decimal or Numeric_Type=Numeric.*/
1718
var $ = $B.args("isnumeric", 1, {self: null}, ["self"],
1719
arguments, {}, null, null)
1728
var unprintable = {},
1729
unprintable_gc = ['Cc', 'Cf', 'Co', 'Cs','Zl', 'Zp', 'Zs']
1730
1731
str.isprintable = function(self){
1732
/* Return true if all characters in the string are printable or the string
1733
is empty, false otherwise. Nonprintable characters are those characters
1734
defined in the Unicode character database as "Other" or "Separator",
1735
excepting the ASCII space (0x20) which is considered printable. */
1736
1737
// Set unprintable if not set yet
1738
if(Object.keys(unprintable).length == 0){
1739
for(var i = 0; i < unprintable_gc.length; i++){
1740
var table = unicode_tables[unprintable_gc[i]]
1751
return false
1752
}
1753
}
1754
return true
1755
}
1756
1757
str.isspace = function(self){
1758
/* Return true if there are only whitespace characters in the string and
1759
there is at least one character, false otherwise.
1760
1761
A character is whitespace if in the Unicode character database, either its
1762
general category is Zs ("Separator, space"), or its bidirectional class is
1763
one of WS, B, or S.*/
1764
var $ = $B.args("isspace", 1, {self: null}, ["self"],
1765
arguments, {}, null, null),
1766
cp
1767
for(var char of to_chars(self)){
1768
cp = _b_.ord(char)
1769
if(! unicode_tables.Zs[cp] &&
1770
$B.unicode_bidi_whitespace.indexOf(cp) == -1){
1771
return false
1772
}
1773
}
1774
return self.length > 0
1775
}
1776
1777
str.istitle = function(self){
1778
/* Return true if the string is a titlecased string and there is at least
1779
one character, for example uppercase characters may only follow uncased
1780
characters and lowercase characters only cased ones. Return false
1781
otherwise. */
1782
var $ = $B.args("istitle", 1, {self: null}, ["self"],
1783
arguments, {}, null, null)
1784
return self.length > 0 && str.title(self) == self
1785
}
1786
1787
str.isupper = function(self){
1788
/* Return true if all cased characters 4 in the string are lowercase and
1789
there is at least one cased character, false otherwise. */
1790
var $ = $B.args("islower", 1, {self: null}, ["self"],
1791
arguments, {}, null, null),
1795
for(var char of to_chars(self)){
1796
cp = _b_.ord(char)
1797
if(unicode_tables.Lu[cp]){
1798
is_upper = true
1799
continue
1800
}else if(unicode_tables.Ll[cp] || unicode_tables.Lt[cp]){
1819
throw _b_.TypeError.$factory("sequence item " + count +
1820
": expected str instance, " + $B.class_name(obj2) +
1821
" found")
1822
}
1835
var $ = $B.args("ljust", 3, {self: null, width: null, fillchar:null},
1836
["self", "width", "fillchar"],
1840
if($.width <= len){
1841
return self
1842
}
1843
return self + $.fillchar.repeat($.width - len)
1846
str.lower = function(self){
1847
var $ = $B.args("lower", 1, {self: null}, ["self"],
1848
arguments, {}, null, null)
1849
return self.toLowerCase()
1850
}
1851
1854
arguments, {chars:_b_.None}, null, null),
1855
self = $.self,
1856
chars = $.chars
1857
if(chars === _b_.None){
1858
return self.trimStart()
1860
while(self.length > 0){
1861
var flag = false
1862
for(var char of chars){
1863
if(self.startsWith(char)){
1864
self = self.substr(char.length)
1865
flag = true
1866
break
1867
}
1868
}
1869
if(! flag){
1870
return $.self.surrogates ? $B.String(self) : self
1878
var $ = $B.args("maketrans", 3, {x: null, y: null, z: null},
1879
["x", "y", "z"], arguments, {y: null, z: null}, null, null)
1884
// If there is only one argument, it must be a dictionary mapping
1885
// Unicode ordinals (integers) or characters (strings of length 1) to
1886
// Unicode ordinals, strings (of arbitrary lengths) or None. Character
1888
if(! _b_.isinstance($.x, _b_.dict)){
1889
throw _b_.TypeError.$factory(
1890
"maketrans only argument must be a dict")
1893
for(var i = 0, len = items.length; i < len; i++){
1894
var k = items[i][0],
1895
v = items[i][1]
1896
if(! _b_.isinstance(k, _b_.int)){
1897
if(_b_.isinstance(k, _b_.str) && k.length == 1){
1898
k = _b_.ord(k)
1899
}else{throw _b_.TypeError.$factory("dictionary key " + k +
1902
if(v !== _b_.None && ! _b_.isinstance(v, [_b_.int, _b_.str])){
1903
throw _b_.TypeError.$factory("dictionary value " + v +
1911
// and in the resulting dictionary, each character in x will be mapped
1912
// to the character at the same position in y
1915
}else if($.x.length !== $.y.length){
1916
throw _b_.TypeError.$factory(
1917
"maketrans arguments must be strings or same length")
1923
if(! _b_.isinstance($.z, _b_.str)){
1924
throw _b_.TypeError.$factory(
1925
"maketrans third argument must be a string")
1947
var $ = $B.args("partition", 2, {self: null, sep: null}, ["self", "sep"],
1948
arguments, {}, null, null)
1955
if(i == -1){
1956
return _b_.tuple.$factory([$.self, "", ""])
1957
}
1958
return _b_.tuple.$factory([chars.slice(0, i).join(''), $.sep,
1959
chars.slice(i + $.sep.length).join('')])
1962
str.removeprefix = function(){
1963
var $ = $B.args("removeprefix", 2, {self: null, prefix: null},
1964
["self", "prefix"], arguments, {}, null, null)
1965
if(!_b_.isinstance($.prefix, str)){
1966
throw _b_.ValueError.$factory("prefix should be str, not " +
1967
`'${$B.class_name($.prefix)}'`)
1968
}
1969
if(str.startswith($.self, $.prefix)){
1970
return $.self.substr($.prefix.length)
1971
}
1972
return $.self.substr(0)
1973
}
1974
1975
str.removesuffix = function(){
1976
var $ = $B.args("removesuffix", 2, {self: null, prefix: null},
1977
["self", "suffix"], arguments, {}, null, null)
1978
if(!_b_.isinstance($.suffix, str)){
1979
throw _b_.ValueError.$factory("suffix should be str, not " +
1980
`'${$B.class_name($.prefix)}'`)
1981
}
1982
if($.suffix.length > 0 && str.endswith($.self, $.suffix)){
1983
return $.self.substr(0, $.self.length - $.suffix.length)
1984
}
1985
return $.self.substr(0)
1986
}
1987
1988
function $re_escape(str){
1989
var specials = "[.*+?|()$^"
1990
for(var i = 0, len = specials.length; i < len; i++){
1991
var re = new RegExp("\\"+specials.charAt(i), "g")
1992
str = str.replace(re, "\\"+specials.charAt(i))
1993
}
1994
return str
2002
{self: null, old: null, new: null, count: null},
2003
["self", "old", "new", "count"],
2004
arguments, {count: -1}, null, null),
2005
count = $.count,
2006
self = $.self,
2007
old = $.old,
2010
check_str(old, "replace() argument 1 ")
2011
check_str(_new, "replace() argument 2 ")
2019
if(count == 0){
2020
return self
2021
}
2022
if(count.__class__ == $B.long_int){
2023
count = parseInt(count.value)
2024
}
2026
if(_new == ""){
2027
return self
2028
}
2029
if(self == ""){
2030
return _new
2031
}
2032
var elts = self.split("")
2033
if(count > -1 && elts.length >= count){
2034
var rest = elts.slice(count).join("")
2035
return _new + elts.slice(0, count).join(_new) + rest
2061
res = res.substr(0, pos) + _new + res.substr(pos + old.length)
2062
pos = pos + _new.length
2063
count--
2069
// Return the highest index in the string where substring sub is found,
2070
// such that sub is contained within s[start:end]. Optional arguments
2073
{self: null, sub: null, start: null, end: null},
2074
["self", "sub", "start", "end"],
2075
arguments, {start: 0, end: null}, null, null)
2080
var len = str.__len__($.self),
2081
sub_len = str.__len__($.sub)
2082
2083
if(sub_len == 0){
2084
if($.js_start > len){
2091
// Use .indexOf(), not .search(), to avoid conversion to reg exp
2092
var js_start = pypos2jspos($.self, $.start),
2093
js_end = pypos2jspos($.self, $.end),
2094
ix = $.self.substring(js_start, js_end).lastIndexOf($.sub)
2095
if(ix == -1){
2096
return -1
2111
var $ = $B.args("rjust",3,
2112
{self: null, width: null, fillchar: null},
2113
["self", "width", "fillchar"],
2114
arguments, {fillchar: " "}, null, null)
2124
var $ = $B.args("rpartition", 2, {self: null, sep: null}, ["self", "sep"],
2125
arguments, {}, null, null)
2129
var items = str.partition(self, sep).reverse()
2130
for(var i = 0; i < items.length; i++){
2131
items[i] = items[i].split("").reverse().join("")
2137
var $ = $B.args("rsplit", 3, {self: null, sep: null, maxsplit: null},
2138
["self", "sep", "maxsplit"], arguments,
2139
{sep: _b_.None, maxsplit: -1}, null, null),
2140
sep = $.sep
2143
var rev_str = reverse($.self),
2144
rev_sep = sep === _b_.None ? sep : reverse($.sep),
2155
str.rstrip = function(self, x){
2156
var $ = $B.args("rstrip", 2, {self: null, chars: null}, ["self", "chars"],
2157
arguments, {chars: _b_.None}, null, null),
2158
self = $.self,
2159
chars = $.chars
2160
if(chars === _b_.None){
2161
return self.trimEnd()
2163
while(self.length > 0){
2164
var flag = false
2165
for(var char of chars){
2166
if(self.endsWith(char)){
2167
self = self.substr(0, self.length - char.length)
2168
flag = true
2169
break
2170
}
2171
}
2172
if(! flag){
2173
return $.self.surrogates ? $B.String(self) : self
2180
var $ = $B.args("split", 3, {self: null, sep: null, maxsplit: null},
2181
["self", "sep", "maxsplit"], arguments,
2182
{sep: _b_.None, maxsplit: -1}, null, null),
2183
sep = $.sep,
2184
maxsplit = $.maxsplit,
2185
self = $.self,
2186
pos = 0
2187
if(maxsplit.__class__ === $B.long_int){
2188
maxsplit = parseInt(maxsplit.value)
2189
}
2190
if(sep == ""){
2191
throw _b_.ValueError.$factory("empty separator")
2192
}
2196
while(pos < self.length && self.charAt(pos).search(/\s/) > -1){
2197
pos++
2198
}
2199
if(pos === self.length - 1){
2200
return [self]
2201
}
2205
if(name == ""){
2206
name = self.charAt(pos)
2207
}else{
2208
name += self.charAt(pos)
2209
}
2256
str.splitlines = function(self) {
2257
var $ = $B.args('splitlines', 2, {self: null, keepends: null},
2258
['self','keepends'], arguments, {keepends: false},
2259
null, null)
2260
if(!_b_.isinstance($.keepends,[_b_.bool, _b_.int])){
2261
throw _b_.TypeError('integer argument expected, got '+
2264
var keepends = _b_.int.$factory($.keepends),
2265
res = [],
2266
self = $.self,
2267
start = 0,
2268
pos = 0
2269
if(!self.length){
2273
if(self.substr(pos, 2) == '\r\n'){
2274
res.push(self.slice(start, keepends ? pos + 2 : pos))
2275
start = pos = pos+2
2276
}else if(self[pos] == '\r' || self[pos] == '\n'){
2277
res.push(self.slice(start, keepends ? pos+1 : pos))
2278
start = pos = pos+1
2279
}else{
2280
pos++
2281
}
2282
}
2283
if(start < self.length){
2284
res.push(self.slice(start))
2285
}
2290
// Return True if string starts with the prefix, otherwise return False.
2291
// prefix can also be a tuple of prefixes to look for. With optional
2292
// start, test string beginning at that position. With optional end,
2294
var $ = $B.args("startswith", 4,
2295
{self: null, prefix: null, start: null, end: null},
2296
["self", "prefix", "start", "end"],
2297
arguments, {start: 0, end: null}, null, null)
2307
if(! _b_.isinstance(prefix, str)){
2308
throw _b_.TypeError.$factory("endswith first arg must be str " +
2309
"or a tuple of str, not int")
2310
}
2311
if(s.substr(0, prefix.length) == prefix){
2312
return true
2313
}
2319
var $ = $B.args("strip", 2, {self: null, chars: null}, ["self", "chars"],
2320
arguments, {chars: _b_.None}, null, null)
2327
str.swapcase = function(self){
2328
var $ = $B.args("swapcase", 1, {self}, ["self"],
2329
arguments, {}, null, null),
2330
res = "",
2331
cp
2332
2333
for(var char of to_chars(self)){
2334
cp = _b_.ord(char)
2335
if(unicode_tables.Ll[cp]){
2336
res += char.toUpperCase()
2337
}else if(unicode_tables.Lu[cp]){
2338
res += char.toLowerCase()
2341
}
2342
}
2343
return res
2344
}
2345
2346
str.title = function(self){
2347
var $ = $B.args("title", 1, {self}, ["self"],
2348
arguments, {}, null, null),
2349
state,
2352
for(var char of to_chars(self)){
2353
cp = _b_.ord(char)
2354
if(unicode_tables.Ll[cp]){
2361
}else if(unicode_tables.Lu[cp] || unicode_tables.Lt[cp]){
2362
res += state ? char.toLowerCase() : char
2374
getitem = $B.$getattr(table, "__getitem__"),
2375
cp
2376
for(var char of to_chars(self)){
2377
cp = _b_.ord(char)
2381
if(typeof repl == "string"){
2382
res.push(repl)
2383
}else if(typeof repl == "number"){
2384
res.push(String.fromCharCode(repl))
2385
}
2394
str.upper = function(self){
2395
var $ = $B.args("upper", 1, {self: null}, ["self"],
2396
arguments, {}, null, null)
2397
return self.toUpperCase()
2398
}
2399
2402
["self", "width"], arguments, {}, null, null),
2403
len = str.__len__(self)
2404
if($.width <= len){
2405
return self
2406
}
2426
if(encoding !== undefined){
2427
// Arguments may be passed as keywords (cf. issue #1060)
2428
var $ = $B.args("str", 3, {arg: null, encoding: null, errors: null},
2429
["arg", "encoding", "errors"], arguments,
2430
{encoding: "utf-8", errors: "strict"}, null, null),
2431
encoding = $.encoding,
2432
errors = $.errors
2433
}
2434
if(typeof arg == "string" || arg instanceof String ||
2435
typeof arg == "number"){
2436
if(isFinite(arg)){
2437
return arg.toString()
2438
}
2444
// class or its subclasses, but the attribute __str__ of the
2445
// class metaclass (usually "type") or its subclasses (usually
2446
// "object")
2447
// The metaclass is the attribute __class__ of the class dictionary
2452
if(arg.__class__ && arg.__class__ === _b_.bytes &&
2453
encoding !== undefined){
2454
// str(bytes, encoding, errors) is equal to
2455
// bytes.decode(encoding, errors)
2458
// Implicit invocation of __str__ uses method __str__ on the class,
2459
// even if arg has an attribute __str__
2460
var klass = arg.__class__ || $B.get_class(arg)
2466
// if not better than object.__str__, try __repr__
2467
(arg.__class__ && arg.__class__ !== _b_.object &&
2468
method.$infos && method.$infos.__func__ === _b_.object.__str__)){
2469
var method = $B.$getattr(klass, "__repr__")
2475
if($B.debug > 1){console.log(err)}
2476
console.log("Warning - no method __str__ or __repr__, " +
2477
"default to toString", arg)
2484
if(cls === undefined){
2485
throw _b_.TypeError.$factory("str.__new__(): not enough arguments")
2509
var args = [],
2510
pos = 0
2511
if(arguments.length > 0){
2512
var args = [arguments[0].valueOf()],
2513
pos = 1
2514
for(var i = 1, len = arguments.length; i < len; i++){
2515
args[pos++] = arguments[i]
2532
// Function to parse the 2nd argument of format()
2533
$B.parse_format_spec = function(spec){
2537
var pos = 0,
2538
aligns = "<>=^",
2539
digits = "0123456789",
2540
types = "bcdeEfFgGnosxX%",
2542
if(align_pos != -1){
2543
if(spec.charAt(1) && aligns.indexOf(spec.charAt(1)) != -1){
2544
// If the second char is also an alignment specifier, the
2545
// first char is the fill value
2546
this.fill = spec.charAt(0)
2547
this.align = spec.charAt(1)
2548
pos = 2
2549
}else{
2550
// The first character defines alignment : fill defaults to ' '
2565
if(car == "+" || car == "-" || car == " "){
2566
this.sign = car
2567
pos++
2568
car = spec.charAt(pos)
2583
if(this.width === undefined){
2584
this.width = car
2585
}else{
2586
this.width += car
2587
}
2594
if(this.width === undefined && car == "{"){
2595
// Width is determined by a parameter
2596
var end_param_pos = spec.substr(pos).search("}")
2597
this.width = spec.substring(pos, end_param_pos)
2598
console.log("width", "[" + this.width + "]")
2599
pos += end_param_pos + 1
2600
}
2601
if(car == ","){
2602
this.comma = true
2603
pos++
2604
car = spec.charAt(pos)
2605
}
2606
if(car == "."){
2607
if(digits.indexOf(spec.charAt(pos + 1)) == -1){
2608
throw _b_.ValueError.$factory(
2609
"Missing precision in format spec")
2611
this.precision = spec.charAt(pos + 1)
2612
pos += 2
2613
car = spec.charAt(pos)
2614
while(car && digits.indexOf(car) > -1){
2621
if(car && types.indexOf(car) > -1){
2622
this.type = car
2623
pos++
2624
car = spec.charAt(pos)
2625
}
2626
if(pos !== spec.length){
2632
return (this.fill === undefined ? "" : _b_.str.$factory(this.fill)) +
2633
(this.align || "") +
2634
(this.sign || "") +
2635
(this.alternate ? "#" : "") +
2636
(this.sign_aware ? "0" : "") +
2637
(this.width || "") +
2638
(this.comma ? "," : "") +
2639
(this.precision ? "." + this.precision : "") +
2640
(this.type || "")
2645
if(fmt.width && s.length < fmt.width){
2646
var fill = fmt.fill || " ",
2647
align = fmt.align || "<",
2648
missing = fmt.width - s.length
2650
case "<":
2651
return s + fill.repeat(missing)
2652
case ">":
2653
return fill.repeat(missing) + s
2654
case "=":
2655
if("+-".indexOf(s.charAt(0)) > -1){
2656
return s.charAt(0) + fill.repeat(missing) + s.substr(1)
2660
case "^":
2661
var left = parseInt(missing / 2)
2662
return fill.repeat(left) + s + fill.repeat(missing - left)
2675
function fstring_error(msg, pos){
2676
error = Error(msg)
2677
error.position = pos
2678
throw error
2679
}
2680
2681
$B.parse_fstring = function(string){
2682
// Parse a f-string
2683
var elts = [],
2684
pos = 0,
2749
}else if(ctype == "debug"){
2750
// after the equal sign, whitespace are ignored and the only
2751
// valid characters are } and :
2752
while(string.charAt(i) == " "){i++}
2753
if(string.charAt(i) == "}"){
2754
// end of debug expression
2755
elts.push(current)
2756
ctype = null
2757
current = ""
2758
pos = i + 1
2759
}
2760
}else{
2761
// End of expression is the } matching the opening {
2762
// There may be nested braces
2763
var i = pos,
2764
nb_braces = 1,
2777
if(current.expression == ""){
2778
fstring_error("f-string: empty expression not allowed",
2779
pos)
2780
}
2790
// backslash is not allowed in expressions
2791
throw Error("f-string expression part cannot include a" +
2792
" backslash")
2799
throw Error("f-string: invalid conversion character:" +
2800
" expected 's', 'r', or 'a'")
2801
}else{
2815
if(string.substr(i, 3) == '"""'){
2816
var end = string.indexOf('"""', i + 3)
2817
if(end == -1){
2819
}else{
2820
var trs = string.substring(i, end + 3)
2821
trs = trs.replace("\n", "\\n\\")
2837
var cb = 0,
2838
fmt_complete = false
2839
for(var j = i + 1; j < string.length; j++){
2840
if(string[j] == '{'){
2841
if(string[j + 1] == '{'){
2842
j += 2
2843
}else{
2844
cb++
2845
}
2846
}else if(string[j] == '}'){
2847
if(string[j + 1] == '}'){
2848
j += 2
2849
}else if(cb == 0){
2850
fmt_complete = true
2851
var fmt = string.substring(i + 1, j)
2852
current.format = $B.parse_fstring(fmt)
2853
i = j
2854
break
2855
}else{
2856
cb--
2857
}
2858
}
2859
}
2860
if(! fmt_complete){
2861
fstring_error('invalid format', pos)
2862
}
2865
var ce = current.expression,
2866
last_char = ce.charAt(ce.length - 1),
2867
last_char_re = ('()'.indexOf(last_char) > -1 ? "\\" : "") + last_char
2876
}else{
2877
// add debug string
2878
tail = car
2879
while(string.charAt(i + 1).match(/\s/)){
2880
tail += string.charAt(i + 1)
2881
i++
2882
}
2884
elts.push(current.expression + tail)
2885
// remove trailing whitespace from expression
2886
while(ce.match(/\s$/)){
2887
ce = ce.substr(0, ce.length - 1)
2888
}
2889
current.expression = ce
2890
ctype = "debug"
2891
i++
2892
}
2906
for(var elt of elts){
2907
if(typeof elt == "object"){
2908
if(elt.fmt_pos !== undefined &&
2909
elt.expression.charAt(elt.fmt_pos) != ':'){
2910
console.log('mauvais format', string, elts)
2911
throw Error()
2912
}
2913
}
2914
}
2919
if(i >= 0x10000 && i <= 0x10FFFF){
2920
var code = (i - 0x10000)
2921
return String.fromCodePoint(0xD800 | (code >> 10)) +
2922
String.fromCodePoint(0xDC00 | (code & 0x3FF))
2923
}else{
2924
return String.fromCodePoint(i)
2925
}
2926
}
2929
if(c.length == 1){
2930
return c.charCodeAt(0)
2931
}
2932
var code = 0x10000
2933
code += (c.charCodeAt(0) & 0x03FF) << 10
2934
code += (c.charCodeAt(1) & 0x03FF)
2935
return code
2936
}
2937