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
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
2933 lines (2720 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)
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)){
1021
if(res.search('"') == -1 && res.search("'") == -1){
1022
return "'" + res + "'"
1023
}else if(self.search('"') == -1){
1024
return '"' + res + '"'
1025
}
1026
var qesc = new RegExp("'", "g") // to escape single quote
1027
res = "'" + res.replace(qesc, "\\'") + "'"
1031
str.__rmul__ = function(self, other){
1032
if(_b_.isinstance(other, _b_.int)){
1033
other = _b_.int.numerator(other)
1034
var res = ''
1035
while(other > 0){
1036
res += self
1037
other--
1038
}
1039
return res
1040
}
1041
return _b_.NotImplemented
1042
}
1043
1044
str.__setattr__ = function(self, attr, value){
1045
if(typeof self === "string"){
1046
if(str.hasOwnProperty(attr)){
1048
attr + "' is read-only")
1049
}else{
1050
throw _b_.AttributeError.$factory(
1051
"'str' object has no attribute '" + attr + "'")
1052
}
1053
}
1054
// str subclass : use __dict__
1055
_b_.dict.$setitem(self.__dict__, attr, value)
1056
return $N
1057
}
1058
1059
str.__setitem__ = function(self, attr, value){
1060
throw _b_.TypeError.$factory(
1061
"'str' object does not support item assignment")
1064
var combining = []
1065
for(var cp = 0x300; cp <= 0x36F; cp++){
1066
combining.push(String.fromCharCode(cp))
1067
}
1071
var repl = '',
1072
chars = to_chars(self)
1073
if(chars.length == self.length){
1074
return self.replace(combining_re, "\u200B$1")
1075
}
1076
for(var i = 0; i < chars.length; i++){
1077
var cp = _b_.ord(chars[i])
1078
if(cp >= 0x300 && cp <= 0x36F){
1079
repl += "\u200B" + chars[i]
1080
}else{
1081
repl += chars[i]
1082
}
1083
}
1084
return repl
1094
$comp_func += "" // source code
1095
var $comps = {">": "gt", ">=": "ge", "<": "lt", "<=": "le"}
1106
str.capitalize = function(self){
1107
var $ = $B.args("capitalize", 1, {self}, ["self"],
1108
arguments, {}, null, null)
1112
return self.charAt(0).toUpperCase() + self.substr(1)
1113
}
1114
1115
str.casefold = function(self){
1116
var $ = $B.args("casefold", 1, {self}, ["self"],
1117
arguments, {}, null, null),
1118
res = "",
1119
char,
1120
cf,
1121
chars = to_chars($.self)
1122
1123
for(var i = 0, len = chars.length; i < len; i++){
1124
char = chars[i]
1125
cf = $B.unicode_casefold[char]
1126
if(cf){
1127
cf.forEach(function(cp){
1128
res += String.fromCharCode(cp)
1129
})
1130
}else{
1137
str.center = function(){
1138
var $ = $B.args("center", 3, {self: null, width: null, fillchar: null},
1139
["self", "width", "fillchar"],
1140
arguments, {fillchar:" "}, null, null),
1141
self = $.self
1145
var pad = parseInt(($.width - self.length) / 2),
1146
res = $.fillchar.repeat(pad)
1155
var $ = $B.args("count", 4, {self:null, sub:null, start:null, stop:null},
1156
["self", "sub", "start", "stop"], arguments, {start:null, stop:null},
1159
throw _b_.TypeError.$factory("Can't convert '" + $B.class_name($.sub) +
1160
"' object to str implicitly")
1161
}
1165
if($.stop !== null){
1166
_slice = _b_.slice.$factory($.start, $.stop)
1167
}else{
1168
_slice = _b_.slice.$factory($.start, $.self.length)
1169
}
1177
if($.start == $.self.length){
1178
return 1
1179
}else if(substr.length == 0){
1180
return 0
1181
}
1184
var n = 0,
1185
pos = 0
1186
while(pos < substr.length){
1187
pos = substr.indexOf($.sub, pos)
1198
str.encode = function(){
1199
var $ = $B.args("encode", 3, {self: null, encoding: null, errors: null},
1200
["self", "encoding", "errors"], arguments,
1201
{encoding: "utf-8", errors: "strict"}, null, null)
1202
if($.encoding == "rot13" || $.encoding == "rot_13"){
1205
for(var i = 0, len = $.self.length; i < len ; i++){
1206
var char = $.self.charAt(i)
1207
if(("a" <= char && char <= "m") || ("A" <= char && char <= "M")){
1208
res += String.fromCharCode(String.charCodeAt(char) + 13)
1209
}else if(("m" < char && char <= "z") ||
1210
("M" < char && char <= "Z")){
1211
res += String.fromCharCode(String.charCodeAt(char) - 13)
1220
// Return True if the string ends with the specified suffix, otherwise
1221
// return False. suffix can also be a tuple of suffixes to look for.
1222
// With optional start, test beginning at that position. With optional
1226
["self", "suffix", "start", "end"],
1227
arguments, {start: 0, end: null}, null, null)
1240
if(! _b_.isinstance(suffix, str)){
1241
throw _b_.TypeError.$factory(
1242
"endswith first arg must be str or a tuple of str, not int")
1243
}
1253
var $ = $B.args("expandtabs", 2, {self: null, tabsize: null},
1254
["self", "tabsize"], arguments, {tabsize: 8}, null, null)
1255
var s = $B.$GetInt($.tabsize),
1256
col = 0,
1257
pos = 0,
1258
res = "",
1259
chars = to_chars(self)
1260
if(s == 1){
1261
return self.replace(/\t/g," ")
1262
}
1263
while(pos < chars.length){
1264
var car = chars[pos]
1274
res += car
1275
col = 0
1276
break
1277
default:
1278
res += car
1279
col++
1280
break
1281
}
1282
pos++
1283
}
1284
return res
1288
// Return the lowest index in the string where substring sub is found,
1289
// such that sub is contained in the slice s[start:end]. Optional
1290
// arguments start and end are interpreted as in slice notation.
1293
{self: null, sub: null, start: null, end: null},
1294
["self", "sub", "start", "end"],
1295
arguments, {start: 0, end: null}, null, null)
1308
// Use .indexOf(), not .search(), to avoid conversion to reg exp
1309
var js_start = pypos2jspos($.self, $.start),
1310
js_end = pypos2jspos($.self, $.end),
1311
ix = $.self.substring(js_start, js_end).indexOf($.sub)
1312
if(ix == -1){
1313
return -1
1324
// a.x[z]!r:...
1325
// the object has attributes :
1326
// - name : "a"
1327
// - name_ext : [".x", "[z]"]
1328
// - conv : r
1329
// - spec : rest of string after :
1337
// No : in the string : it only contains a name
1338
name = fmt_string
1339
}else{
1340
// name is before the first ":"
1341
// spec (the format specification) is after
1342
name = elts[0]
1346
var elts = name.split("!")
1347
if(elts.length > 1){
1348
name = elts[0]
1349
conv = elts[1] // conversion flag
1353
// "name' may be a subscription or attribute
1354
// Put these "extensions" in the list "name_ext"
1355
function name_repl(match){
1356
name_ext.push(match)
1358
}
1359
var name_ext_re = /\.[_a-zA-Z][_a-zA-Z0-9]*|\[[_a-zA-Z][_a-zA-Z0-9]*\]|\[[0-9]+\]/g
1360
name = name.replace(name_ext_re, name_repl)
1361
}
1368
// Parse self to detect formatting instructions
1369
// Create a list "parts" made of sections of the string :
1370
// - elements of even rank are literal text
1371
// - elements of odd rank are "format objects", built from the
1372
// format strings in self (of the form {...})
1383
text += "{"
1384
pos += 2
1385
}else if(car == "}" && self.charAt(pos + 1) == "}"){
1392
// Store current literal text
1393
parts.push(text)
1394
1395
// Search the end of the format string, ie the } closing the
1396
// opening {. Since the string can contain other pairs {} for
1397
// nested formatting, an integer nb is incremented for each { and
1398
// decremented for each } ; the end of the format string is
1399
// reached when nb == 0
1400
var end = pos + 1,
1401
nb = 1
1402
while(end < _len){
1403
if(self.charAt(end) == "{"){nb++; end++}
1404
else if(self.charAt(end) == "}"){
1405
nb--; end++
1406
if(nb == 0){
1411
var fmt_obj = $B.parse_format(fmt_string)
1412
fmt_obj.raw_name = fmt_obj.name
1413
fmt_obj.raw_spec = fmt_obj.spec
1447
}else{
1448
text += car
1449
pos++
1450
}
1451
}
1452
if(text){
1453
parts.push(text)
1459
// Special management of keyword arguments if str.format is called by
1460
// str.format_map(mapping) : the argument "mapping" might not be a
1461
// dictionary
1462
var last_arg = $B.last(arguments)
1463
if(last_arg.$nat == "mapping"){
1464
var mapping = last_arg.mapping,
1465
getitem = $B.$getattr(mapping, "__getitem__")
1466
// Get the rest of the arguments
1467
var args = []
1468
for(var i = 0, len = arguments.length - 1; i < len; i++){
1469
args.push(arguments[i])
1470
}
1471
var $ = $B.args("format", 1, {self: null}, ["self"],
1472
args, {}, "$args", null)
1473
}else{
1474
var $ = $B.args("format", 1, {self: null}, ["self"],
1475
arguments, {}, "$args", "$kw"),
1476
mapping = $.$kw, // dictionary
1477
getitem = function(key){
1478
return _b_.dict.$getitem(mapping, key)
1479
}
1480
}
1496
1497
if(fmt.spec !== undefined){
1498
// "spec" may contain "nested replacement fields"
1499
// In this case, evaluate them using the positional
1500
// or keyword arguments passed to format()
1501
function replace_nested(name, key){
1502
if(/\d+/.exec(key)){
1503
// If key is numeric, search in positional
1504
// arguments
1505
return _b_.tuple.__getitem__($.$args,
1506
parseInt(key))
1507
}else{
1508
// Else try in keyword arguments
1509
return _b_.dict.__getitem__($.$kw, key)
1510
}
1511
}
1512
fmt.spec = fmt.spec.replace(/\{(.*?)\}/g,
1513
replace_nested)
1514
}
1516
// Numerical reference : use positional arguments
1517
var pos = parseInt(fmt.name),
1538
// If the conversion flag is set, first call a function to convert
1539
// the value
1540
if(fmt.conv == "a"){value = _b_.ascii(value)}
1541
else if(fmt.conv == "r"){value = _b_.repr(value)}
1542
else if(fmt.conv == "s"){value = _b_.str.$factory(value)}
1555
str.format_map = function(self, mapping){
1556
var $ = $B.args("format_map", 2, {self: null, mapping: null},
1557
['self', 'mapping'], arguments, {}, null, null)
1558
return str.format(self, {$nat: 'mapping', mapping})
1571
/* Return true if the string is empty or all characters in the string are
1572
ASCII, false otherwise. ASCII characters have code points in the range
1573
U+0000-U+007F. */
1582
str.isalnum = function(self){
1583
/* Return true if all characters in the string are alphanumeric and there
1584
is at least one character, false otherwise. A character c is alphanumeric
1585
if one of the following returns True: c.isalpha(), c.isdecimal(),
1586
c.isdigit(), or c.isnumeric(). */
1587
var $ = $B.args("isalnum", 1, {self: null}, ["self"],
1588
arguments, {}, null, null),
1589
cp
1590
for(var char of to_chars(self)){
1591
cp = _b_.ord(char)
1592
if(unicode_tables.Ll[cp] ||
1593
unicode_tables.Lu[cp] ||
1594
unicode_tables.Lm[cp] ||
1595
unicode_tables.Lt[cp] ||
1596
unicode_tables.Lo[cp] ||
1597
unicode_tables.Nd[cp] ||
1598
unicode_tables.digits[cp] ||
1599
unicode_tables.numeric[cp]){
1600
continue
1601
}
1602
return false
1603
}
1604
return true
1605
}
1606
1607
str.isalpha = function(self){
1608
/* Return true if all characters in the string are alphabetic and there is
1609
at least one character, false otherwise. Alphabetic characters are those
1610
characters defined in the Unicode character database as "Letter", i.e.,
1611
those with general category property being one of "Lm", "Lt", "Lu", "Ll",
1612
or "Lo". */
1613
var $ = $B.args("isalpha", 1, {self: null}, ["self"],
1614
arguments, {}, null, null),
1615
cp
1616
for(var char of to_chars(self)){
1617
cp = _b_.ord(char)
1618
if(unicode_tables.Ll[cp] ||
1619
unicode_tables.Lu[cp] ||
1620
unicode_tables.Lm[cp] ||
1621
unicode_tables.Lt[cp] ||
1622
unicode_tables.Lo[cp]){
1623
continue
1624
}
1625
return false
1626
}
1627
return true
1628
}
1629
1630
str.isdecimal = function(self){
1631
/* Return true if all characters in the string are decimal characters and
1632
there is at least one character, false otherwise. Decimal characters are
1633
those that can be used to form numbers in base 10, e.g. U+0660,
1634
ARABIC-INDIC DIGIT ZERO. Formally a decimal character is a character in
1635
the Unicode General Category "Nd". */
1636
var $ = $B.args("isdecimal", 1, {self: null}, ["self"],
1637
arguments, {}, null, null),
1638
cp
1639
for(var char of to_chars(self)){
1640
cp = _b_.ord(char)
1641
if(! unicode_tables.Nd[cp]){
1642
return false
1643
}
1644
}
1645
return self.length > 0
1646
}
1647
1648
str.isdigit = function(self){
1649
/* Return true if all characters in the string are digits and there is at
1650
least one character, false otherwise. */
1651
var $ = $B.args("isdigit", 1, {self: null}, ["self"],
1652
arguments, {}, null, null),
1653
cp
1654
for(var char of to_chars(self)){
1655
cp = _b_.ord(char)
1656
if(! unicode_tables.digits[cp]){
1657
return false
1658
}
1659
}
1660
return self.length > 0
1661
}
1662
1663
str.isidentifier = function(self){
1664
/* Return true if the string is a valid identifier according to the
1665
language definition. */
1666
var $ = $B.args("isidentifier", 1, {self: null}, ["self"],
1670
}
1671
var chars = to_chars(self)
1672
if(unicode_tables.XID_Start[_b_.ord(chars[0])] === undefined){
1675
for(var char of chars){
1676
var cp = _b_.ord(char)
1677
if(unicode_tables.XID_Continue[cp] === undefined){
1678
return false
1679
}
1680
}
1681
}
1682
return true
1683
}
1684
1685
str.islower = function(self){
1686
/* Return true if all cased characters 4 in the string are lowercase and
1687
there is at least one cased character, false otherwise. */
1688
var $ = $B.args("islower", 1, {self: null}, ["self"],
1689
arguments, {}, null, null),
1690
has_cased = false,
1693
for(var char of to_chars(self)){
1694
cp = _b_.ord(char)
1695
if(unicode_tables.Ll[cp]){
1696
has_cased = true
1697
continue
1698
}else if(unicode_tables.Lu[cp] || unicode_tables.Lt[cp]){
1699
return false
1700
}
1701
}
1702
return has_cased
1703
}
1704
1705
str.isnumeric = function(self){
1706
/* Return true if all characters in the string are numeric characters, and
1707
there is at least one character, false otherwise. Numeric characters
1708
include digit characters, and all characters that have the Unicode numeric
1709
value property, e.g. U+2155, VULGAR FRACTION ONE FIFTH. Formally, numeric
1710
characters are those with the property value Numeric_Type=Digit,
1711
Numeric_Type=Decimal or Numeric_Type=Numeric.*/
1712
var $ = $B.args("isnumeric", 1, {self: null}, ["self"],
1713
arguments, {}, null, null)
1722
var unprintable = {},
1723
unprintable_gc = ['Cc', 'Cf', 'Co', 'Cs','Zl', 'Zp', 'Zs']
1724
1725
str.isprintable = function(self){
1726
/* Return true if all characters in the string are printable or the string
1727
is empty, false otherwise. Nonprintable characters are those characters
1728
defined in the Unicode character database as "Other" or "Separator",
1729
excepting the ASCII space (0x20) which is considered printable. */
1730
1731
// Set unprintable if not set yet
1732
if(Object.keys(unprintable).length == 0){
1733
for(var i = 0; i < unprintable_gc.length; i++){
1734
var table = unicode_tables[unprintable_gc[i]]
1745
return false
1746
}
1747
}
1748
return true
1749
}
1750
1751
str.isspace = function(self){
1752
/* Return true if there are only whitespace characters in the string and
1753
there is at least one character, false otherwise.
1754
1755
A character is whitespace if in the Unicode character database, either its
1756
general category is Zs ("Separator, space"), or its bidirectional class is
1757
one of WS, B, or S.*/
1758
var $ = $B.args("isspace", 1, {self: null}, ["self"],
1759
arguments, {}, null, null),
1760
cp
1761
for(var char of to_chars(self)){
1762
cp = _b_.ord(char)
1763
if(! unicode_tables.Zs[cp] &&
1764
$B.unicode_bidi_whitespace.indexOf(cp) == -1){
1765
return false
1766
}
1767
}
1768
return self.length > 0
1769
}
1770
1771
str.istitle = function(self){
1772
/* Return true if the string is a titlecased string and there is at least
1773
one character, for example uppercase characters may only follow uncased
1774
characters and lowercase characters only cased ones. Return false
1775
otherwise. */
1776
var $ = $B.args("istitle", 1, {self: null}, ["self"],
1777
arguments, {}, null, null)
1778
return self.length > 0 && str.title(self) == self
1779
}
1780
1781
str.isupper = function(self){
1782
/* Return true if all cased characters 4 in the string are lowercase and
1783
there is at least one cased character, false otherwise. */
1784
var $ = $B.args("islower", 1, {self: null}, ["self"],
1785
arguments, {}, null, null),
1789
for(var char of to_chars(self)){
1790
cp = _b_.ord(char)
1791
if(unicode_tables.Lu[cp]){
1792
is_upper = true
1793
continue
1794
}else if(unicode_tables.Ll[cp] || unicode_tables.Lt[cp]){
1813
throw _b_.TypeError.$factory("sequence item " + count +
1814
": expected str instance, " + $B.class_name(obj2) +
1815
" found")
1816
}
1829
var $ = $B.args("ljust", 3, {self: null, width: null, fillchar:null},
1830
["self", "width", "fillchar"],
1834
if($.width <= len){
1835
return self
1836
}
1837
return self + $.fillchar.repeat($.width - len)
1840
str.lower = function(self){
1841
var $ = $B.args("lower", 1, {self: null}, ["self"],
1842
arguments, {}, null, null)
1843
return self.toLowerCase()
1844
}
1845
1848
arguments, {chars:_b_.None}, null, null),
1849
self = $.self,
1850
chars = $.chars
1851
if(chars === _b_.None){
1852
return self.trimStart()
1854
while(self.length > 0){
1855
var flag = false
1856
for(var char of chars){
1857
if(self.startsWith(char)){
1858
self = self.substr(char.length)
1859
flag = true
1860
break
1861
}
1862
}
1863
if(! flag){
1864
return $.self.surrogates ? $B.String(self) : self
1872
var $ = $B.args("maketrans", 3, {x: null, y: null, z: null},
1873
["x", "y", "z"], arguments, {y: null, z: null}, null, null)
1878
// If there is only one argument, it must be a dictionary mapping
1879
// Unicode ordinals (integers) or characters (strings of length 1) to
1880
// Unicode ordinals, strings (of arbitrary lengths) or None. Character
1882
if(! _b_.isinstance($.x, _b_.dict)){
1883
throw _b_.TypeError.$factory(
1884
"maketrans only argument must be a dict")
1887
for(var i = 0, len = items.length; i < len; i++){
1888
var k = items[i][0],
1889
v = items[i][1]
1890
if(! _b_.isinstance(k, _b_.int)){
1891
if(_b_.isinstance(k, _b_.str) && k.length == 1){
1892
k = _b_.ord(k)
1893
}else{throw _b_.TypeError.$factory("dictionary key " + k +
1896
if(v !== _b_.None && ! _b_.isinstance(v, [_b_.int, _b_.str])){
1897
throw _b_.TypeError.$factory("dictionary value " + v +
1905
// and in the resulting dictionary, each character in x will be mapped
1906
// to the character at the same position in y
1909
}else if($.x.length !== $.y.length){
1910
throw _b_.TypeError.$factory(
1911
"maketrans arguments must be strings or same length")
1917
if(! _b_.isinstance($.z, _b_.str)){
1918
throw _b_.TypeError.$factory(
1919
"maketrans third argument must be a string")
1941
var $ = $B.args("partition", 2, {self: null, sep: null}, ["self", "sep"],
1942
arguments, {}, null, null)
1949
if(i == -1){
1950
return _b_.tuple.$factory([$.self, "", ""])
1951
}
1952
return _b_.tuple.$factory([chars.slice(0, i).join(''), $.sep,
1953
chars.slice(i + $.sep.length).join('')])
1956
str.removeprefix = function(){
1957
var $ = $B.args("removeprefix", 2, {self: null, prefix: null},
1958
["self", "prefix"], arguments, {}, null, null)
1959
if(!_b_.isinstance($.prefix, str)){
1960
throw _b_.ValueError.$factory("prefix should be str, not " +
1961
`'${$B.class_name($.prefix)}'`)
1962
}
1963
if(str.startswith($.self, $.prefix)){
1964
return $.self.substr($.prefix.length)
1965
}
1966
return $.self.substr(0)
1967
}
1968
1969
str.removesuffix = function(){
1970
var $ = $B.args("removesuffix", 2, {self: null, prefix: null},
1971
["self", "suffix"], arguments, {}, null, null)
1972
if(!_b_.isinstance($.suffix, str)){
1973
throw _b_.ValueError.$factory("suffix should be str, not " +
1974
`'${$B.class_name($.prefix)}'`)
1975
}
1976
if($.suffix.length > 0 && str.endswith($.self, $.suffix)){
1977
return $.self.substr(0, $.self.length - $.suffix.length)
1978
}
1979
return $.self.substr(0)
1980
}
1981
1982
function $re_escape(str){
1983
var specials = "[.*+?|()$^"
1984
for(var i = 0, len = specials.length; i < len; i++){
1985
var re = new RegExp("\\"+specials.charAt(i), "g")
1986
str = str.replace(re, "\\"+specials.charAt(i))
1987
}
1988
return str
1996
{self: null, old: null, new: null, count: null},
1997
["self", "old", "new", "count"],
1998
arguments, {count: -1}, null, null),
1999
count = $.count,
2000
self = $.self,
2001
old = $.old,
2004
check_str(old, "replace() argument 1 ")
2005
check_str(_new, "replace() argument 2 ")
2013
if(count == 0){
2014
return self
2015
}
2016
if(count.__class__ == $B.long_int){
2017
count = parseInt(count.value)
2018
}
2020
if(_new == ""){
2021
return self
2022
}
2023
if(self == ""){
2024
return _new
2025
}
2026
var elts = self.split("")
2027
if(count > -1 && elts.length >= count){
2028
var rest = elts.slice(count).join("")
2029
return _new + elts.slice(0, count).join(_new) + rest
2055
res = res.substr(0, pos) + _new + res.substr(pos + old.length)
2056
pos = pos + _new.length
2057
count--
2063
// Return the highest index in the string where substring sub is found,
2064
// such that sub is contained within s[start:end]. Optional arguments
2067
{self: null, sub: null, start: null, end: null},
2068
["self", "sub", "start", "end"],
2069
arguments, {start: 0, end: null}, null, null)
2074
var len = str.__len__($.self),
2075
sub_len = str.__len__($.sub)
2076
2077
if(sub_len == 0){
2078
if($.js_start > len){
2085
// Use .indexOf(), not .search(), to avoid conversion to reg exp
2086
var js_start = pypos2jspos($.self, $.start),
2087
js_end = pypos2jspos($.self, $.end),
2088
ix = $.self.substring(js_start, js_end).lastIndexOf($.sub)
2089
if(ix == -1){
2090
return -1
2105
var $ = $B.args("rjust",3,
2106
{self: null, width: null, fillchar: null},
2107
["self", "width", "fillchar"],
2108
arguments, {fillchar: " "}, null, null)
2118
var $ = $B.args("rpartition", 2, {self: null, sep: null}, ["self", "sep"],
2119
arguments, {}, null, null)
2123
var items = str.partition(self, sep).reverse()
2124
for(var i = 0; i < items.length; i++){
2125
items[i] = items[i].split("").reverse().join("")
2131
var $ = $B.args("rsplit", 3, {self: null, sep: null, maxsplit: null},
2132
["self", "sep", "maxsplit"], arguments,
2133
{sep: _b_.None, maxsplit: -1}, null, null),
2134
sep = $.sep
2137
var rev_str = reverse($.self),
2138
rev_sep = sep === _b_.None ? sep : reverse($.sep),
2149
str.rstrip = function(self, x){
2150
var $ = $B.args("rstrip", 2, {self: null, chars: null}, ["self", "chars"],
2151
arguments, {chars: _b_.None}, null, null),
2152
self = $.self,
2153
chars = $.chars
2154
if(chars === _b_.None){
2155
return self.trimEnd()
2157
while(self.length > 0){
2158
var flag = false
2159
for(var char of chars){
2160
if(self.endsWith(char)){
2161
self = self.substr(0, self.length - char.length)
2162
flag = true
2163
break
2164
}
2165
}
2166
if(! flag){
2167
return $.self.surrogates ? $B.String(self) : self
2174
var $ = $B.args("split", 3, {self: null, sep: null, maxsplit: null},
2175
["self", "sep", "maxsplit"], arguments,
2176
{sep: _b_.None, maxsplit: -1}, null, null),
2177
sep = $.sep,
2178
maxsplit = $.maxsplit,
2179
self = $.self,
2180
pos = 0
2181
if(maxsplit.__class__ === $B.long_int){
2182
maxsplit = parseInt(maxsplit.value)
2183
}
2184
if(sep == ""){
2185
throw _b_.ValueError.$factory("empty separator")
2186
}
2190
while(pos < self.length && self.charAt(pos).search(/\s/) > -1){
2191
pos++
2192
}
2193
if(pos === self.length - 1){
2194
return [self]
2195
}
2199
if(name == ""){
2200
name = self.charAt(pos)
2201
}else{
2202
name += self.charAt(pos)
2203
}
2250
str.splitlines = function(self) {
2251
var $ = $B.args('splitlines', 2, {self: null, keepends: null},
2252
['self','keepends'], arguments, {keepends: false},
2253
null, null)
2254
if(!_b_.isinstance($.keepends,[_b_.bool, _b_.int])){
2255
throw _b_.TypeError('integer argument expected, got '+
2258
var keepends = _b_.int.$factory($.keepends),
2259
res = [],
2260
self = $.self,
2261
start = 0,
2262
pos = 0
2263
if(!self.length){
2267
if(self.substr(pos, 2) == '\r\n'){
2268
res.push(self.slice(start, keepends ? pos + 2 : pos))
2269
start = pos = pos+2
2270
}else if(self[pos] == '\r' || self[pos] == '\n'){
2271
res.push(self.slice(start, keepends ? pos+1 : pos))
2272
start = pos = pos+1
2273
}else{
2274
pos++
2275
}
2276
}
2277
if(start < self.length){
2278
res.push(self.slice(start))
2279
}
2284
// Return True if string starts with the prefix, otherwise return False.
2285
// prefix can also be a tuple of prefixes to look for. With optional
2286
// start, test string beginning at that position. With optional end,
2288
var $ = $B.args("startswith", 4,
2289
{self: null, prefix: null, start: null, end: null},
2290
["self", "prefix", "start", "end"],
2291
arguments, {start: 0, end: null}, null, null)
2301
if(! _b_.isinstance(prefix, str)){
2302
throw _b_.TypeError.$factory("endswith first arg must be str " +
2303
"or a tuple of str, not int")
2304
}
2305
if(s.substr(0, prefix.length) == prefix){
2306
return true
2307
}
2313
var $ = $B.args("strip", 2, {self: null, chars: null}, ["self", "chars"],
2314
arguments, {chars: _b_.None}, null, null)
2321
str.swapcase = function(self){
2322
var $ = $B.args("swapcase", 1, {self}, ["self"],
2323
arguments, {}, null, null),
2324
res = "",
2325
cp
2326
2327
for(var char of to_chars(self)){
2328
cp = _b_.ord(char)
2329
if(unicode_tables.Ll[cp]){
2330
res += char.toUpperCase()
2331
}else if(unicode_tables.Lu[cp]){
2332
res += char.toLowerCase()
2335
}
2336
}
2337
return res
2338
}
2339
2340
str.title = function(self){
2341
var $ = $B.args("title", 1, {self}, ["self"],
2342
arguments, {}, null, null),
2343
state,
2346
for(var char of to_chars(self)){
2347
cp = _b_.ord(char)
2348
if(unicode_tables.Ll[cp]){
2355
}else if(unicode_tables.Lu[cp] || unicode_tables.Lt[cp]){
2356
res += state ? char.toLowerCase() : char
2368
getitem = $B.$getattr(table, "__getitem__"),
2369
cp
2370
for(var char of to_chars(self)){
2371
cp = _b_.ord(char)
2375
if(typeof repl == "string"){
2376
res.push(repl)
2377
}else if(typeof repl == "number"){
2378
res.push(String.fromCharCode(repl))
2379
}
2388
str.upper = function(self){
2389
var $ = $B.args("upper", 1, {self: null}, ["self"],
2390
arguments, {}, null, null)
2391
return self.toUpperCase()
2392
}
2393
2396
["self", "width"], arguments, {}, null, null),
2397
len = str.__len__(self)
2398
if($.width <= len){
2399
return self
2400
}
2420
if(encoding !== undefined){
2421
// Arguments may be passed as keywords (cf. issue #1060)
2422
var $ = $B.args("str", 3, {arg: null, encoding: null, errors: null},
2423
["arg", "encoding", "errors"], arguments,
2424
{encoding: "utf-8", errors: "strict"}, null, null),
2425
encoding = $.encoding,
2426
errors = $.errors
2427
}
2428
if(typeof arg == "string" || arg instanceof String ||
2429
typeof arg == "number"){
2430
if(isFinite(arg)){
2431
return arg.toString()
2432
}
2438
// class or its subclasses, but the attribute __str__ of the
2439
// class metaclass (usually "type") or its subclasses (usually
2440
// "object")
2441
// The metaclass is the attribute __class__ of the class dictionary
2446
if(arg.__class__ && arg.__class__ === _b_.bytes &&
2447
encoding !== undefined){
2448
// str(bytes, encoding, errors) is equal to
2449
// bytes.decode(encoding, errors)
2452
// Implicit invocation of __str__ uses method __str__ on the class,
2453
// even if arg has an attribute __str__
2454
var klass = arg.__class__ || $B.get_class(arg)
2460
// if not better than object.__str__, try __repr__
2461
(arg.__class__ && arg.__class__ !== _b_.object &&
2469
if($B.debug > 1){console.log(err)}
2470
console.log("Warning - no method __str__ or __repr__, " +
2471
"default to toString", arg)
2478
if(cls === undefined){
2479
throw _b_.TypeError.$factory("str.__new__(): not enough arguments")
2503
var args = [],
2504
pos = 0
2505
if(arguments.length > 0){
2506
var args = [arguments[0].valueOf()],
2507
pos = 1
2508
for(var i = 1, len = arguments.length; i < len; i++){
2509
args[pos++] = arguments[i]
2526
// Function to parse the 2nd argument of format()
2527
$B.parse_format_spec = function(spec){
2531
var pos = 0,
2532
aligns = "<>=^",
2533
digits = "0123456789",
2534
types = "bcdeEfFgGnosxX%",
2536
if(align_pos != -1){
2537
if(spec.charAt(1) && aligns.indexOf(spec.charAt(1)) != -1){
2538
// If the second char is also an alignment specifier, the
2539
// first char is the fill value
2540
this.fill = spec.charAt(0)
2541
this.align = spec.charAt(1)
2542
pos = 2
2543
}else{
2544
// The first character defines alignment : fill defaults to ' '
2559
if(car == "+" || car == "-" || car == " "){
2560
this.sign = car
2561
pos++
2562
car = spec.charAt(pos)
2577
if(this.width === undefined){
2578
this.width = car
2579
}else{
2580
this.width += car
2581
}
2588
if(this.width === undefined && car == "{"){
2589
// Width is determined by a parameter
2590
var end_param_pos = spec.substr(pos).search("}")
2591
this.width = spec.substring(pos, end_param_pos)
2592
console.log("width", "[" + this.width + "]")
2593
pos += end_param_pos + 1
2594
}
2595
if(car == ","){
2596
this.comma = true
2597
pos++
2598
car = spec.charAt(pos)
2599
}
2600
if(car == "."){
2601
if(digits.indexOf(spec.charAt(pos + 1)) == -1){
2602
throw _b_.ValueError.$factory(
2603
"Missing precision in format spec")
2605
this.precision = spec.charAt(pos + 1)
2606
pos += 2
2607
car = spec.charAt(pos)
2608
while(car && digits.indexOf(car) > -1){
2615
if(car && types.indexOf(car) > -1){
2616
this.type = car
2617
pos++
2618
car = spec.charAt(pos)
2619
}
2620
if(pos !== spec.length){
2626
return (this.fill === undefined ? "" : _b_.str.$factory(this.fill)) +
2627
(this.align || "") +
2628
(this.sign || "") +
2629
(this.alternate ? "#" : "") +
2630
(this.sign_aware ? "0" : "") +
2631
(this.width || "") +
2632
(this.comma ? "," : "") +
2633
(this.precision ? "." + this.precision : "") +
2634
(this.type || "")
2639
if(fmt.width && s.length < fmt.width){
2640
var fill = fmt.fill || " ",
2641
align = fmt.align || "<",
2642
missing = fmt.width - s.length
2644
case "<":
2645
return s + fill.repeat(missing)
2646
case ">":
2647
return fill.repeat(missing) + s
2648
case "=":
2649
if("+-".indexOf(s.charAt(0)) > -1){
2650
return s.charAt(0) + fill.repeat(missing) + s.substr(1)
2654
case "^":
2655
var left = parseInt(missing / 2)
2656
return fill.repeat(left) + s + fill.repeat(missing - left)
2670
function fstring_error(msg, pos){
2671
error = Error(msg)
2672
error.position = pos
2673
throw error
2674
}
2675
2676
$B.parse_fstring = function(string){
2677
// Parse a f-string
2678
var elts = [],
2679
pos = 0,
2744
}else if(ctype == "debug"){
2745
// after the equal sign, whitespace are ignored and the only
2746
// valid characters are } and :
2747
while(string.charAt(i) == " "){i++}
2748
if(string.charAt(i) == "}"){
2749
// end of debug expression
2750
elts.push(current)
2751
ctype = null
2752
current = ""
2753
pos = i + 1
2754
}
2755
}else{
2756
// End of expression is the } matching the opening {
2757
// There may be nested braces
2758
var i = pos,
2759
nb_braces = 1,
2772
if(current.expression == ""){
2773
fstring_error("f-string: empty expression not allowed",
2774
pos)
2775
}
2785
// backslash is not allowed in expressions
2786
throw Error("f-string expression part cannot include a" +
2787
" backslash")
2794
throw Error("f-string: invalid conversion character:" +
2795
" expected 's', 'r', or 'a'")
2796
}else{
2810
if(string.substr(i, 3) == '"""'){
2811
var end = string.indexOf('"""', i + 3)
2812
if(end == -1){
2814
}else{
2815
var trs = string.substring(i, end + 3)
2816
trs = trs.replace("\n", "\\n\\")
2832
var cb = 0,
2833
fmt_complete = false
2834
for(var j = i + 1; j < string.length; j++){
2835
if(string[j] == '{'){
2836
if(string[j + 1] == '{'){
2837
j += 2
2838
}else{
2839
cb++
2840
}
2841
}else if(string[j] == '}'){
2842
if(string[j + 1] == '}'){
2843
j += 2
2844
}else if(cb == 0){
2845
fmt_complete = true
2846
var fmt = string.substring(i + 1, j)
2847
current.format = $B.parse_fstring(fmt)
2848
i = j
2849
break
2850
}else{
2851
cb--
2852
}
2853
}
2854
}
2855
if(! fmt_complete){
2856
fstring_error('invalid format', pos)
2857
}
2860
var ce = current.expression,
2861
last_char = ce.charAt(ce.length - 1),
2862
last_char_re = ('()'.indexOf(last_char) > -1 ? "\\" : "") + last_char
2871
}else{
2872
// add debug string
2873
tail = car
2874
while(string.charAt(i + 1).match(/\s/)){
2875
tail += string.charAt(i + 1)
2876
i++
2877
}
2879
elts.push(current.expression + tail)
2880
// remove trailing whitespace from expression
2881
while(ce.match(/\s$/)){
2882
ce = ce.substr(0, ce.length - 1)
2883
}
2884
current.expression = ce
2885
ctype = "debug"
2886
i++
2887
}
2901
for(var elt of elts){
2902
if(typeof elt == "object"){
2903
if(elt.fmt_pos !== undefined &&
2904
elt.expression.charAt(elt.fmt_pos) != ':'){
2905
console.log('mauvais format', string, elts)
2906
throw Error()
2907
}
2908
}
2909
}
2914
if(i >= 0x10000 && i <= 0x10FFFF){
2915
var code = (i - 0x10000)
2916
return String.fromCodePoint(0xD800 | (code >> 10)) +
2917
String.fromCodePoint(0xDC00 | (code & 0x3FF))
2918
}else{
2919
return String.fromCodePoint(i)
2920
}
2921
}
2924
if(c.length == 1){
2925
return c.charCodeAt(0)
2926
}
2927
var code = 0x10000
2928
code += (c.charCodeAt(0) & 0x03FF) << 10
2929
code += (c.charCodeAt(1) & 0x03FF)
2930
return code
2931
}
2932