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