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
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
Nov 8, 2021
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
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
2941 lines (2727 sloc)
88.8 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){
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)
967
$B.class_name($.other) + "'")
968
}
969
return $.self.valueOf().repeat($.other < 0 ? 0 : $.other)
976
function __newobj__(){
977
// __newobj__ is called with a generator as only argument
978
var $ = $B.args('__newobj__', 0, {}, [], arguments, {}, 'args', null),
979
args = $.args
980
var res = args[1]
981
res.__class__ = args[0]
982
return res
983
}
984
985
str.__reduce_ex__ = function(self){
986
return $B.fast_tuple([
987
__newobj__,
988
$B.fast_tuple([self.__class__ || _b_.str, self]),
989
_b_.None,
990
_b_.None])
991
}
992
997
chars = to_chars(self)
998
for(var i = 0; i < chars.length; i++){
999
var cp = _b_.ord(chars[i])
1000
if(t[cp] !== undefined){
1001
repl += t[cp]
1002
}else if($B.is_unicode_cn(cp)){
1015
repl += "\u200B" + chars[i] + ' '
1016
}else if(cp.toString(16) == 'feff'){
1017
repl += '\\ufeff'
1023
if(res.search('"') == -1 && res.search("'") == -1){
1024
return "'" + res + "'"
1025
}else if(self.search('"') == -1){
1026
return '"' + res + '"'
1027
}
1028
var qesc = new RegExp("'", "g") // to escape single quote
1029
res = "'" + res.replace(qesc, "\\'") + "'"
1033
str.__rmod__ = function(){
1034
var $ = $B.args('__rmod__', 2, {self: null, other: null},
1035
['self', 'other'], arguments, {}, null, null)
1036
return str.__mod__($.other, $.self)
1037
}
1038
1039
str.__rmul__ = function(self, other){
1040
if(_b_.isinstance(other, _b_.int)){
1041
other = _b_.int.numerator(other)
1042
var res = ''
1043
while(other > 0){
1044
res += self
1045
other--
1046
}
1047
return res
1048
}
1049
return _b_.NotImplemented
1050
}
1051
1052
str.__setattr__ = function(self, attr, value){
1053
if(typeof self === "string"){
1054
if(str.hasOwnProperty(attr)){
1056
attr + "' is read-only")
1057
}else{
1058
throw _b_.AttributeError.$factory(
1059
"'str' object has no attribute '" + attr + "'")
1060
}
1061
}
1062
// str subclass : use __dict__
1063
_b_.dict.$setitem(self.__dict__, attr, value)
1064
return $N
1065
}
1066
1067
str.__setitem__ = function(self, attr, value){
1068
throw _b_.TypeError.$factory(
1069
"'str' object does not support item assignment")
1072
var combining = []
1073
for(var cp = 0x300; cp <= 0x36F; cp++){
1074
combining.push(String.fromCharCode(cp))
1075
}
1079
var repl = '',
1080
chars = to_chars(self)
1081
if(chars.length == self.length){
1082
return self.replace(combining_re, "\u200B$1")
1083
}
1084
for(var i = 0; i < chars.length; i++){
1085
var cp = _b_.ord(chars[i])
1086
if(cp >= 0x300 && cp <= 0x36F){
1087
repl += "\u200B" + chars[i]
1088
}else{
1089
repl += chars[i]
1090
}
1091
}
1092
return repl
1102
$comp_func += "" // source code
1103
var $comps = {">": "gt", ">=": "ge", "<": "lt", "<=": "le"}
1114
str.capitalize = function(self){
1115
var $ = $B.args("capitalize", 1, {self}, ["self"],
1116
arguments, {}, null, null)
1120
return self.charAt(0).toUpperCase() + self.substr(1)
1121
}
1122
1123
str.casefold = function(self){
1124
var $ = $B.args("casefold", 1, {self}, ["self"],
1125
arguments, {}, null, null),
1126
res = "",
1127
char,
1128
cf,
1129
chars = to_chars($.self)
1130
1131
for(var i = 0, len = chars.length; i < len; i++){
1132
char = chars[i]
1133
cf = $B.unicode_casefold[char]
1134
if(cf){
1135
cf.forEach(function(cp){
1136
res += String.fromCharCode(cp)
1137
})
1138
}else{
1145
str.center = function(){
1146
var $ = $B.args("center", 3, {self: null, width: null, fillchar: null},
1147
["self", "width", "fillchar"],
1148
arguments, {fillchar:" "}, null, null),
1149
self = $.self
1153
var pad = parseInt(($.width - self.length) / 2),
1154
res = $.fillchar.repeat(pad)
1163
var $ = $B.args("count", 4, {self:null, sub:null, start:null, stop:null},
1164
["self", "sub", "start", "stop"], arguments, {start:null, stop:null},
1167
throw _b_.TypeError.$factory("Can't convert '" + $B.class_name($.sub) +
1168
"' object to str implicitly")
1169
}
1173
if($.stop !== null){
1174
_slice = _b_.slice.$factory($.start, $.stop)
1175
}else{
1176
_slice = _b_.slice.$factory($.start, $.self.length)
1177
}
1185
if($.start == $.self.length){
1186
return 1
1187
}else if(substr.length == 0){
1188
return 0
1189
}
1192
var n = 0,
1193
pos = 0
1194
while(pos < substr.length){
1195
pos = substr.indexOf($.sub, pos)
1206
str.encode = function(){
1207
var $ = $B.args("encode", 3, {self: null, encoding: null, errors: null},
1208
["self", "encoding", "errors"], arguments,
1209
{encoding: "utf-8", errors: "strict"}, null, null)
1210
if($.encoding == "rot13" || $.encoding == "rot_13"){
1213
for(var i = 0, len = $.self.length; i < len ; i++){
1214
var char = $.self.charAt(i)
1215
if(("a" <= char && char <= "m") || ("A" <= char && char <= "M")){
1216
res += String.fromCharCode(String.charCodeAt(char) + 13)
1217
}else if(("m" < char && char <= "z") ||
1218
("M" < char && char <= "Z")){
1219
res += String.fromCharCode(String.charCodeAt(char) - 13)
1228
// Return True if the string ends with the specified suffix, otherwise
1229
// return False. suffix can also be a tuple of suffixes to look for.
1230
// With optional start, test beginning at that position. With optional
1234
["self", "suffix", "start", "end"],
1235
arguments, {start: 0, end: null}, null, null)
1248
if(! _b_.isinstance(suffix, str)){
1249
throw _b_.TypeError.$factory(
1250
"endswith first arg must be str or a tuple of str, not int")
1251
}
1261
var $ = $B.args("expandtabs", 2, {self: null, tabsize: null},
1262
["self", "tabsize"], arguments, {tabsize: 8}, null, null)
1263
var s = $B.$GetInt($.tabsize),
1264
col = 0,
1265
pos = 0,
1266
res = "",
1267
chars = to_chars(self)
1268
if(s == 1){
1269
return self.replace(/\t/g," ")
1270
}
1271
while(pos < chars.length){
1272
var car = chars[pos]
1282
res += car
1283
col = 0
1284
break
1285
default:
1286
res += car
1287
col++
1288
break
1289
}
1290
pos++
1291
}
1292
return res
1296
// Return the lowest index in the string where substring sub is found,
1297
// such that sub is contained in the slice s[start:end]. Optional
1298
// arguments start and end are interpreted as in slice notation.
1301
{self: null, sub: null, start: null, end: null},
1302
["self", "sub", "start", "end"],
1303
arguments, {start: 0, end: null}, null, null)
1316
// Use .indexOf(), not .search(), to avoid conversion to reg exp
1317
var js_start = pypos2jspos($.self, $.start),
1318
js_end = pypos2jspos($.self, $.end),
1319
ix = $.self.substring(js_start, js_end).indexOf($.sub)
1320
if(ix == -1){
1321
return -1
1332
// a.x[z]!r:...
1333
// the object has attributes :
1334
// - name : "a"
1335
// - name_ext : [".x", "[z]"]
1336
// - conv : r
1337
// - spec : rest of string after :
1345
// No : in the string : it only contains a name
1346
name = fmt_string
1347
}else{
1348
// name is before the first ":"
1349
// spec (the format specification) is after
1350
name = elts[0]
1354
var elts = name.split("!")
1355
if(elts.length > 1){
1356
name = elts[0]
1357
conv = elts[1] // conversion flag
1361
// "name' may be a subscription or attribute
1362
// Put these "extensions" in the list "name_ext"
1363
function name_repl(match){
1364
name_ext.push(match)
1366
}
1367
var name_ext_re = /\.[_a-zA-Z][_a-zA-Z0-9]*|\[[_a-zA-Z][_a-zA-Z0-9]*\]|\[[0-9]+\]/g
1368
name = name.replace(name_ext_re, name_repl)
1369
}
1376
// Parse self to detect formatting instructions
1377
// Create a list "parts" made of sections of the string :
1378
// - elements of even rank are literal text
1379
// - elements of odd rank are "format objects", built from the
1380
// format strings in self (of the form {...})
1391
text += "{"
1392
pos += 2
1393
}else if(car == "}" && self.charAt(pos + 1) == "}"){
1400
// Store current literal text
1401
parts.push(text)
1402
1403
// Search the end of the format string, ie the } closing the
1404
// opening {. Since the string can contain other pairs {} for
1405
// nested formatting, an integer nb is incremented for each { and
1406
// decremented for each } ; the end of the format string is
1407
// reached when nb == 0
1408
var end = pos + 1,
1409
nb = 1
1410
while(end < _len){
1411
if(self.charAt(end) == "{"){nb++; end++}
1412
else if(self.charAt(end) == "}"){
1413
nb--; end++
1414
if(nb == 0){
1419
var fmt_obj = $B.parse_format(fmt_string)
1420
fmt_obj.raw_name = fmt_obj.name
1421
fmt_obj.raw_spec = fmt_obj.spec
1455
}else{
1456
text += car
1457
pos++
1458
}
1459
}
1460
if(text){
1461
parts.push(text)
1467
// Special management of keyword arguments if str.format is called by
1468
// str.format_map(mapping) : the argument "mapping" might not be a
1469
// dictionary
1470
var last_arg = $B.last(arguments)
1471
if(last_arg.$nat == "mapping"){
1472
var mapping = last_arg.mapping,
1473
getitem = $B.$getattr(mapping, "__getitem__")
1474
// Get the rest of the arguments
1475
var args = []
1476
for(var i = 0, len = arguments.length - 1; i < len; i++){
1477
args.push(arguments[i])
1478
}
1479
var $ = $B.args("format", 1, {self: null}, ["self"],
1480
args, {}, "$args", null)
1481
}else{
1482
var $ = $B.args("format", 1, {self: null}, ["self"],
1483
arguments, {}, "$args", "$kw"),
1484
mapping = $.$kw, // dictionary
1485
getitem = function(key){
1486
return _b_.dict.$getitem(mapping, key)
1487
}
1488
}
1504
1505
if(fmt.spec !== undefined){
1506
// "spec" may contain "nested replacement fields"
1507
// In this case, evaluate them using the positional
1508
// or keyword arguments passed to format()
1509
function replace_nested(name, key){
1510
if(/\d+/.exec(key)){
1511
// If key is numeric, search in positional
1512
// arguments
1513
return _b_.tuple.__getitem__($.$args,
1514
parseInt(key))
1515
}else{
1516
// Else try in keyword arguments
1517
return _b_.dict.__getitem__($.$kw, key)
1518
}
1519
}
1520
fmt.spec = fmt.spec.replace(/\{(.*?)\}/g,
1521
replace_nested)
1522
}
1524
// Numerical reference : use positional arguments
1525
var pos = parseInt(fmt.name),
1546
// If the conversion flag is set, first call a function to convert
1547
// the value
1548
if(fmt.conv == "a"){value = _b_.ascii(value)}
1549
else if(fmt.conv == "r"){value = _b_.repr(value)}
1550
else if(fmt.conv == "s"){value = _b_.str.$factory(value)}
1563
str.format_map = function(self, mapping){
1564
var $ = $B.args("format_map", 2, {self: null, mapping: null},
1565
['self', 'mapping'], arguments, {}, null, null)
1566
return str.format(self, {$nat: 'mapping', mapping})
1579
/* Return true if the string is empty or all characters in the string are
1580
ASCII, false otherwise. ASCII characters have code points in the range
1581
U+0000-U+007F. */
1590
str.isalnum = function(self){
1591
/* Return true if all characters in the string are alphanumeric and there
1592
is at least one character, false otherwise. A character c is alphanumeric
1593
if one of the following returns True: c.isalpha(), c.isdecimal(),
1594
c.isdigit(), or c.isnumeric(). */
1595
var $ = $B.args("isalnum", 1, {self: null}, ["self"],
1596
arguments, {}, null, null),
1597
cp
1598
for(var char of to_chars(self)){
1599
cp = _b_.ord(char)
1600
if(unicode_tables.Ll[cp] ||
1601
unicode_tables.Lu[cp] ||
1602
unicode_tables.Lm[cp] ||
1603
unicode_tables.Lt[cp] ||
1604
unicode_tables.Lo[cp] ||
1605
unicode_tables.Nd[cp] ||
1606
unicode_tables.digits[cp] ||
1607
unicode_tables.numeric[cp]){
1608
continue
1609
}
1610
return false
1611
}
1612
return true
1613
}
1614
1615
str.isalpha = function(self){
1616
/* Return true if all characters in the string are alphabetic and there is
1617
at least one character, false otherwise. Alphabetic characters are those
1618
characters defined in the Unicode character database as "Letter", i.e.,
1619
those with general category property being one of "Lm", "Lt", "Lu", "Ll",
1620
or "Lo". */
1621
var $ = $B.args("isalpha", 1, {self: null}, ["self"],
1622
arguments, {}, null, null),
1623
cp
1624
for(var char of to_chars(self)){
1625
cp = _b_.ord(char)
1626
if(unicode_tables.Ll[cp] ||
1627
unicode_tables.Lu[cp] ||
1628
unicode_tables.Lm[cp] ||
1629
unicode_tables.Lt[cp] ||
1630
unicode_tables.Lo[cp]){
1631
continue
1632
}
1633
return false
1634
}
1635
return true
1636
}
1637
1638
str.isdecimal = function(self){
1639
/* Return true if all characters in the string are decimal characters and
1640
there is at least one character, false otherwise. Decimal characters are
1641
those that can be used to form numbers in base 10, e.g. U+0660,
1642
ARABIC-INDIC DIGIT ZERO. Formally a decimal character is a character in
1643
the Unicode General Category "Nd". */
1644
var $ = $B.args("isdecimal", 1, {self: null}, ["self"],
1645
arguments, {}, null, null),
1646
cp
1647
for(var char of to_chars(self)){
1648
cp = _b_.ord(char)
1649
if(! unicode_tables.Nd[cp]){
1650
return false
1651
}
1652
}
1653
return self.length > 0
1654
}
1655
1656
str.isdigit = function(self){
1657
/* Return true if all characters in the string are digits and there is at
1658
least one character, false otherwise. */
1659
var $ = $B.args("isdigit", 1, {self: null}, ["self"],
1660
arguments, {}, null, null),
1661
cp
1662
for(var char of to_chars(self)){
1663
cp = _b_.ord(char)
1664
if(! unicode_tables.digits[cp]){
1665
return false
1666
}
1667
}
1668
return self.length > 0
1669
}
1670
1671
str.isidentifier = function(self){
1672
/* Return true if the string is a valid identifier according to the
1673
language definition. */
1674
var $ = $B.args("isidentifier", 1, {self: null}, ["self"],
1678
}
1679
var chars = to_chars(self)
1680
if(unicode_tables.XID_Start[_b_.ord(chars[0])] === undefined){
1683
for(var char of chars){
1684
var cp = _b_.ord(char)
1685
if(unicode_tables.XID_Continue[cp] === undefined){
1686
return false
1687
}
1688
}
1689
}
1690
return true
1691
}
1692
1693
str.islower = function(self){
1694
/* Return true if all cased characters 4 in the string are lowercase and
1695
there is at least one cased character, false otherwise. */
1696
var $ = $B.args("islower", 1, {self: null}, ["self"],
1697
arguments, {}, null, null),
1698
has_cased = false,
1701
for(var char of to_chars(self)){
1702
cp = _b_.ord(char)
1703
if(unicode_tables.Ll[cp]){
1704
has_cased = true
1705
continue
1706
}else if(unicode_tables.Lu[cp] || unicode_tables.Lt[cp]){
1707
return false
1708
}
1709
}
1710
return has_cased
1711
}
1712
1713
str.isnumeric = function(self){
1714
/* Return true if all characters in the string are numeric characters, and
1715
there is at least one character, false otherwise. Numeric characters
1716
include digit characters, and all characters that have the Unicode numeric
1717
value property, e.g. U+2155, VULGAR FRACTION ONE FIFTH. Formally, numeric
1718
characters are those with the property value Numeric_Type=Digit,
1719
Numeric_Type=Decimal or Numeric_Type=Numeric.*/
1720
var $ = $B.args("isnumeric", 1, {self: null}, ["self"],
1721
arguments, {}, null, null)
1730
var unprintable = {},
1731
unprintable_gc = ['Cc', 'Cf', 'Co', 'Cs','Zl', 'Zp', 'Zs']
1732
1733
str.isprintable = function(self){
1734
/* Return true if all characters in the string are printable or the string
1735
is empty, false otherwise. Nonprintable characters are those characters
1736
defined in the Unicode character database as "Other" or "Separator",
1737
excepting the ASCII space (0x20) which is considered printable. */
1738
1739
// Set unprintable if not set yet
1740
if(Object.keys(unprintable).length == 0){
1741
for(var i = 0; i < unprintable_gc.length; i++){
1742
var table = unicode_tables[unprintable_gc[i]]
1753
return false
1754
}
1755
}
1756
return true
1757
}
1758
1759
str.isspace = function(self){
1760
/* Return true if there are only whitespace characters in the string and
1761
there is at least one character, false otherwise.
1762
1763
A character is whitespace if in the Unicode character database, either its
1764
general category is Zs ("Separator, space"), or its bidirectional class is
1765
one of WS, B, or S.*/
1766
var $ = $B.args("isspace", 1, {self: null}, ["self"],
1767
arguments, {}, null, null),
1768
cp
1769
for(var char of to_chars(self)){
1770
cp = _b_.ord(char)
1771
if(! unicode_tables.Zs[cp] &&
1772
$B.unicode_bidi_whitespace.indexOf(cp) == -1){
1773
return false
1774
}
1775
}
1776
return self.length > 0
1777
}
1778
1779
str.istitle = function(self){
1780
/* Return true if the string is a titlecased string and there is at least
1781
one character, for example uppercase characters may only follow uncased
1782
characters and lowercase characters only cased ones. Return false
1783
otherwise. */
1784
var $ = $B.args("istitle", 1, {self: null}, ["self"],
1785
arguments, {}, null, null)
1786
return self.length > 0 && str.title(self) == self
1787
}
1788
1789
str.isupper = function(self){
1790
/* Return true if all cased characters 4 in the string are lowercase and
1791
there is at least one cased character, false otherwise. */
1792
var $ = $B.args("islower", 1, {self: null}, ["self"],
1793
arguments, {}, null, null),
1797
for(var char of to_chars(self)){
1798
cp = _b_.ord(char)
1799
if(unicode_tables.Lu[cp]){
1800
is_upper = true
1801
continue
1802
}else if(unicode_tables.Ll[cp] || unicode_tables.Lt[cp]){
1821
throw _b_.TypeError.$factory("sequence item " + count +
1822
": expected str instance, " + $B.class_name(obj2) +
1823
" found")
1824
}
1837
var $ = $B.args("ljust", 3, {self: null, width: null, fillchar:null},
1838
["self", "width", "fillchar"],
1842
if($.width <= len){
1843
return self
1844
}
1845
return self + $.fillchar.repeat($.width - len)
1848
str.lower = function(self){
1849
var $ = $B.args("lower", 1, {self: null}, ["self"],
1850
arguments, {}, null, null)
1851
return self.toLowerCase()
1852
}
1853
1856
arguments, {chars:_b_.None}, null, null),
1857
self = $.self,
1858
chars = $.chars
1859
if(chars === _b_.None){
1860
return self.trimStart()
1862
while(self.length > 0){
1863
var flag = false
1864
for(var char of chars){
1865
if(self.startsWith(char)){
1866
self = self.substr(char.length)
1867
flag = true
1868
break
1869
}
1870
}
1871
if(! flag){
1872
return $.self.surrogates ? $B.String(self) : self
1880
var $ = $B.args("maketrans", 3, {x: null, y: null, z: null},
1881
["x", "y", "z"], arguments, {y: null, z: null}, null, null)
1886
// If there is only one argument, it must be a dictionary mapping
1887
// Unicode ordinals (integers) or characters (strings of length 1) to
1888
// Unicode ordinals, strings (of arbitrary lengths) or None. Character
1890
if(! _b_.isinstance($.x, _b_.dict)){
1891
throw _b_.TypeError.$factory(
1892
"maketrans only argument must be a dict")
1895
for(var i = 0, len = items.length; i < len; i++){
1896
var k = items[i][0],
1897
v = items[i][1]
1898
if(! _b_.isinstance(k, _b_.int)){
1899
if(_b_.isinstance(k, _b_.str) && k.length == 1){
1900
k = _b_.ord(k)
1901
}else{throw _b_.TypeError.$factory("dictionary key " + k +
1904
if(v !== _b_.None && ! _b_.isinstance(v, [_b_.int, _b_.str])){
1905
throw _b_.TypeError.$factory("dictionary value " + v +
1913
// and in the resulting dictionary, each character in x will be mapped
1914
// to the character at the same position in y
1917
}else if($.x.length !== $.y.length){
1918
throw _b_.TypeError.$factory(
1919
"maketrans arguments must be strings or same length")
1925
if(! _b_.isinstance($.z, _b_.str)){
1926
throw _b_.TypeError.$factory(
1927
"maketrans third argument must be a string")
1949
var $ = $B.args("partition", 2, {self: null, sep: null}, ["self", "sep"],
1950
arguments, {}, null, null)
1957
if(i == -1){
1958
return _b_.tuple.$factory([$.self, "", ""])
1959
}
1960
return _b_.tuple.$factory([chars.slice(0, i).join(''), $.sep,
1961
chars.slice(i + $.sep.length).join('')])
1964
str.removeprefix = function(){
1965
var $ = $B.args("removeprefix", 2, {self: null, prefix: null},
1966
["self", "prefix"], arguments, {}, null, null)
1967
if(!_b_.isinstance($.prefix, str)){
1968
throw _b_.ValueError.$factory("prefix should be str, not " +
1969
`'${$B.class_name($.prefix)}'`)
1970
}
1971
if(str.startswith($.self, $.prefix)){
1972
return $.self.substr($.prefix.length)
1973
}
1974
return $.self.substr(0)
1975
}
1976
1977
str.removesuffix = function(){
1978
var $ = $B.args("removesuffix", 2, {self: null, prefix: null},
1979
["self", "suffix"], arguments, {}, null, null)
1980
if(!_b_.isinstance($.suffix, str)){
1981
throw _b_.ValueError.$factory("suffix should be str, not " +
1982
`'${$B.class_name($.prefix)}'`)
1983
}
1984
if($.suffix.length > 0 && str.endswith($.self, $.suffix)){
1985
return $.self.substr(0, $.self.length - $.suffix.length)
1986
}
1987
return $.self.substr(0)
1988
}
1989
1990
function $re_escape(str){
1991
var specials = "[.*+?|()$^"
1992
for(var i = 0, len = specials.length; i < len; i++){
1993
var re = new RegExp("\\"+specials.charAt(i), "g")
1994
str = str.replace(re, "\\"+specials.charAt(i))
1995
}
1996
return str
2004
{self: null, old: null, new: null, count: null},
2005
["self", "old", "new", "count"],
2006
arguments, {count: -1}, null, null),
2007
count = $.count,
2008
self = $.self,
2009
old = $.old,
2012
check_str(old, "replace() argument 1 ")
2013
check_str(_new, "replace() argument 2 ")
2021
if(count == 0){
2022
return self
2023
}
2024
if(count.__class__ == $B.long_int){
2025
count = parseInt(count.value)
2026
}
2028
if(_new == ""){
2029
return self
2030
}
2031
if(self == ""){
2032
return _new
2033
}
2034
var elts = self.split("")
2035
if(count > -1 && elts.length >= count){
2036
var rest = elts.slice(count).join("")
2037
return _new + elts.slice(0, count).join(_new) + rest
2063
res = res.substr(0, pos) + _new + res.substr(pos + old.length)
2064
pos = pos + _new.length
2065
count--
2071
// Return the highest index in the string where substring sub is found,
2072
// such that sub is contained within s[start:end]. Optional arguments
2075
{self: null, sub: null, start: null, end: null},
2076
["self", "sub", "start", "end"],
2077
arguments, {start: 0, end: null}, null, null)
2082
var len = str.__len__($.self),
2083
sub_len = str.__len__($.sub)
2084
2085
if(sub_len == 0){
2086
if($.js_start > len){
2093
// Use .indexOf(), not .search(), to avoid conversion to reg exp
2094
var js_start = pypos2jspos($.self, $.start),
2095
js_end = pypos2jspos($.self, $.end),
2096
ix = $.self.substring(js_start, js_end).lastIndexOf($.sub)
2097
if(ix == -1){
2098
return -1
2113
var $ = $B.args("rjust",3,
2114
{self: null, width: null, fillchar: null},
2115
["self", "width", "fillchar"],
2116
arguments, {fillchar: " "}, null, null)
2126
var $ = $B.args("rpartition", 2, {self: null, sep: null}, ["self", "sep"],
2127
arguments, {}, null, null)
2131
var items = str.partition(self, sep).reverse()
2132
for(var i = 0; i < items.length; i++){
2133
items[i] = items[i].split("").reverse().join("")
2139
var $ = $B.args("rsplit", 3, {self: null, sep: null, maxsplit: null},
2140
["self", "sep", "maxsplit"], arguments,
2141
{sep: _b_.None, maxsplit: -1}, null, null),
2142
sep = $.sep
2145
var rev_str = reverse($.self),
2146
rev_sep = sep === _b_.None ? sep : reverse($.sep),
2157
str.rstrip = function(self, x){
2158
var $ = $B.args("rstrip", 2, {self: null, chars: null}, ["self", "chars"],
2159
arguments, {chars: _b_.None}, null, null),
2160
self = $.self,
2161
chars = $.chars
2162
if(chars === _b_.None){
2163
return self.trimEnd()
2165
while(self.length > 0){
2166
var flag = false
2167
for(var char of chars){
2168
if(self.endsWith(char)){
2169
self = self.substr(0, self.length - char.length)
2170
flag = true
2171
break
2172
}
2173
}
2174
if(! flag){
2175
return $.self.surrogates ? $B.String(self) : self
2182
var $ = $B.args("split", 3, {self: null, sep: null, maxsplit: null},
2183
["self", "sep", "maxsplit"], arguments,
2184
{sep: _b_.None, maxsplit: -1}, null, null),
2185
sep = $.sep,
2186
maxsplit = $.maxsplit,
2187
self = $.self,
2188
pos = 0
2189
if(maxsplit.__class__ === $B.long_int){
2190
maxsplit = parseInt(maxsplit.value)
2191
}
2192
if(sep == ""){
2193
throw _b_.ValueError.$factory("empty separator")
2194
}
2198
while(pos < self.length && self.charAt(pos).search(/\s/) > -1){
2199
pos++
2200
}
2201
if(pos === self.length - 1){
2202
return [self]
2203
}
2207
if(name == ""){
2208
name = self.charAt(pos)
2209
}else{
2210
name += self.charAt(pos)
2211
}
2258
str.splitlines = function(self) {
2259
var $ = $B.args('splitlines', 2, {self: null, keepends: null},
2260
['self','keepends'], arguments, {keepends: false},
2261
null, null)
2262
if(!_b_.isinstance($.keepends,[_b_.bool, _b_.int])){
2263
throw _b_.TypeError('integer argument expected, got '+
2266
var keepends = _b_.int.$factory($.keepends),
2267
res = [],
2268
self = $.self,
2269
start = 0,
2270
pos = 0
2271
if(!self.length){
2275
if(self.substr(pos, 2) == '\r\n'){
2276
res.push(self.slice(start, keepends ? pos + 2 : pos))
2277
start = pos = pos+2
2278
}else if(self[pos] == '\r' || self[pos] == '\n'){
2279
res.push(self.slice(start, keepends ? pos+1 : pos))
2280
start = pos = pos+1
2281
}else{
2282
pos++
2283
}
2284
}
2285
if(start < self.length){
2286
res.push(self.slice(start))
2287
}
2292
// Return True if string starts with the prefix, otherwise return False.
2293
// prefix can also be a tuple of prefixes to look for. With optional
2294
// start, test string beginning at that position. With optional end,
2296
var $ = $B.args("startswith", 4,
2297
{self: null, prefix: null, start: null, end: null},
2298
["self", "prefix", "start", "end"],
2299
arguments, {start: 0, end: null}, null, null)
2309
if(! _b_.isinstance(prefix, str)){
2310
throw _b_.TypeError.$factory("endswith first arg must be str " +
2311
"or a tuple of str, not int")
2312
}
2313
if(s.substr(0, prefix.length) == prefix){
2314
return true
2315
}
2321
var $ = $B.args("strip", 2, {self: null, chars: null}, ["self", "chars"],
2322
arguments, {chars: _b_.None}, null, null)
2329
str.swapcase = function(self){
2330
var $ = $B.args("swapcase", 1, {self}, ["self"],
2331
arguments, {}, null, null),
2332
res = "",
2333
cp
2334
2335
for(var char of to_chars(self)){
2336
cp = _b_.ord(char)
2337
if(unicode_tables.Ll[cp]){
2338
res += char.toUpperCase()
2339
}else if(unicode_tables.Lu[cp]){
2340
res += char.toLowerCase()
2343
}
2344
}
2345
return res
2346
}
2347
2348
str.title = function(self){
2349
var $ = $B.args("title", 1, {self}, ["self"],
2350
arguments, {}, null, null),
2351
state,
2354
for(var char of to_chars(self)){
2355
cp = _b_.ord(char)
2356
if(unicode_tables.Ll[cp]){
2363
}else if(unicode_tables.Lu[cp] || unicode_tables.Lt[cp]){
2364
res += state ? char.toLowerCase() : char
2376
getitem = $B.$getattr(table, "__getitem__"),
2377
cp
2378
for(var char of to_chars(self)){
2379
cp = _b_.ord(char)
2383
if(typeof repl == "string"){
2384
res.push(repl)
2385
}else if(typeof repl == "number"){
2386
res.push(String.fromCharCode(repl))
2387
}
2396
str.upper = function(self){
2397
var $ = $B.args("upper", 1, {self: null}, ["self"],
2398
arguments, {}, null, null)
2399
return self.toUpperCase()
2400
}
2401
2404
["self", "width"], arguments, {}, null, null),
2405
len = str.__len__(self)
2406
if($.width <= len){
2407
return self
2408
}
2428
if(encoding !== undefined){
2429
// Arguments may be passed as keywords (cf. issue #1060)
2430
var $ = $B.args("str", 3, {arg: null, encoding: null, errors: null},
2431
["arg", "encoding", "errors"], arguments,
2432
{encoding: "utf-8", errors: "strict"}, null, null),
2433
encoding = $.encoding,
2434
errors = $.errors
2435
}
2436
if(typeof arg == "string" || arg instanceof String ||
2437
typeof arg == "number"){
2438
if(isFinite(arg)){
2439
return arg.toString()
2440
}
2446
// class or its subclasses, but the attribute __str__ of the
2447
// class metaclass (usually "type") or its subclasses (usually
2448
// "object")
2449
// The metaclass is the attribute __class__ of the class dictionary
2454
if(arg.__class__ && arg.__class__ === _b_.bytes &&
2455
encoding !== undefined){
2456
// str(bytes, encoding, errors) is equal to
2457
// bytes.decode(encoding, errors)
2460
// Implicit invocation of __str__ uses method __str__ on the class,
2461
// even if arg has an attribute __str__
2462
var klass = arg.__class__ || $B.get_class(arg)
2468
// if not better than object.__str__, try __repr__
2469
(arg.__class__ && arg.__class__ !== _b_.object &&
2477
if($B.debug > 1){console.log(err)}
2478
console.log("Warning - no method __str__ or __repr__, " +
2479
"default to toString", arg)
2486
if(cls === undefined){
2487
throw _b_.TypeError.$factory("str.__new__(): not enough arguments")
2511
var args = [],
2512
pos = 0
2513
if(arguments.length > 0){
2514
var args = [arguments[0].valueOf()],
2515
pos = 1
2516
for(var i = 1, len = arguments.length; i < len; i++){
2517
args[pos++] = arguments[i]
2534
// Function to parse the 2nd argument of format()
2535
$B.parse_format_spec = function(spec){
2539
var pos = 0,
2540
aligns = "<>=^",
2541
digits = "0123456789",
2542
types = "bcdeEfFgGnosxX%",
2544
if(align_pos != -1){
2545
if(spec.charAt(1) && aligns.indexOf(spec.charAt(1)) != -1){
2546
// If the second char is also an alignment specifier, the
2547
// first char is the fill value
2548
this.fill = spec.charAt(0)
2549
this.align = spec.charAt(1)
2550
pos = 2
2551
}else{
2552
// The first character defines alignment : fill defaults to ' '
2567
if(car == "+" || car == "-" || car == " "){
2568
this.sign = car
2569
pos++
2570
car = spec.charAt(pos)
2585
if(this.width === undefined){
2586
this.width = car
2587
}else{
2588
this.width += car
2589
}
2596
if(this.width === undefined && car == "{"){
2597
// Width is determined by a parameter
2598
var end_param_pos = spec.substr(pos).search("}")
2599
this.width = spec.substring(pos, end_param_pos)
2600
console.log("width", "[" + this.width + "]")
2601
pos += end_param_pos + 1
2602
}
2603
if(car == ","){
2604
this.comma = true
2605
pos++
2606
car = spec.charAt(pos)
2607
}
2608
if(car == "."){
2609
if(digits.indexOf(spec.charAt(pos + 1)) == -1){
2610
throw _b_.ValueError.$factory(
2611
"Missing precision in format spec")
2613
this.precision = spec.charAt(pos + 1)
2614
pos += 2
2615
car = spec.charAt(pos)
2616
while(car && digits.indexOf(car) > -1){
2623
if(car && types.indexOf(car) > -1){
2624
this.type = car
2625
pos++
2626
car = spec.charAt(pos)
2627
}
2628
if(pos !== spec.length){
2634
return (this.fill === undefined ? "" : _b_.str.$factory(this.fill)) +
2635
(this.align || "") +
2636
(this.sign || "") +
2637
(this.alternate ? "#" : "") +
2638
(this.sign_aware ? "0" : "") +
2639
(this.width || "") +
2640
(this.comma ? "," : "") +
2641
(this.precision ? "." + this.precision : "") +
2642
(this.type || "")
2647
if(fmt.width && s.length < fmt.width){
2648
var fill = fmt.fill || " ",
2649
align = fmt.align || "<",
2650
missing = fmt.width - s.length
2652
case "<":
2653
return s + fill.repeat(missing)
2654
case ">":
2655
return fill.repeat(missing) + s
2656
case "=":
2657
if("+-".indexOf(s.charAt(0)) > -1){
2658
return s.charAt(0) + fill.repeat(missing) + s.substr(1)
2662
case "^":
2663
var left = parseInt(missing / 2)
2664
return fill.repeat(left) + s + fill.repeat(missing - left)
2678
function fstring_error(msg, pos){
2679
error = Error(msg)
2680
error.position = pos
2681
throw error
2682
}
2683
2684
$B.parse_fstring = function(string){
2685
// Parse a f-string
2686
var elts = [],
2687
pos = 0,
2752
}else if(ctype == "debug"){
2753
// after the equal sign, whitespace are ignored and the only
2754
// valid characters are } and :
2755
while(string.charAt(i) == " "){i++}
2756
if(string.charAt(i) == "}"){
2757
// end of debug expression
2758
elts.push(current)
2759
ctype = null
2760
current = ""
2761
pos = i + 1
2762
}
2763
}else{
2764
// End of expression is the } matching the opening {
2765
// There may be nested braces
2766
var i = pos,
2767
nb_braces = 1,
2780
if(current.expression == ""){
2781
fstring_error("f-string: empty expression not allowed",
2782
pos)
2783
}
2793
// backslash is not allowed in expressions
2794
throw Error("f-string expression part cannot include a" +
2795
" backslash")
2802
throw Error("f-string: invalid conversion character:" +
2803
" expected 's', 'r', or 'a'")
2804
}else{
2818
if(string.substr(i, 3) == '"""'){
2819
var end = string.indexOf('"""', i + 3)
2820
if(end == -1){
2822
}else{
2823
var trs = string.substring(i, end + 3)
2824
trs = trs.replace("\n", "\\n\\")
2840
var cb = 0,
2841
fmt_complete = false
2842
for(var j = i + 1; j < string.length; j++){
2843
if(string[j] == '{'){
2844
if(string[j + 1] == '{'){
2845
j += 2
2846
}else{
2847
cb++
2848
}
2849
}else if(string[j] == '}'){
2850
if(string[j + 1] == '}'){
2851
j += 2
2852
}else if(cb == 0){
2853
fmt_complete = true
2854
var fmt = string.substring(i + 1, j)
2855
current.format = $B.parse_fstring(fmt)
2856
i = j
2857
break
2858
}else{
2859
cb--
2860
}
2861
}
2862
}
2863
if(! fmt_complete){
2864
fstring_error('invalid format', pos)
2865
}
2868
var ce = current.expression,
2869
last_char = ce.charAt(ce.length - 1),
2870
last_char_re = ('()'.indexOf(last_char) > -1 ? "\\" : "") + last_char
2879
}else{
2880
// add debug string
2881
tail = car
2882
while(string.charAt(i + 1).match(/\s/)){
2883
tail += string.charAt(i + 1)
2884
i++
2885
}
2887
elts.push(current.expression + tail)
2888
// remove trailing whitespace from expression
2889
while(ce.match(/\s$/)){
2890
ce = ce.substr(0, ce.length - 1)
2891
}
2892
current.expression = ce
2893
ctype = "debug"
2894
i++
2895
}
2909
for(var elt of elts){
2910
if(typeof elt == "object"){
2911
if(elt.fmt_pos !== undefined &&
2912
elt.expression.charAt(elt.fmt_pos) != ':'){
2913
console.log('mauvais format', string, elts)
2914
throw Error()
2915
}
2916
}
2917
}
2922
if(i >= 0x10000 && i <= 0x10FFFF){
2923
var code = (i - 0x10000)
2924
return String.fromCodePoint(0xD800 | (code >> 10)) +
2925
String.fromCodePoint(0xDC00 | (code & 0x3FF))
2926
}else{
2927
return String.fromCodePoint(i)
2928
}
2929
}
2932
if(c.length == 1){
2933
return c.charCodeAt(0)
2934
}
2935
var code = 0x10000
2936
code += (c.charCodeAt(0) & 0x03FF) << 10
2937
code += (c.charCodeAt(1) & 0x03FF)
2938
return code
2939
}
2940