Permalink
Jan 14, 2015
Jan 1, 2015
Jan 1, 2015
Sep 18, 2014
Jan 1, 2015
Jan 1, 2015
Jan 1, 2015
Jan 1, 2015
Newer
100644
1612 lines (1405 sloc)
53.8 KB
3
var _b_ = $B.builtins
4
var $s=[]
5
for(var $b in _b_) $s.push('var ' + $b +'=_b_["'+$b+'"]')
6
eval($s.join(';'))
7
8
var $ObjectDict = object.$dict
9
10
var $StringDict = {__class__:$B.$type,
11
__name__:'str',
12
$native:true
13
}
14
15
$StringDict.__add__ = function(self,other){
16
if(!(typeof other==="string")){
17
try{return getattr(other,'__radd__')(self)}
18
catch(err){throw _b_.TypeError(
19
"Can't convert "+$B.get_class(other).__name__+" to str implicitely")}
20
}
21
return self+other
22
}
23
24
$StringDict.__contains__ = function(self,item){
25
if(!(typeof item==="string")){throw _b_.TypeError(
26
"'in <string>' requires string as left operand, not "+item.__class__)}
27
var nbcar = item.length
28
if(nbcar==0) return true // a string contains the empty string
29
if(self.length==0) return nbcar==0
31
if(self.substr(i,nbcar)==item) return true
32
}
33
return false
34
}
35
36
$StringDict.__delitem__ = function(){
37
throw _b_.TypeError("'str' object doesn't support item deletion")
38
}
39
40
$StringDict.__eq__ = function(self,other){
41
if(other===undefined){ // compare object "self" to class "str"
42
return self===str
43
}
44
return other===self.valueOf()
45
}
46
47
$StringDict.__format__ = function(self,arg){
48
var _fs = $FormattableString(self.valueOf())
49
var args=[]
50
// we don't need the first item (ie, self)
51
for (var i = 1, _len_i = arguments.length; i < _len_i; i++) { args.push(arguments[i])}
52
return _fs.strformat(arg)
53
}
54
55
$StringDict.__getitem__ = function(self,arg){
56
if(isinstance(arg,_b_.int)){
57
var pos = arg
58
if(arg<0) pos+=self.length
59
if(pos>=0 && pos<self.length) return self.charAt(pos)
60
throw _b_.IndexError('string index out of range')
61
}
62
if(isinstance(arg,slice)) {
63
var step = arg.step===None ? 1 : arg.step
64
if(step>0){
65
var start = arg.start===None ? 0 : arg.start
66
var stop = arg.stop===None ? getattr(self,'__len__')() : arg.stop
67
}else{
68
var start = arg.start===None ? getattr(self,'__len__')()-1 : arg.start
69
var stop = arg.stop===None ? 0 : arg.stop
70
}
71
if(start<0) start+=self.length
72
if(stop<0) stop+=self.length
73
var res = '',i=null
74
if(step>0){
75
if(stop<=start) return ''
76
for(var i=start;i<stop;i+=step) res += self.charAt(i)
77
} else {
78
if(stop>=start) return ''
79
for(var i=start;i>=stop;i+=step) res += self.charAt(i)
80
}
81
return res
82
}
83
if(isinstance(arg,bool)) return self.__getitem__(_b_.int(arg))
84
}
85
86
// special method to speed up "for" loops
87
$StringDict.__getitems__ = function(self){return self.split('')}
88
89
$StringDict.__hash__ = function(self) {
90
if (self === undefined) {
91
return $StringDict.__hashvalue__ || $B.$py_next_hash-- // for hash of string type (not instance of string)
92
}
93
94
//http://stackoverflow.com/questions/2909106/python-whats-a-correct-and-good-way-to-implement-hash
95
// this implementation for strings maybe good enough for us..
96
97
var hash=1;
99
hash=(101*hash + self.charCodeAt(i)) & 0xFFFFFFFF
100
}
101
102
return hash
103
}
104
105
$StringDict.__init__ = function(self,arg){
106
self.valueOf = function(){return arg}
107
self.toString = function(){return arg}
108
}
109
110
var $str_iterator = $B.$iterator_class('str_iterator')
111
$StringDict.__iter__ = function(self){
112
var items = self.split('') // list of all characters in string
113
return $B.$iterator(items,$str_iterator)
114
}
115
116
$StringDict.__len__ = function(self){return self.length}
117
118
var $legacy_format=$StringDict.__mod__ = function(self,args){
119
// string formatting (old style with %)
120
var ph = [] // placeholders for replacements
121
122
function format(s){
123
if (s === undefined) console.log('format:', s)
124
var conv_flags = '([#\\+\\- 0]*)'
125
//var conv_types = '[diouxXeEfFgGcrsa%]'
126
//var re = new RegExp('\\%(\\(.+?\\))*'+conv_flags+'(\\*|\\d*)(\\.\\*|\\.\\d*)*(h|l|L)*('+conv_types+'){1}')
127
var re = new RegExp('\\%(\\(.+?\\))*'+conv_flags+'(\\*|\\d*)(\\.\\*|\\.\\d*)*(h|l|L)*(.){1}')
128
var res = re.exec(s)
129
this.is_format = true
130
if(!res){this.is_format = false;return}
131
this.src = res[0]
132
if(res[1]){this.mapping_key=str(res[1].substr(1,res[1].length-2))}
133
else{this.mapping_key=null}
134
this.flag = res[2]
135
this.min_width = res[3]
136
this.precision = res[4]
137
this.length_modifier = res[5]
138
this.type = res[6]
139
140
this._number_check=function(s) {
141
if(!isinstance(s,[_b_.int,_b_.float])){
142
if (s.__class__ !== undefined) {
143
throw _b_.TypeError("%"+this.type+" format: a number is required, not " + str(s.__class__))
144
} else if (typeof(s) === 'string') {
145
throw _b_.TypeError("%"+this.type+" format: a number is required, not str")
146
} else {
147
throw _b_.TypeError("%"+this.type+" format: a number is required, not 'unknown type'")
148
}
149
}
150
}
151
152
this.toString = function(){
153
var res = 'type '+this.type+' key '+this.mapping_key+' min width '+this.min_width
154
return res + ' precision '+this.precision
155
}
156
this.format = function(src){
157
if(this.mapping_key!==null){
158
if(!isinstance(src,_b_.dict)){throw _b_.TypeError("format requires a mapping")}
159
src=getattr(src,'__getitem__')(this.mapping_key)
160
}
161
162
if(this.flag.indexOf("#") > -1){var flag_hash = true}
163
if(this.flag.indexOf("+") > -1){var flag_plus = true}
164
if(this.flag.indexOf("-") > -1){var flag_minus = true}
165
if(this.flag.indexOf("0") > -1){var flag_zero = true}
166
if(this.flag.indexOf(" ") > -1){var flag_space = true}
167
168
switch(this.type) {
169
case 's':
170
//if(this.type=="s"){
171
var res = str(src)
172
if(this.precision){return res.substr(0,parseInt(this.precision.substr(1)))}
173
return res
174
case 'r':
175
//}else if(this.type=="r"){
176
var res = repr(src)
177
if(this.precision){return res.substr(0,parseInt(this.precision.substr(1)))}
178
return res
179
case 'a':
180
//}else if(this.type=="a"){
181
var res = ascii(src)
182
if(this.precision){return res.substr(0,parseInt(this.precision.substr(1)))}
183
return res
184
case 'n': //fix me n is like g but uses current locale for separators
185
case 'g':
186
case 'G':
187
//}else if(this.type=="g" || this.type=="G"){
188
if(!isinstance(src,[_b_.int,_b_.float])){
189
throw _b_.TypeError("a float is required")}
190
var prec = -4
191
if(this.precision){prec=parseInt(this.precision.substr(1))}
192
var res = parseFloat(src)
193
194
switch(res) {
195
case Infinity:
196
if (this.flag==='+' || this.flag === '+#') return '+inf'
197
if (this.flag===' ' || this.flag === ' #') return ' inf'
198
return 'inf'
199
case -Infinity:
200
return '-inf'
201
}
202
204
if (this.flag === '+' || this.flag === '+#') return '+nan'
205
if (this.flag === ' ' || this.flag === ' #') return ' nan'
206
return 'nan'
207
}
208
209
res=res.toExponential()
210
var elts = res.split('e')
211
if((this.precision && eval(elts[1])>prec) ||
212
(!this.precision && eval(elts[1])<-4)){
213
this.type === 'g' ? this.type='e' : this.type='E'
214
// The precision determines the number of significant digits
215
// before and after the decimal point and defaults to 6
216
var prec = 6
217
if(this.precision){prec=parseInt(this.precision.substr(1))-1}
218
var res = parseFloat(src).toExponential(prec)
219
var elts = res.split('e')
220
var res = elts[0]+this.type+elts[1].charAt(0)
221
if(elts[1].length===2){res += '0'}
222
return res+elts[1].substr(1)
223
}else{
224
var prec = 2
225
if(this.flag=='#'){
226
if (this.precision === undefined) {
227
this.precision='.5' // use a default of 6
228
} else {
229
prec=parseInt(this.precision.substr(1))-1
230
var elts = str(src).split('.')
231
this.precision = '.'+(prec-elts[0].length)
232
}
233
} else {
234
//this.precision = this.precision || 0
235
}
236
237
this.type="f"
238
var _v=this.format(src)
239
//removing ending zeros
240
241
if (this.flag === '#') return _v
242
return _v.replace(new RegExp("[\.0]+$"), "");
243
}
244
case 'e':
245
case 'E':
246
//}else if(this.type=="e" || this.type=="E"){
247
this._number_check(src)
248
var prec = 6
249
if(this.precision){prec=parseInt(this.precision.substr(1))}
250
var res = parseFloat(src)
251
252
switch(res) {
253
case Infinity:
254
switch(this.flag) {
255
case ' ':
256
case ' #':
257
return ' inf'
258
case '+':
259
case '+#':
260
return '+inf'
261
default:
262
return 'inf'
263
}
264
case -Infinity:
265
return '-inf'
266
}
267
269
switch(this.flag) {
270
case ' ':
271
case ' #':
272
return ' nan'
273
case '+':
274
case '+#':
275
return '+nan'
276
default:
277
return 'nan'
278
}
279
}
280
281
res=res.toExponential(prec)
282
var elts = res.split('e')
283
var res = elts[0]+this.type+elts[1].charAt(0)
284
if(elts[1].length===2){res += '0'}
285
return res+elts[1].substr(1)
286
case 'x':
287
case 'X':
288
//}else if(this.type=="x" || this.type=="X"){ // hex
289
this._number_check(src)
290
var num = src
291
res = src.toString(16)
292
293
var pad=' '
294
if(this.flag===' '){res = ' '+res}
295
else if(this.flag==='+' && num>=0){pad='+';res = '+'+res}
296
297
if(this.precision){
298
var width=this.precision.substr(1)
299
if(this.flag==='#'){pad="0"}
300
while(res.length<width){res=pad+res}
301
}
302
303
if(this.flag ==='#'){
304
if(this.type==='x'){res = '0x'+res}
305
else{res = '0X'+res}
306
}
307
return res
308
case 'i':
318
var prec = parseInt(this.precision.substr(1))
319
}else{
320
var prec = 0
321
}
322
if(this.min_width){
323
var min_width = parseInt(this.min_width)
324
}else{
325
var min_width = 0
326
}
327
var width = Math.max(len_num, prec, min_width)
328
var pad = ' '
329
if (len_num === width){
330
if(flag_plus && num>=0){res = '+'+res}
331
}else{
332
if(flag_minus){
333
if(!flag_plus && !flag_space){
334
res=res+pad.repeat(width-len_num)
335
}
336
if(flag_plus){
337
res='+'+res+pad.repeat(width-len_num-1)
338
}
339
if(!flag_plus && flag_space){
340
res=pad+res+pad.repeat(width-len_num-1)
341
}
342
}else if(flag_plus && !flag_zero){
343
res=pad.repeat(width-len_num-1)+'+'+res
344
}else if(flag_plus && flag_zero){
345
if(num.substr(0,1) === '-'){
346
res='-'+'0'.repeat(width-len_num)+res.substr(1)
347
}else{
348
res='+'+'0'.repeat(width-len_num-1)+res
349
}
350
}else if(!flag_plus && !flag_space && flag_zero){
351
res='0'.repeat(width-len_num)+res
352
}else if(!flag_plus && !flag_zero && !flag_space && !flag_minus){
353
if(prec>0 && prec > len_num){
354
res=pad.repeat(width-(prec-len_num)-1)+'0'.repeat(prec-len_num)+res
355
}else{
356
res=pad.repeat(width-len_num)+res
357
}
358
}else if(flag_space && flag_zero){
359
res=pad+'0'.repeat(width-len_num-1)+res
360
}
361
}
362
return res
363
case 'f':
364
case 'F':
365
//}else if(this.type=="f" || this.type=="F"){
366
this._number_check(src)
367
var num = parseFloat(src)
368
if (num == Infinity){res='inf'}
369
else if (num == -Infinity){res='-inf'}
371
else {res=num}
372
373
// set default precision of 6 if precision is not specified
374
if(this.precision === undefined) this.precision=".6"
375
376
if(this.precision && typeof res === 'number'){
377
res = res.toFixed(parseInt(this.precision.substr(1)))
378
}
379
380
//res = num+''
381
switch(this.flag) {
382
case ' ':
383
case ' #':
384
//if(this.flag===' ' &&
385
if (num>=0 || res=='nan' || res == 'inf') res = ' '+res
386
break
387
//else if(this.flag===' #' &&
388
//if (num>=0 || res=='nan' || res=='inf') res = ' '+res
389
case '+':
390
case '+#':
391
//else if(this.flag==='+' && (num>=0 || res=='nan' || res=='inf')){res = '+'+res}
392
//else if(this.flag==='+#' &&
393
if (num>=0 || res=='nan' || res=='inf') res = '+'+res
394
break
395
}
396
if(this.min_width){
397
var pad = ' '
398
if(this.flag==='0'){pad="0"}
399
while(res.length<parseInt(this.min_width)){res=pad+res}
400
}
401
return res
402
case 'c':
403
//}else if(this.type=='c'){
404
if(isinstance(src,str) && str.length==1) return src
405
if(isinstance(src,_b_.int) && src>0 && src<256) return String.fromCharCode(src)
406
_b_.TypeError('%c requires _b_.int or char')
407
case 'o':
408
//}else if(this.type=='o'){
409
var res = src.toString(8)
410
if(this.flag==='#') return '0o' + res
411
return res
412
case 'b':
413
//}else if (this.type=='b') {
414
var res = src.toString(2)
415
if(this.flag==='#') return '0b' + res
416
return res
417
default:
418
//}else {
419
//if (hasattr(src, '__format__')) {
420
// console.log(this.type)
421
// //console.log(getattr(src, '__format__')(this.type))
422
// return getattr(src, '__format__')(this.type)
423
//}
424
// consider this 'type' invalid
425
var _msg="unsupported format character '" + this.type
426
_msg+= "' (0x" + this.type.charCodeAt(0).toString(16) + ") at index "
427
_msg+= (self.valueOf().indexOf('%' + this.type)+1)
428
console.log(_msg)
429
throw _b_.ValueError(_msg)
430
}//switch
431
}
432
} // end format
433
434
435
// elts is an Array ; items of odd rank are string format objects
436
var elts = []
437
var pos = 0, start = 0, nb_repl = 0, is_mapping = null
438
var val = self.valueOf()
439
while(pos<val.length){
440
if (val === undefined) console.log(val)
441
if(val.charAt(pos)=='%'){
442
var f = new format(val.substr(pos))
443
if(f.is_format){
444
if(f.type!=="%"){
445
elts.push(val.substring(start,pos))
446
elts.push(f)
447
start = pos+f.src.length
448
pos = start
449
nb_repl++
450
if(is_mapping===null){is_mapping=f.mapping_key!==null}
451
else if(is_mapping!==(f.mapping_key!==null)){
452
// can't mix mapping keys with non-mapping
453
console.log(f+' not mapping')
454
throw _b_.TypeError('format required a mapping')
455
}
456
}else{ // form %%
457
pos++;pos++
458
}
459
}else{pos++}
460
}else{pos++}
461
}
462
// check for invalid format string "no format"
463
if(elts.length == 0) {
464
throw _b_.TypeError('not all arguments converted during string formatting')
465
}
466
elts.push(val.substr(start))
467
if(!isinstance(args,_b_.tuple)){
468
if(args.__class__==_b_.dict.$dict && is_mapping){
469
// convert all formats with the dictionary
471
elts[i]=elts[i].format(args)
472
}
473
}
474
else if(nb_repl>1){throw _b_.TypeError('not enough arguments for format string')}
475
else{elts[1]=elts[1].format(args)}
476
}else{
477
if(nb_repl==args.length){
479
var fmt = elts[1+2*i]
480
elts[1+2*i]=fmt.format(args[i])
481
}
482
}else if(nb_repl<args.length){throw _b_.TypeError(
483
"not all arguments converted during string formatting")
484
}else{throw _b_.TypeError('not enough arguments for format string')}
485
}
486
var res = ''
488
// finally, replace %% by %
489
return res.replace(/%%/g,'%')
490
}// $end $legacy_format
491
492
//_b_.$legacy_format=$legacy_format
493
494
$StringDict.__mro__ = [$StringDict,$ObjectDict]
495
496
$StringDict.__mul__ = function(self,other){
497
if(!isinstance(other,_b_.int)){throw _b_.TypeError(
498
"Can't multiply sequence by non-int of type '"+
499
$B.get_class(other).__name__+"'")}
500
$res = ''
501
for(var i=0;i<other;i++){$res+=self.valueOf()}
502
return $res
503
}
504
505
$StringDict.__ne__ = function(self,other){return other!==self.valueOf()}
506
507
$StringDict.__repr__ = function(self){
508
if(self===undefined){return "<class 'str'>"}
509
var qesc = new RegExp("'","g") // to escape single quote
510
var res = self.replace(/\n/g,'\\\\n')
511
res = "'"+res.replace(qesc,"\\'")+"'"
512
//console.log(res)
513
return res
514
}
515
516
$StringDict.__setattr__ = function(self,attr,value){setattr(self,attr,value)}
517
518
$StringDict.__setitem__ = function(self,attr,value){
519
throw _b_.TypeError("'str' object does not support item assignment")
520
}
521
$StringDict.__str__ = function(self){
522
if(self===undefined) return "<class 'str'>"
523
return self.toString()
524
}
525
$StringDict.toString = function(){return 'string!'}
526
527
// generate comparison methods
528
var $comp_func = function(self,other){
529
if(typeof other !=="string"){throw _b_.TypeError(
530
"unorderable types: 'str' > "+$B.get_class(other).__name__+"()")}
531
return self > other
532
}
533
$comp_func += '' // source code
534
var $comps = {'>':'gt','>=':'ge','<':'lt','<=':'le'}
535
for(var $op in $comps){
536
eval("$StringDict.__"+$comps[$op]+'__ = '+$comp_func.replace(/>/gm,$op))
537
}
538
539
// add "reflected" methods
540
$B.make_rmethods($StringDict)
541
542
// unsupported operations
543
var $notimplemented = function(self,other){
544
throw NotImplementedError("OPERATOR not implemented for class str")
545
}
547
$notimplemented += '' // coerce to string
548
for(var $op in $B.$operators){
549
var $opfunc = '__'+$B.$operators[$op]+'__'
550
if(!($opfunc in str)){
551
//eval('$StringDict.'+$opfunc+"="+$notimplemented.replace(/OPERATOR/gm,$op))
552
}
553
}
555
556
$StringDict.capitalize = function(self){
557
if(self.length==0) return ''
558
return self.charAt(0).toUpperCase()+self.substr(1).toLowerCase()
559
}
560
561
$StringDict.casefold = function(self) {
562
throw _b_.NotImplementedError("function casefold not implemented yet");
563
}
564
565
$StringDict.center = function(self,width,fillchar){
566
if(fillchar===undefined){fillchar=' '}else{fillchar=fillchar}
567
if(width<=self.length) return self
568
569
var pad = parseInt((width-self.length)/2)
570
var res = Array(pad+1).join(fillchar) // is this statement faster than the for loop below?
571
res += self + res
572
if(res.length<width){res += fillchar}
573
return res
574
}
575
576
$StringDict.count = function(self,elt){
577
if(!(typeof elt==="string")){throw _b_.TypeError(
578
"Can't convert '"+elt.__class__.__name__+"' object to str implicitly")}
579
//needs to be non overlapping occurrences of substring in string.
580
var n=0, pos=0
581
while(1){
582
pos=self.indexOf(elt,pos)
583
if(pos>=0){ n++; pos+=elt.length} else break;
584
}
585
return n
586
}
587
588
$StringDict.encode = function(self, encoding) {
589
if (encoding === undefined) encoding='utf-8'
590
return bytes(self, encoding)
591
}
592
593
$StringDict.endswith = function(self){
594
// Return True if the string ends with the specified suffix, otherwise
595
// return False. suffix can also be a tuple of suffixes to look for.
596
// With optional start, test beginning at that position. With optional
597
// end, stop comparing at that position.
598
var args = []
600
var start=null,end=null
601
var $ns=$B.$MakeArgs("$StringDict.endswith",args,['suffix'],
602
['start','end'],null,null)
603
var suffixes = $ns['suffix']
604
if(!isinstance(suffixes,_b_.tuple)){suffixes=[suffixes]}
605
start = $ns['start'] || start
606
end = $ns['end'] || self.length-1
607
var s = self.substr(start,end+1)
609
suffix = suffixes[i]
610
if(suffix.length<=s.length &&
611
s.substr(s.length-suffix.length)==suffix) return true
612
}
613
return false
614
}
615
616
$StringDict.expandtabs = function(self, tabsize) {
617
tabsize=tabsize || 8
618
var _str=''
619
for (var i=0; i < tabsize; i++) _str+=' '
620
return self.valueOf().replace(/\t/g, _str)
621
}
622
623
$StringDict.find = function(self){
624
// Return the lowest index in the string where substring sub is found,
625
// such that sub is contained in the slice s[start:end]. Optional
626
// arguments start and end are interpreted as in slice notation.
627
// Return -1 if sub is not found.
628
var start=0,end=self.length
629
var $ns=$B.$MakeArgs("$StringDict.find",arguments,['self','sub'],
630
['start','end'],null,null)
631
for(var attr in $ns){eval('var '+attr+'=$ns[attr]')}
632
if(!isinstance(sub,str)){throw _b_.TypeError(
633
"Can't convert '"+sub.__class__.__name__+"' object to str implicitly")}
634
if(!isinstance(start,_b_.int)||!isinstance(end,_b_.int)){
635
throw _b_.TypeError(
636
"slice indices must be integers or None or have an __index__ method")}
637
var s = self.substring(start,end)
638
//var escaped = ['[','.','*','+','?','|','(',')','$','^']
639
var esc_sub = ''
641
switch(sub.charAt(i)) {
642
case '[':
643
case '.':
644
case '*':
645
case '+':
646
case '?':
647
case '|':
648
case '(':
649
case ')':
650
case '$':
651
case '^':
652
//if(escaped.indexOf(sub.charAt(i))>-1){
653
esc_sub += '\\'
654
}
655
esc_sub += sub.charAt(i)
656
}
657
var res = s.search(esc_sub)
658
if(res==-1) return -1
659
return start+res
660
}
661
662
var $FormattableString=function(format_string) {
663
// inspired from
664
// https://raw.github.com/florentx/stringformat/master/stringformat.py
665
this.format_string=format_string
666
667
this._prepare = function() {
668
//console.log('prepare')
669
var match = arguments[0]
670
//console.log('match1', match)
671
672
var p1 = '' + arguments[2]
673
674
if (match == '%') return '%%'
675
if (match.substring(0,1) == match.substring(match.length-1)) {
676
// '{{' or '}}'
677
return match.substring(0, Math.floor(match.length/2))
678
}
679
680
if (p1.charAt(0) == '{' && p1.charAt(match.length-1) == '}') {
681
p1=match.substring(1, p1.length-1)
682
}
683
684
var _repl
685
if (match.length >= 2) {
686
_repl=''
687
} else {
688
_repl = match.substring(1)
689
}
690
691
var _i = p1.indexOf(':')
692
var _out
693
if (_i > -1) {
694
_out = [p1.slice(0,_i), p1.slice(_i+1)]
695
//var _out = p1.split(':') // only want to split on first ':'
696
} else { _out=[p1]}
697
698
var _field=_out[0] || ''
699
var _format_spec=_out[1] || ''
700
701
_out= _field.split('!')
702
var _literal=_out[0] || ''
703
var _sep=_field.indexOf('!') > -1?'!': undefined // _out[1]
704
var _conv=_out[1] //conversion
705
706
if (_sep && _conv === undefined) {
707
throw _b_.ValueError("end of format while looking for conversion specifier")
708
}
709
710
if (_conv !== undefined && _conv.length > 1) {
711
throw _b_.ValueError("expected ':' after format specifier")
712
}
713
714
if (_conv !== undefined && 'rsa'.indexOf(_conv) == -1) {
715
throw _b_.ValueError("Unknown conversion specifier " + _conv)
716
}
717
718
_name_parts=this.field_part.apply(null, [_literal])
719
720
var _start=_literal.charAt(0)
721
var _name=''
722
if (_start=='' || _start=='.' || _start == '[') {
723
// auto-numbering
724
if (this._index === undefined) {
725
throw _b_.ValueError("cannot switch from manual field specification to automatic field numbering")
726
}
727
728
_name = self._index.toString()
729
this._index+=1
730
731
if (! _literal ) {
732
_name_parts.shift()
733
}
734
} else {
735
_name = _name_parts.shift()[1]
737
// manual specification
738
if (this._index) {
739
throw _b_.ValueError("cannot switch from automatic field " +
740
"numbering to manual field specification")
741
this._index=undefined
742
}
743
}
744
}
745
746
var _empty_attribute=false
747
748
//console.log('name', _name)
749
var _k
751
_k = _name_parts[i][0]
752
var _v = _name_parts[i][1]
753
var _tail = _name_parts[i][2]
754
//console.log('_v', _v)
755
if (_v === '') {_empty_attribute = true}
756
//console.log(_tail)
757
if (_tail !== '') {
758
throw _b_.ValueError("Only '.' or '[' may follow ']' " +
759
"in format field specifier")
760
}
761
}
762
763
if (_name_parts && _k == '[' && !
764
_literal.charAt(_literal.length) == ']') {
765
throw _b_.ValueError("Missing ']' in format string")
766
}
767
768
if (_empty_attribute) {
769
throw _b_.ValueError("Empty attribute in format string")
770
}
771
772
var _rv=''
773
if (_format_spec.indexOf('{') != -1) {
774
_format_spec = _format_spec.replace(this.format_sub_re, this._prepare)
775
_rv = [_name_parts, _conv, _format_spec]
776
if (this._nested[_name] === undefined) {
777
this._nested[_name]=[]
778
this._nested_array.push(_name)
779
}
780
this._nested[_name].push(_rv)
781
} else {
782
_rv = [_name_parts, _conv, _format_spec]
783
if (this._kwords[_name] === undefined) {
784
this._kwords[_name]=[]
785
this._kwords_array.push(_name)
786
}
787
this._kwords[_name].push(_rv)
788
}
789
790
//console.log('_rv', _rv)
791
return '%(' + id(_rv) + ')s'
792
} // this._prepare
793
794
this.format=function() {
795
//console.log('format')
796
// same as str.format() and unicode.format in Python 2.6+
797
798
var $ns=$B.$MakeArgs('format',arguments,[],[],'args','kwargs')
799
var args=$ns['args']
800
var kwargs=$ns['kwargs']
801
802
if (args.length>0) {
804
//kwargs[str(i)]=args.$dict[i]
805
getattr(kwargs, '__setitem__')(str(i), args[i])
806
}
807
}
808
809
//encode arguments to ASCII, if format string is bytes
810
var _want_bytes = isinstance(this._string, str)
811
var _params=_b_.dict()
812
814
var _name = this._kwords_array[i]
815
var _items = this._kwords[_name]
816
var _var = getattr(kwargs, '__getitem__')(_name)
817
var _value;
818
if (hasattr(_var, 'value')) {
819
//_value = getattr(getattr(kwargs, '__getitem__')(_name), 'value')
820
_value = getattr(_var, 'value')
821
} else {
822
_value=_var
823
}
824
826
var _parts = _items[j][0]
827
var _conv = _items[j][1]
828
var _spec = _items[j][2]
829
830
//console.log('legacy_format:', _spec, _params)
831
//_spec=$legacy_format(_spec, _params)
832
833
var _f=this.format_field.apply(null, [_value, _parts,_conv,_spec,_want_bytes])
834
getattr(_params,'__setitem__')(id(_items[j]).toString(), _f)
835
}
836
}
837
839
var _name = this._nested_array[i]
840
var _items = this._nested[i]
841
842
var _var = getattr(kwargs, '__getitem__')(_name)
843
var _value;
844
if (hasattr(_var, 'value')) {
845
_value = getattr(getattr(kwargs, '__getitem__')(_name), 'value')
846
} else {
847
_value=_var
848
}
849
851
var _parts = _items[j][0]
852
var _conv = _items[j][1]
853
var _spec = _items[j][2]
854
855
//console.log('legacy_format:', _spec, _params)
856
_spec=$legacy_format(_spec, _params)
857
858
var _f=this.format_field.apply(null, [_value, _parts,_conv,_spec,_want_bytes])
859
getattr(_params,'__setitem__')(id(_items[j]).toString(), _f)
860
}
861
}
862
//console.log('legacy_format:', this._string, _params)
863
return $legacy_format(this._string, _params)
864
} // this.format
865
866
this.format_field=function(value,parts,conv,spec,want_bytes) {
867
//console.log('format_field')
868
869
if (want_bytes === undefined) want_bytes = false
870
872
var _k = parts[i][0]
873
var _part = parts[i][1]
874
875
if (_k) {
876
if (!isNaN(_part)) {
877
value = value[parseInt(_part)]
878
} else {
879
value = getattr(value, _part)
880
}
881
} else {
882
value = value[_part]
883
}
884
}
885
886
if (conv) {
887
// fix me
888
//console.log('legacy_format:', conv, value)
889
value = $legacy_format((conv == 'r') && '%r' || '%s', value)
890
}
891
892
value = this.strformat(value, spec)
893
//value=this.strformat.apply(null, [value, spec])
894
895
if (want_bytes) { // && isinstance(value, unicode)) {
896
return value.toString()
897
}
898
899
return value
900
}
901
902
this.strformat=function(value, format_spec) {
903
//console.log('strformat')
904
if (format_spec === undefined) format_spec = ''
905
//console.log(value)
906
//console.log(format_spec)
907
if (!isinstance(value,[str,_b_.int]) && hasattr(value, '__format__')) {
908
return getattr(value, '__format__')(format_spec)
909
}
910
var _m = this.format_spec_re.test(format_spec)
911
912
if (!_m) throw _b_.ValueError('Invalid conversion specification')
913
914
var _match=this.format_spec_re.exec(format_spec)
915
var _align=_match[1]
916
var _sign=_match[2]
917
var _prefix=_match[3]
918
var _width=_match[4]
919
var _comma=_match[5]
920
var _precision=_match[6]
921
var _conversion=_match[7]
922
926
927
//console.log('match', _match)
928
929
if (_prefix != '' && ! _is_numeric) {
930
if (_is_numeric) {
931
throw _b_.ValueError('Alternate form (#) not allowed in float format specifier')
932
} else {
933
throw _b_.ValueError('Alternate form (#) not allowed in string format specification')
934
}
935
}
936
937
if (_is_numeric && _conversion == 'n') {
938
_conversion = _is_integer && 'd' || 'g'
939
} else {
940
if (_sign) {
941
if (! _is_numeric) {
942
throw _b_.ValueError('Sign not allowed in string format specification');
943
}
944
if (_conversion == 'c') {
945
throw("Sign not allowed with integer format specifier 'c'")
946
}
947
}
948
}
949
950
if (_comma !== '') {
951
value += ''
952
var x = value.split('.')
953
var x1 = x[0];
954
var x2 = x.length > 1 ? '.' + x[1] : '';
955
var rgx = /(\d+)(\d{3})/;
956
957
while (rgx.test(x1)) {
958
x1 = x1.replace(rgx, '$1' + ',' + '$2');
959
}
960
value=x1+x2
961
}
962
963
var _rv
964
if (_conversion != '' && ((_is_numeric && _conversion == 's') ||
965
(! _is_integer && 'coxX'.indexOf(_conversion) != -1))) {
966
console.log(_conversion)
967
throw _b_.ValueError('Fix me')
968
}
969
970
if (_conversion == 'c') _conversion = 's'
971
972
// fix me
973
_rv='%' + _prefix + _precision + (_conversion || 's')
974
975
//console.log('legacy_format', _rv, value)
976
_rv = $legacy_format(_rv, value)
977
978
if (_sign != '-' && value >= 0) _rv = _sign + _rv
979
980
var _zero = false
981
if (_width) {
982
//_zero = _width.substring(0,1) == '0'
983
_zero = _width.charAt(0) == '0'
984
_width = parseInt(_width)
985
} else {
986
_width = 0
987
}
988
989
// Fastpath when alignment is not required
990
991
if (_width <= _rv.length) {
993
throw _b_.ValueError("'=' alignment not allowed in string format specifier")
994
}
995
return _rv
996
}
997
998
_fill = _align.substr(0,_align.length-1)
999
_align= _align.substr(_align.length-1)
1000
1001
if (! _fill) {_fill = _zero && '0' || ' '}
1002
1003
if (_align == '^') {
1004
_rv = getattr(_rv, 'center')(_width, _fill)
1005
} else if (_align == '=' || (_zero && ! _align)) {
1006
if (! _is_numeric) {
1007
throw _b_.ValueError("'=' alignment not allowed in string format specifier")
1008
}
1009
if (_value < 0 || _sign != '-') {
1010
_rv = _rv.substring(0,1) + getattr(_rv.substring(1),'rjust')(_width - 1, _fill)
1011
} else {
1012
_rv = getattr(_rv, 'rjust')(_width, _fill)
1013
}
1014
} else if ((_align == '>' || _align == '=') || (_is_numeric && ! _aligned)) {
1015
_rv = getattr(_rv, 'rjust')(_width, _fill)
1016
} else if (_align == '<') {
1017
_rv = getattr(_rv, 'ljust')(_width, _fill)
1018
} else {
1019
throw _b_.ValueError("'" + _align + "' alignment not valid")
1020
}
1021
1022
return _rv
1023
}
1024
1025
this.field_part=function(literal) {
1026
//console.log('field_part')
1027
if (literal.length == 0) return [['','','']]
1028
1029
var _matches=[]
1030
var _pos=0
1031
1032
var _start='', _middle='', _end=''
1033
var arg_name=''
1034
1035
// arg_name
1036
if (literal === undefined) console.log(literal)
1037
var _lit=literal.charAt(_pos)
1038
while (_pos < literal.length &&
1039
_lit !== '[' && _lit !== '.') {
1040
//console.log(literal.charAt(_pos))
1041
arg_name += _lit
1042
_pos++
1043
_lit=literal.charAt(_pos)
1044
}
1045
1046
// todo.. need to work on code below, but this takes cares of most
1047
// common cases.
1048
if (arg_name != '') _matches.push(['', arg_name, ''])
1049
1050
//return _matches
1051
1052
var attribute_name=''
1053
var element_index=''
1054
1055
//look for attribute_name and element_index
1056
while (_pos < literal.length) {
1057
var car = literal.charAt(_pos)
1058
//console.log(_pos, car)
1059
1060
if (car == '[') { // element_index
1061
_start=_middle=_end=''
1062
_pos++
1063
1064
car = literal.charAt(_pos)
1065
while (_pos < literal.length && car !== ']') {
1066
_middle += car
1067
_pos++
1068
car = literal.charAt(_pos)
1069
//console.log(car)
1070
}
1071
1072
_pos++
1073
if (car == ']') {
1074
while (_pos < literal.length) {
1075
_end+=literal.charAt(_pos)
1076
_pos++
1077
}
1078
}
1079
1080
_matches.push([_start, _middle, _end])
1081
1082
} else if (car == '.') { // attribute_name
1083
_middle=''
1084
_pos++
1085
car = literal.charAt(_pos)
1086
while (_pos < literal.length &&
1087
car !== '[' &&
1088
car !== '.') {
1089
//console.log(car)
1090
_middle += car
1091
_pos++
1092
car = literal.charAt(_pos)
1093
}
1094
1095
_matches.push(['.', _middle, ''])
1096
}
1097
}
1098
//console.log(_matches)
1099
return _matches
1100
}
1101
1102
this.format_str_re = new RegExp(
1103
'(%)' +
1104
'|((?!{)(?:{{)+' +
1105
'|(?:}})+(?!})' +
1107
)
1108
1109
this.format_sub_re = new RegExp('({[^{}]*})') // nested replacement field
1110
1111
this.format_spec_re = new RegExp(
1112
'((?:[^{}]?[<>=^])?)' + // alignment
1113
'([\\-\\+ ]?)' + // sign
1114
'(#?)' + '(\\d*)' + '(,?)' + // base prefix, minimal width, thousands sep
1115
'((?:\.\\d+)?)' + // precision
1116
'(.?)$' // type
1117
)
1118
1119
this._index = 0
1120
this._kwords = {}
1121
this._kwords_array=[]
1122
this._nested = {}
1123
this._nested_array=[]
1124
1125
this._string=format_string.replace(this.format_str_re, this._prepare)
1126
1127
return this
1128
}
1129
1130
1131
$StringDict.format = function(self) {
1132
1133
var _fs = $FormattableString(self.valueOf())
1134
var args=[]
1135
// we don't need the first item (ie, self)
1136
for (var i = 1, _len_i = arguments.length; i < _len_i; i++) { args.push(arguments[i])}
1137
return _fs.format.apply(null, args)
1138
}
1139
1140
$StringDict.format_map = function(self) {
1141
throw NotImplementedError("function format_map not implemented yet");
1142
}
1143
1144
$StringDict.index = function(self){
1145
// Like find(), but raise ValueError when the substring is not found.
1146
var res = $StringDict.find.apply(self,arguments)
1147
if(res===-1) throw _b_.ValueError("substring not found")
1148
return res
1149
}
1150
1151
$StringDict.isalnum = function(self) {return /^[a-z0-9]+$/i.test(self)}
1152
1153
$StringDict.isalpha = function(self) {return /^[a-z]+$/i.test(self)}
1154
1155
$StringDict.isdecimal = function(self) {
1156
// this is not 100% correct
1157
return /^[0-9]+$/.test(self)
1158
}
1159
1160
$StringDict.isdigit = function(self) { return /^[0-9]+$/.test(self)}
1161
1162
$StringDict.isidentifier = function(self) {
1163
//var keywords=['False', 'None', 'True', 'and', 'as', 'assert', 'break',
1164
// 'class', 'continue', 'def', 'del', 'elif', 'else', 'except', 'finally',
1165
// 'for', 'from', 'global', 'if', 'import', 'in', 'is', 'lambda', 'nonlocal',
1166
// 'not', 'or', 'pass', 'raise', 'return', 'try', 'while', 'with', 'yield'];
1167
1168
switch(self) {
1169
case 'False':
1170
case 'None':
1171
case 'True':
1172
case 'and':
1173
case 'as':
1174
case 'assert':
1175
case 'break':
1176
case 'class':
1177
case 'continue':
1178
case 'def':
1179
case 'del':
1180
case 'elif':
1181
case 'else':
1182
case 'except':
1183
case 'finally':
1184
case 'for':
1185
case 'from':
1186
case 'global':
1187
case 'if':
1188
case 'import':
1189
case 'in':
1190
case 'is':
1191
case 'lambda':
1192
case 'nonlocal':
1193
case 'not':
1194
case 'or':
1195
case 'pass':
1196
case 'raise':
1197
case 'return':
1198
case 'try':
1199
case 'while':
1200
case 'with':
1201
case 'yield':
1202
return true
1203
}
1204
1205
// fixme.. this isn't complete but should be a good start
1206
return /^[a-z][0-9a-z_]+$/i.test(self)
1207
}
1208
1209
$StringDict.islower = function(self) {return /^[a-z]+$/.test(self)}
1210
1211
// not sure how to handle unicode variables
1212
$StringDict.isnumeric = function(self) {return /^[0-9]+$/.test(self)}
1213
1214
// inspired by http://www.codingforums.com/archive/index.php/t-17925.html
1215
$StringDict.isprintable = function(self) {return !/[^ -~]/.test(self)}
1216
1217
$StringDict.isspace = function(self) {return /^\s+$/i.test(self)}
1218
1219
$StringDict.istitle = function(self) {return /^([A-Z][a-z]+)(\s[A-Z][a-z]+)$/i.test(self)}
1220
1221
$StringDict.isupper = function(self) {return /^[A-Z]+$/.test(self)}
1222
1223
$StringDict.join = function(self,obj){
1224
var iterable=iter(obj)
1225
var res = '',count=0
1226
while(1){
1227
try{
1228
var obj2 = next(iterable)
1229
if(!isinstance(obj2,str)){throw _b_.TypeError(
1230
"sequence item "+count+": expected str instance, "+$B.get_class(obj2).__name__+" found")}
1231
res += obj2+self
1232
count++
1233
}catch(err){
1234
if(err.__name__==='StopIteration'){$B.$pop_exc();break}
1235
else{throw err}
1236
}
1237
}
1238
if(count==0) return ''
1239
return res.substr(0,res.length-self.length)
1240
}
1241
1242
$StringDict.ljust = function(self, width, fillchar) {
1243
if (width <= self.length) return self
1244
if (fillchar === undefined) fillchar=' '
1245
return self + Array(width - self.length + 1).join(fillchar)
1246
}
1247
1248
$StringDict.lower = function(self){return self.toLowerCase()}
1249
1250
$StringDict.lstrip = function(self,x){
1251
var pattern = null
1252
if(x==undefined){pattern="\\s*"}
1253
else{pattern = "["+x+"]*"}
1254
var sp = new RegExp("^"+pattern)
1255
return self.replace(sp,"")
1256
}
1257
1258
// note, maketrans should be a static function.
1259
$StringDict.maketrans = function(from, to) {
1260
var _t=[]
1261
// make 'default' translate table
1262
for(var i=0; i < 256; i++) _t[i]=String.fromCharCode(i)
1263
1264
// make substitution in the translation table
1266
var _ndx=from.source[i].charCodeAt(0) //retrieve ascii code of char
1267
_t[_ndx]=to.source[i]
1268
}
1269
1270
// create a data structure that string.translate understands
1271
var _d=$B.$dict()
1272
for(var i=0; i < 256; i++) {
1274
}
1275
return _d
1276
}
1277
1278
$StringDict.partition = function(self,sep) {
1279
if (sep === undefined) {
1280
throw Error("sep argument is required");
1281
return
1282
}
1283
var i=self.indexOf(sep)
1284
if (i== -1) return _b_.tuple([self, '', ''])
1285
return _b_.tuple([self.substring(0,i), sep, self.substring(i+sep.length)])
1286
}
1287
1288
function $re_escape(str)
1289
{
1290
var specials = "[.*+?|()$^"
1292
var re = new RegExp('\\'+specials.charAt(i),'g')
1293
str = str.replace(re, "\\"+specials.charAt(i))
1294
}
1295
return str
1296
}
1297
1298
$StringDict.replace = function(self, old, _new, count) {
1299
// Replaces occurrences of 'old' by '_new'. Count references
1300
// the number of times to replace. In CPython, negative or undefined
1301
// values of count means replace all.
1302
if (count === undefined) {
1303
count = -1;
1304
} else {
1305
// Validate instance type of 'count'
1306
if (!isinstance(count,[_b_.int,_b_.float])) {
1307
throw _b_.TypeError("'" + str(count.__class__) + "' object cannot be interpreted as an integer");
1308
} else if (isinstance(count, _b_.float)) {
1309
throw _b_.TypeError("integer argument expected, got float");
1312
1313
var res = self.valueOf();
1314
var pos = -1;
1315
if (count < 0) count = res.length;
1316
while (count > 0) {
1317
pos = res.indexOf(old, pos);
1318
if (pos < 0)
1319
break;
1320
res = res.substr(0, pos) + _new + res.substr(pos + old.length);
1321
pos = pos + _new.length;
1322
count--;
1323
}
1324
return res;
1325
}
1326
1327
$StringDict.rfind = function(self){
1328
// Return the highest index in the string where substring sub is found,
1329
// such that sub is contained within s[start:end]. Optional arguments
1330
// start and end are interpreted as in slice notation. Return -1 on failure.
1331
var start=0,end=self.length
1332
var $ns=$B.$MakeArgs("$StringDict.find",arguments,['self','sub'],
1333
['start','end'],null,null)
1334
for(var attr in $ns){eval('var '+attr+'=$ns[attr]')}
1335
if(!isinstance(sub,str)){throw _b_.TypeError(
1336
"Can't convert '"+sub.__class__.__name__+"' object to str implicitly")}
1337
if(!isinstance(start,_b_.int)||!isinstance(end,_b_.int)){throw _b_.TypeError(
1338
"slice indices must be integers or None or have an __index__ method")}
1339
1340
var s = self.substring(start,end)
1341
var reversed = '',rsub=''
1342
for(var i=s.length-1;i>=0;i--){reversed += s.charAt(i)}
1343
for(var i=sub.length-1;i>=0;i--){rsub += sub.charAt(i)}
1344
var res = reversed.search($re_escape(rsub))
1345
if(res==-1) return -1
1346
return start+s.length-1-res-sub.length+1
1347
}
1348
1349
$StringDict.rindex = function(){
1350
// Like rfind() but raises ValueError when the substring sub is not found
1351
var res = $StringDict.rfind.apply(this,arguments)
1352
if(res==-1){throw _b_.ValueError("substring not found")}
1353
return res
1354
}
1355
1356
$StringDict.rjust = function(self) {
1357
var fillchar = ' '
1358
var $ns=$B.$MakeArgs("$StringDict.rjust",arguments,['self','width'],
1359
['fillchar'],null,null)
1360
for(var attr in $ns){eval('var '+attr+'=$ns[attr]')}
1361
1362
if (width <= self.length) return self
1363
1364
return Array(width - self.length + 1).join(fillchar) + self
1365
}
1366
1367
$StringDict.rpartition = function(self,sep) {
1368
if (sep === undefined) {
1369
throw Error("sep argument is required");
1370
return
1371
}
1372
var pos=self.length-sep.length
1373
while(1){
1374
if(self.substr(pos,sep.length)==sep){
1375
return _b_.tuple([self.substr(0,pos),sep,self.substr(pos+sep.length)])
1376
}else{
1377
pos--
1378
if(pos<0){return _b_.tuple(['','',self])}
1379
}
1380
}
1381
}
1382
1383
$StringDict.rsplit = function(self) {
1384
var args = []
1386
var $ns=$B.$MakeArgs("$StringDict.rsplit",args,[],[],'args','kw')
1387
var sep=None,maxsplit=-1
1388
if($ns['args'].length>=1){sep=$ns['args'][0]}
1389
if($ns['args'].length==2){maxsplit=$ns['args'][1]}
1396
if (array.length <= maxsplit || maxsplit == -1) return array
1397
1398
var s=[]
1399
1400
s = array.splice(array.length - maxsplit, array.length)
1401
s.splice(0, 0, array.join(sep))
1402
1403
return s
1404
}
1405
1406
$StringDict.rstrip = function(self,x){
1407
if(x==undefined){var pattern="\\s*"}
1408
else{var pattern = "["+x+"]*"}
1409
sp = new RegExp(pattern+'$')
1410
return str(self.replace(sp,""))
1411
}
1412
1413
$StringDict.split = function(self){
1414
var args = []
1416
var $ns=$B.$MakeArgs("$StringDict.split",args,[],[],'args','kw')
1417
var sep=None,maxsplit=-1
1418
if($ns['args'].length>=1){sep=$ns['args'][0]}
1419
if($ns['args'].length==2){maxsplit=$ns['args'][1]}
1420
maxsplit = _b_.dict.$dict.get($ns['kw'],'maxsplit',maxsplit)
1422
if(sep===None){
1423
var res = []
1424
var pos = 0
1425
while(pos<self.length&&self.charAt(pos).search(/\s/)>-1){pos++}
1426
if(pos===self.length-1){return []}
1427
var name = ''
1428
while(1){
1429
if(self.charAt(pos).search(/\s/)===-1){
1430
if(name===''){name=self.charAt(pos)}
1431
else{name+=self.charAt(pos)}
1432
}else{
1433
if(name!==''){
1434
res.push(name)
1435
if(maxsplit!==-1&&res.length===maxsplit+1){
1436
res.pop()
1437
res.push(name+self.substr(pos))
1438
return res
1439
}
1440
name=''
1441
}
1442
}
1443
pos++
1444
if(pos>self.length-1){
1445
if(name){res.push(name)}
1446
break
1447
}
1448
}
1449
return res
1450
}else{
1451
//var escaped = ['*','.','[',']','(',')','|','$','^']
1452
var esc_sep = ''
1454
switch(sep.charAt(i)) {
1455
case '*':
1456
case '.':
1457
case '[':
1458
case ']':
1459
case '(':
1460
case ')':
1461
case '|':
1462
case '$':
1463
case '^':
1464
//if(escaped.indexOf(sep.charAt(i))>-1){esc_sep += '\\'}
1465
esc_sep += '\\'
1466
}
1467
esc_sep += sep.charAt(i)
1468
}
1469
var re = new RegExp(esc_sep)
1470
if (maxsplit==-1){
1471
// use native Javascript split on self
1472
return self.valueOf().split(re,maxsplit)
1473
}
1474
1475
// javascript split behavior is different from python when
1476
// a maxsplit argument is supplied. (see javascript string split
1477
// function docs for details)
1478
var l=self.valueOf().split(re,-1)
1481
if (b.length > 0) a.push(b.join(sep))
1482
1483
return a
1484
}
1485
}
1486
1487
$StringDict.splitlines = function(self){return $StringDict.split(self,'\n')}
1488
1489
$StringDict.startswith = function(self){
1490
// Return True if string starts with the prefix, otherwise return False.
1491
// prefix can also be a tuple of prefixes to look for. With optional
1492
// start, test string beginning at that position. With optional end,
1493
// stop comparing string at that position.
1494
var $ns=$B.$MakeArgs("$StringDict.startswith",arguments,['self','prefix'],
1495
['start','end'],null,null)
1496
var prefixes = $ns['prefix']
1497
if(!isinstance(prefixes,_b_.tuple)){prefixes=[prefixes]}
1498
var start = $ns['start'] || 0
1499
var end = $ns['end'] || self.length-1
1500
var s = self.substr(start,end+1)
1501
1503
if (s.indexOf(prefixes[i]) == 0) return true
1504
}
1505
return false
1506
}
1507
1508
$StringDict.strip = function(self,x){
1509
if(x==undefined){x = "\\s"}
1510
return $StringDict.rstrip($StringDict.lstrip(self,x),x)
1511
}
1512
1513
$StringDict.swapcase = function(self) {
1514
//inspired by http://www.geekpedia.com/code69_Swap-string-case-using-JavaScript.html
1515
return self.replace(/([a-z])|([A-Z])/g, function($0,$1,$2)
1516
{ return ($1) ? $0.toUpperCase() : $0.toLowerCase()
1517
})
1518
}
1519
1520
$StringDict.title = function(self) {
1521
//inspired from http://stackoverflow.com/questions/196972/convert-string-to-title-case-with-javascript
1522
return self.replace(/\w\S*/g, function(txt){return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();});
1523
}
1524
1525
$StringDict.translate = function(self,table) {
1526
var res = ''
1527
if (isinstance(table, _b_.dict)) {
1529
var repl = _b_.dict.$dict.get(table,self.charCodeAt(i),-1)
1530
if(repl==-1){res += self.charAt(i)}
1531
else if(repl!==None){res += repl}
1532
}
1533
}
1534
return res
1535
}
1536
1537
$StringDict.upper = function(self){return self.toUpperCase()}
1538
1539
$StringDict.zfill = function(self, width) {
1540
if (width === undefined || width <= self.length || !self.isnumeric()) {
1541
return self
1542
}
1543
1544
return Array(width - self.length +1).join('0');
1545
}
1546
1547
function str(arg){
1548
if(arg===undefined) return ''
1549
1550
try{ // try __str__
1551
var f = getattr(arg,'__str__')
1552
// XXX fix : if not better than object.__str__, try __repr__
1553
return f()
1554
}
1555
catch(err){
1556
$B.$pop_exc()
1557
try{ // try __repr__
1558
var f = getattr(arg,'__repr__')
1560
}catch(err){
1561
$B.$pop_exc()
1562
console.log(err+'\ndefault to toString '+arg);return arg.toString()
1563
}
1564
}
1565
}
1566
str.__class__ = $B.$factory
1567
str.$dict = $StringDict
1568
$StringDict.$factory = str
1569
$StringDict.__new__ = function(cls){
1570
if(cls===undefined){
1571
throw _b_.TypeError('str.__new__(): not enough arguments')
1572
}
1573
return {__class__:cls.$dict}
1574
}
1575
1578
// dictionary and factory for subclasses of string
1579
var $StringSubclassDict = {
1580
__class__:$B.$type,
1581
__name__:'str'
1582
}
1583
1584
// the methods in subclass apply the methods in $StringDict to the
1585
// result of instance.valueOf(), which is a Javascript string
1586
for(var $attr in $StringDict){
1587
if(typeof $StringDict[$attr]=='function'){
1588
$StringSubclassDict[$attr]=(function(attr){
1589
return function(){
1590
var args = []
1591
if(arguments.length>0){
1592
var args = [arguments[0].valueOf()]
1594
args.push(arguments[i])
1595
}
1596
}
1597
return $StringDict[attr].apply(null,args)
1598
}
1599
})($attr)
1600
}
1601
}
1602
$StringSubclassDict.__mro__ = [$StringSubclassDict,$ObjectDict]
1603
1604
// factory for str subclasses
1605
$B.$StringSubclassFactory = {
1606
__class__:$B.$factory,
1607
$dict:$StringSubclassDict
1608
}
1609
1610
_b_.str = str
1611
1612
})(__BRYTHON__)