Skip to content
Permalink
Newer
Older
100644 1635 lines (1425 sloc) 53 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
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
}
542
$notimplemented += '' // coerce to string
543
for(var $op in $B.$operators){
544
var $opfunc = '__'+$B.$operators[$op]+'__'
545
if(!($opfunc in str)){
546
//eval('$StringDict.'+$opfunc+"="+$notimplemented.replace(/OPERATOR/gm,$op))
547
}
548
}
549
550
$StringDict.capitalize = function(self){
551
if(self.length==0) return ''
552
return self.charAt(0).toUpperCase()+self.substr(1).toLowerCase()
553
}
554
555
$StringDict.casefold = function(self) {
556
throw _b_.NotImplementedError("function casefold not implemented yet");
557
}
558
559
$StringDict.center = function(self,width,fillchar){
560
if(fillchar===undefined){fillchar=' '}else{fillchar=fillchar}
561
if(width<=self.length) return self
562
563
var pad = parseInt((width-self.length)/2)
564
var res = Array(pad+1).join(fillchar) // is this statement faster than the for loop below?
565
res += self + res
566
if(res.length<width){res += fillchar}
567
return res
568
}
569
570
$StringDict.count = function(self,elt){
571
if(!(typeof elt==="string")){throw _b_.TypeError(
572
"Can't convert '"+elt.__class__.__name__+"' object to str implicitly")}
573
//needs to be non overlapping occurrences of substring in string.
574
var n=0, pos=0
575
while(1){
576
pos=self.indexOf(elt,pos)
577
if(pos>=0){ n++; pos+=elt.length} else break;
578
}
579
return n
580
}
581
582
$StringDict.encode = function(self, encoding) {
583
if (encoding === undefined) encoding='utf-8'
584
return bytes(self, encoding)
585
}
586
587
$StringDict.endswith = function(self){
588
// Return True if the string ends with the specified suffix, otherwise
589
// return False. suffix can also be a tuple of suffixes to look for.
590
// With optional start, test beginning at that position. With optional
591
// end, stop comparing at that position.
592
var args = []
593
for(var i=1;i<arguments.length;i++){args.push(arguments[i])}
594
var start=null,end=null
595
var $ns=$B.$MakeArgs("$StringDict.endswith",args,['suffix'],
596
['start','end'],null,null)
597
var suffixes = $ns['suffix']
598
if(!isinstance(suffixes,_b_.tuple)){suffixes=[suffixes]}
599
start = $ns['start'] || start
600
end = $ns['end'] || self.length-1
601
var s = self.substr(start,end+1)
602
for(var i=0;i<suffixes.length;i++){
603
suffix = suffixes[i]
604
if(suffix.length<=s.length &&
605
s.substr(s.length-suffix.length)==suffix) return true
606
}
607
return false
608
}
609
610
$StringDict.expandtabs = function(self, tabsize) {
611
tabsize=tabsize || 8
612
var _str=''
613
for (var i=0; i < tabsize; i++) _str+=' '
614
return self.valueOf().replace(/\t/g, _str)
615
}
616
617
$StringDict.find = function(self){
618
// Return the lowest index in the string where substring sub is found,
619
// such that sub is contained in the slice s[start:end]. Optional
620
// arguments start and end are interpreted as in slice notation.
621
// Return -1 if sub is not found.
622
var start=0,end=self.length
623
var $ns=$B.$MakeArgs("$StringDict.find",arguments,['self','sub'],
624
['start','end'],null,null)
625
for(var attr in $ns){eval('var '+attr+'=$ns[attr]')}
626
if(!isinstance(sub,str)){throw _b_.TypeError(
627
"Can't convert '"+sub.__class__.__name__+"' object to str implicitly")}
628
if(!isinstance(start,_b_.int)||!isinstance(end,_b_.int)){
629
throw _b_.TypeError(
630
"slice indices must be integers or None or have an __index__ method")}
631
var s = self.substring(start,end)
632
//var escaped = ['[','.','*','+','?','|','(',')','$','^']
633
var esc_sub = ''
634
for(var i=0;i<sub.length;i++){
635
switch(sub.charAt(i)) {
636
case '[':
637
case '.':
638
case '*':
639
case '+':
640
case '?':
641
case '|':
642
case '(':
643
case ')':
644
case '$':
645
case '^':
646
//if(escaped.indexOf(sub.charAt(i))>-1){
647
esc_sub += '\\'
648
}
649
esc_sub += sub.charAt(i)
650
}
651
var res = s.search(esc_sub)
652
if(res==-1) return -1
653
return start+res
654
}
655
656
var $FormattableString=function(format_string) {
657
// inspired from
658
// https://raw.github.com/florentx/stringformat/master/stringformat.py
659
this.format_string=format_string
660
661
this._prepare = function() {
662
//console.log('prepare')
663
var match = arguments[0]
664
//console.log('match1', match)
665
666
var p1 = '' + arguments[2]
667
668
if (match == '%') return '%%'
669
if (match.substring(0,1) == match.substring(match.length-1)) {
670
// '{{' or '}}'
671
return match.substring(0, Math.floor(match.length/2))
672
}
673
674
if (p1.charAt(0) == '{' && p1.charAt(match.length-1) == '}') {
675
p1=match.substring(1, p1.length-1)
676
}
677
678
var _repl
679
if (match.length >= 2) {
680
_repl=''
681
} else {
682
_repl = match.substring(1)
683
}
684
685
var _i = p1.indexOf(':')
686
var _out
687
if (_i > -1) {
688
_out = [p1.slice(0,_i), p1.slice(_i+1)]
689
//var _out = p1.split(':') // only want to split on first ':'
690
} else { _out=[p1]}
691
692
var _field=_out[0] || ''
693
var _format_spec=_out[1] || ''
694
695
_out= _field.split('!')
696
var _literal=_out[0] || ''
697
var _sep=_field.indexOf('!') > -1?'!': undefined // _out[1]
698
var _conv=_out[1] //conversion
699
700
if (_sep && _conv === undefined) {
701
throw _b_.ValueError("end of format while looking for conversion specifier")
702
}
703
704
if (_conv !== undefined && _conv.length > 1) {
705
throw _b_.ValueError("expected ':' after format specifier")
706
}
707
708
if (_conv !== undefined && 'rsa'.indexOf(_conv) == -1) {
709
throw _b_.ValueError("Unknown conversion specifier " + _conv)
710
}
711
712
_name_parts=this.field_part.apply(null, [_literal])
713
714
var _start=_literal.charAt(0)
715
var _name=''
716
if (_start=='' || _start=='.' || _start == '[') {
717
// auto-numbering
718
if (this._index === undefined) {
719
throw _b_.ValueError("cannot switch from manual field specification to automatic field numbering")
720
}
721
722
_name = self._index.toString()
723
this._index+=1
724
725
if (! _literal ) {
726
_name_parts.shift()
727
}
728
} else {
729
_name = _name_parts.shift()[1]
730
if (this._index !== undefined && !isNaN(_name)) {
Sep 5, 2014
731
// manual specification
732
if (this._index) {
733
throw _b_.ValueError("cannot switch from automatic field " +
734
"numbering to manual field specification")
735
this._index=undefined
736
}
737
}
738
}
739
740
var _empty_attribute=false
741
742
//console.log('name', _name)
743
var _k
744
for (var i=0; i < _name_parts.length; i++) {
745
_k = _name_parts[i][0]
746
var _v = _name_parts[i][1]
747
var _tail = _name_parts[i][2]
748
//console.log('_v', _v)
749
if (_v === '') {_empty_attribute = true}
750
//console.log(_tail)
751
if (_tail !== '') {
752
throw _b_.ValueError("Only '.' or '[' may follow ']' " +
753
"in format field specifier")
754
}
755
}
756
757
if (_name_parts && _k == '[' && !
758
_literal.charAt(_literal.length) == ']') {
759
throw _b_.ValueError("Missing ']' in format string")
760
}
761
762
if (_empty_attribute) {
763
throw _b_.ValueError("Empty attribute in format string")
764
}
765
766
var _rv=''
767
if (_format_spec.indexOf('{') != -1) {
768
_format_spec = _format_spec.replace(this.format_sub_re, this._prepare)
769
_rv = [_name_parts, _conv, _format_spec]
770
if (this._nested[_name] === undefined) {
771
this._nested[_name]=[]
772
this._nested_array.push(_name)
773
}
774
this._nested[_name].push(_rv)
775
} else {
776
_rv = [_name_parts, _conv, _format_spec]
777
if (this._kwords[_name] === undefined) {
778
this._kwords[_name]=[]
779
this._kwords_array.push(_name)
780
}
781
this._kwords[_name].push(_rv)
782
}
783
784
//console.log('_rv', _rv)
785
return '%(' + id(_rv) + ')s'
786
} // this._prepare
787
788
this.format=function() {
789
//console.log('format')
790
// same as str.format() and unicode.format in Python 2.6+
791
792
var $ns=$B.$MakeArgs('format',arguments,[],[],'args','kwargs')
793
var args=$ns['args']
794
var kwargs=$ns['kwargs']
795
796
if (args.length>0) {
797
for (var i=0; i < args.length; i++) {
798
//kwargs[str(i)]=args.$dict[i]
799
getattr(kwargs, '__setitem__')(str(i), args[i])
800
}
801
}
802
803
//encode arguments to ASCII, if format string is bytes
804
var _want_bytes = isinstance(this._string, str)
805
var _params=_b_.dict()
806
807
for (var i=0; i < this._kwords_array.length; i++) {
808
var _name = this._kwords_array[i]
809
var _items = this._kwords[_name]
810
var _var = getattr(kwargs, '__getitem__')(_name)
811
var _value;
812
if (hasattr(_var, 'value')) {
813
//_value = getattr(getattr(kwargs, '__getitem__')(_name), 'value')
814
_value = getattr(_var, 'value')
815
} else {
816
_value=_var
817
}
818
819
for (var j=0; j < _items.length; j++) {
820
var _parts = _items[j][0]
821
var _conv = _items[j][1]
822
var _spec = _items[j][2]
823
824
//console.log('legacy_format:', _spec, _params)
825
//_spec=$legacy_format(_spec, _params)
826
827
var _f=this.format_field.apply(null, [_value, _parts,_conv,_spec,_want_bytes])
828
getattr(_params,'__setitem__')(id(_items[j]).toString(), _f)
829
}
830
}
831
832
for (var i=0; i < this._nested_array.length; i++) {
833
var _name = this._nested_array[i]
834
var _items = this._nested[i]
835
836
var _var = getattr(kwargs, '__getitem__')(_name)
837
var _value;
838
if (hasattr(_var, 'value')) {
839
_value = getattr(getattr(kwargs, '__getitem__')(_name), 'value')
840
} else {
841
_value=_var
842
}
843
844
for (var j=0; j < _items.length; j++) {
845
var _parts = _items[j][0]
846
var _conv = _items[j][1]
847
var _spec = _items[j][2]
848
849
//console.log('legacy_format:', _spec, _params)
850
_spec=$legacy_format(_spec, _params)
851
852
var _f=this.format_field.apply(null, [_value, _parts,_conv,_spec,_want_bytes])
853
getattr(_params,'__setitem__')(id(_items[j]).toString(), _f)
854
}
855
}
856
//console.log('legacy_format:', this._string, _params)
857
return $legacy_format(this._string, _params)
858
} // this.format
859
860
this.format_field=function(value,parts,conv,spec,want_bytes) {
861
//console.log('format_field')
862
863
if (want_bytes === undefined) want_bytes = false
864
865
for (var i=0; i < parts.length; i++) {
866
var _k = parts[i][0]
867
var _part = parts[i][1]
868
869
if (_k) {
870
if (!isNaN(_part)) {
871
value = value[parseInt(_part)]
872
} else {
873
value = getattr(value, _part)
874
}
875
} else {
876
value = value[_part]
877
}
878
}
879
880
if (conv) {
881
// fix me
882
//console.log('legacy_format:', conv, value)
883
value = $legacy_format((conv == 'r') && '%r' || '%s', value)
884
}
885
886
value = this.strformat(value, spec)
887
//value=this.strformat.apply(null, [value, spec])
888
889
if (want_bytes) { // && isinstance(value, unicode)) {
890
return value.toString()
891
}
892
893
return value
894
}
895
896
this.strformat=function(value, format_spec) {
897
//console.log('strformat')
898
if (format_spec === undefined) format_spec = ''
899
//console.log(value)
900
//console.log(format_spec)
901
if (!isinstance(value,[str,_b_.int]) && hasattr(value, '__format__')) {
902
return getattr(value, '__format__')(format_spec)
903
}
904
var _m = this.format_spec_re.test(format_spec)
905
906
if (!_m) throw _b_.ValueError('Invalid conversion specification')
907
908
var _match=this.format_spec_re.exec(format_spec)
909
var _align=_match[1]
910
var _sign=_match[2]
911
var _prefix=_match[3]
912
var _width=_match[4]
913
var _comma=_match[5]
914
var _precision=_match[6]
915
var _conversion=_match[7]
916
917
var _is_numeric = isinstance(value, _b_.float)
918
var _is_integer = isinstance(value, _b_.int)
919
920
//console.log('match', _match)
921
922
if (_prefix != '' && ! _is_numeric) {
923
if (_is_numeric) {
924
throw _b_.ValueError('Alternate form (#) not allowed in float format specifier')
925
} else {
926
throw _b_.ValueError('Alternate form (#) not allowed in string format specification')
927
}
928
}
929
930
if (_is_numeric && _conversion == 'n') {
931
_conversion = _is_integer && 'd' || 'g'
932
} else {
933
if (_sign) {
934
if (! _is_numeric) {
935
throw _b_.ValueError('Sign not allowed in string format specification');
936
}
937
if (_conversion == 'c') {
938
throw("Sign not allowed with integer format specifier 'c'")
939
}
940
}
941
}
942
943
if (_comma !== '') {
944
value += ''
945
var x = value.split('.')
946
var x1 = x[0];
947
var x2 = x.length > 1 ? '.' + x[1] : '';
948
var rgx = /(\d+)(\d{3})/;
949
950
while (rgx.test(x1)) {
951
x1 = x1.replace(rgx, '$1' + ',' + '$2');
952
}
953
value=x1+x2
954
}
955
956
var _rv
957
if (_conversion != '' && ((_is_numeric && _conversion == 's') ||
958
(! _is_integer && 'coxX'.indexOf(_conversion) != -1))) {
959
console.log(_conversion)
960
throw _b_.ValueError('Fix me')
961
}
962
963
if (_conversion == 'c') _conversion = 's'
964
965
// fix me
966
_rv='%' + _prefix + _precision + (_conversion || 's')
967
968
//console.log('legacy_format', _rv, value)
969
_rv = $legacy_format(_rv, value)
970
971
if (_sign != '-' && value >= 0) _rv = _sign + _rv
972
973
var _zero = false
974
if (_width) {
975
//_zero = _width.substring(0,1) == '0'
976
_zero = _width.charAt(0) == '0'
977
_width = parseInt(_width)
978
} else {
979
_width = 0
980
}
981
982
// Fastpath when alignment is not required
983
984
if (_width <= _rv.length) {
985
if (! _is_numeric && (_align == '=' || (_zero && ! _align))) {
986
throw _b_.ValueError("'=' alignment not allowed in string format specifier")
987
}
988
return _rv
989
}
990
991
_fill = _align.substr(0,_align.length-1)
992
_align= _align.substr(_align.length-1)
993
994
if (! _fill) {_fill = _zero && '0' || ' '}
995
996
if (_align == '^') {
997
_rv = getattr(_rv, 'center')(_width, _fill)
998
} else if (_align == '=' || (_zero && ! _align)) {
999
if (! _is_numeric) {
1000
throw _b_.ValueError("'=' alignment not allowed in string format specifier")
1001
}
1002
if (_value < 0 || _sign != '-') {
1003
_rv = _rv.substring(0,1) + getattr(_rv.substring(1),'rjust')(_width - 1, _fill)
1004
} else {
1005
_rv = getattr(_rv, 'rjust')(_width, _fill)
1006
}
1007
} else if ((_align == '>' || _align == '=') || (_is_numeric && ! _aligned)) {
1008
_rv = getattr(_rv, 'rjust')(_width, _fill)
1009
} else if (_align == '<') {
1010
_rv = getattr(_rv, 'ljust')(_width, _fill)
1011
} else {
1012
throw _b_.ValueError("'" + _align + "' alignment not valid")
1013
}
1014
1015
return _rv
1016
}
1017
1018
this.field_part=function(literal) {
1019
//console.log('field_part')
1020
if (literal.length == 0) return [['','','']]
1021
1022
var _matches=[]
1023
var _pos=0
1024
1025
var _start='', _middle='', _end=''
1026
var arg_name=''
1027
1028
// arg_name
1029
if (literal === undefined) console.log(literal)
1030
var _lit=literal.charAt(_pos)
1031
while (_pos < literal.length &&
1032
_lit !== '[' && _lit !== '.') {
1033
//console.log(literal.charAt(_pos))
1034
arg_name += _lit
1035
_pos++
1036
_lit=literal.charAt(_pos)
1037
}
1038
1039
// todo.. need to work on code below, but this takes cares of most
1040
// common cases.
1041
if (arg_name != '') _matches.push(['', arg_name, ''])
1042
1043
//return _matches
1044
1045
var attribute_name=''
1046
var element_index=''
1047
1048
//look for attribute_name and element_index
1049
while (_pos < literal.length) {
1050
var car = literal.charAt(_pos)
1051
//console.log(_pos, car)
1052
1053
if (car == '[') { // element_index
1054
_start=_middle=_end=''
1055
_pos++
1056
1057
car = literal.charAt(_pos)
1058
while (_pos < literal.length && car !== ']') {
1059
_middle += car
1060
_pos++
1061
car = literal.charAt(_pos)
1062
//console.log(car)
1063
}
1064
1065
_pos++
1066
if (car == ']') {
1067
while (_pos < literal.length) {
1068
_end+=literal.charAt(_pos)
1069
_pos++
1070
}
1071
}
1072
1073
_matches.push([_start, _middle, _end])
1074
1075
} else if (car == '.') { // attribute_name
1076
_middle=''
1077
_pos++
1078
car = literal.charAt(_pos)
1079
while (_pos < literal.length &&
1080
car !== '[' &&
1081
car !== '.') {
1082
//console.log(car)
1083
_middle += car
1084
_pos++
1085
car = literal.charAt(_pos)
1086
}
1087
1088
_matches.push(['.', _middle, ''])
1089
}
1090
}
1091
//console.log(_matches)
1092
return _matches
1093
}
1094
1095
this.format_str_re = new RegExp(
1096
'(%)' +
1097
'|((?!{)(?:{{)+' +
1098
'|(?:}})+(?!})' +
1099
'|{(?:[^{](?:[^{}]+|{[^{}]*})*)?})', 'g'
1100
)
1101
1102
this.format_sub_re = new RegExp('({[^{}]*})') // nested replacement field
1103
1104
this.format_spec_re = new RegExp(
1105
'((?:[^{}]?[<>=^])?)' + // alignment
1106
'([\\-\\+ ]?)' + // sign
1107
'(#?)' + '(\\d*)' + '(,?)' + // base prefix, minimal width, thousands sep
1108
'((?:\.\\d+)?)' + // precision
1109
'(.?)$' // type
1110
)
1111
1112
this._index = 0
1113
this._kwords = {}
1114
this._kwords_array=[]
1115
this._nested = {}
1116
this._nested_array=[]
1117
1118
this._string=format_string.replace(this.format_str_re, this._prepare)
1119
1120
return this
1121
}
1122
1123
1124
$StringDict.format = function(self) {
1125
1126
var _fs = $FormattableString(self.valueOf())
1127
var args=[]
1128
// we don't need the first item (ie, self)
1129
for (var i =1; i < arguments.length; i++) { args.push(arguments[i])}
1130
return _fs.format.apply(null, args)
1131
}
1132
1133
$StringDict.format_map = function(self) {
1134
throw NotImplementedError("function format_map not implemented yet");
1135
}
1136
1137
$StringDict.index = function(self){
1138
// Like find(), but raise ValueError when the substring is not found.
1139
var res = $StringDict.find.apply(self,arguments)
1140
if(res===-1) throw _b_.ValueError("substring not found")
1141
return res
1142
}
1143
1144
$StringDict.isalnum = function(self) {return /^[a-z0-9]+$/i.test(self)}
1145
1146
$StringDict.isalpha = function(self) {return /^[a-z]+$/i.test(self)}
1147
1148
$StringDict.isdecimal = function(self) {
1149
// this is not 100% correct
1150
return /^[0-9]+$/.test(self)
1151
}
1152
1153
$StringDict.isdigit = function(self) { return /^[0-9]+$/.test(self)}
1154
1155
$StringDict.isidentifier = function(self) {
1156
//var keywords=['False', 'None', 'True', 'and', 'as', 'assert', 'break',
1157
// 'class', 'continue', 'def', 'del', 'elif', 'else', 'except', 'finally',
1158
// 'for', 'from', 'global', 'if', 'import', 'in', 'is', 'lambda', 'nonlocal',
1159
// 'not', 'or', 'pass', 'raise', 'return', 'try', 'while', 'with', 'yield'];
1160
1161
switch(self) {
1162
case 'False':
1163
case 'None':
1164
case 'True':
1165
case 'and':
1166
case 'as':
1167
case 'assert':
1168
case 'break':
1169
case 'class':
1170
case 'continue':
1171
case 'def':
1172
case 'del':
1173
case 'elif':
1174
case 'else':
1175
case 'except':
1176
case 'finally':
1177
case 'for':
1178
case 'from':
1179
case 'global':
1180
case 'if':
1181
case 'import':
1182
case 'in':
1183
case 'is':
1184
case 'lambda':
1185
case 'nonlocal':
1186
case 'not':
1187
case 'or':
1188
case 'pass':
1189
case 'raise':
1190
case 'return':
1191
case 'try':
1192
case 'while':
1193
case 'with':
1194
case 'yield':
1195
return true
1196
}
1197
1198
// fixme.. this isn't complete but should be a good start
1199
return /^[a-z][0-9a-z_]+$/i.test(self)
1200
}
1201
1202
$StringDict.islower = function(self) {return /^[a-z]+$/.test(self)}
1203
1204
// not sure how to handle unicode variables
1205
$StringDict.isnumeric = function(self) {return /^[0-9]+$/.test(self)}
1206
1207
// inspired by http://www.codingforums.com/archive/index.php/t-17925.html
1208
$StringDict.isprintable = function(self) {return !/[^ -~]/.test(self)}
1209
1210
$StringDict.isspace = function(self) {return /^\s+$/i.test(self)}
1211
1212
$StringDict.istitle = function(self) {return /^([A-Z][a-z]+)(\s[A-Z][a-z]+)$/i.test(self)}
1213
1214
$StringDict.isupper = function(self) {return /^[A-Z]+$/.test(self)}
1215
1216
$StringDict.join = function(self,obj){
1217
var iterable=iter(obj)
1218
var res = '',count=0
1219
while(1){
1220
try{
1221
var obj2 = next(iterable)
1222
if(!isinstance(obj2,str)){throw _b_.TypeError(
1223
"sequence item "+count+": expected str instance, "+$B.get_class(obj2).__name__+" found")}
1224
res += obj2+self
1225
count++
1226
}catch(err){
1227
if(err.__name__==='StopIteration'){$B.$pop_exc();break}
1228
else{throw err}
1229
}
1230
}
1231
if(count==0) return ''
1232
return res.substr(0,res.length-self.length)
1233
}
1234
1235
$StringDict.ljust = function(self, width, fillchar) {
1236
if (width <= self.length) return self
1237
if (fillchar === undefined) fillchar=' '
1238
return self + Array(width - self.length + 1).join(fillchar)
1239
}
1240
1241
$StringDict.lower = function(self){return self.toLowerCase()}
1242
1243
$StringDict.lstrip = function(self,x){
1244
var pattern = null
1245
if(x==undefined){pattern="\\s*"}
1246
else{pattern = "["+x+"]*"}
1247
var sp = new RegExp("^"+pattern)
1248
return self.replace(sp,"")
1249
}
1250
1251
// note, maketrans should be a static function.
1252
$StringDict.maketrans = function(from, to) {
1253
var _t=[]
1254
// make 'default' translate table
1255
for(var i=0; i < 256; i++) _t[i]=String.fromCharCode(i)
1256
1257
// make substitution in the translation table
1258
for(var i=0; i < from.source.length; i++) {
1259
var _ndx=from.source[i].charCodeAt(0) //retrieve ascii code of char
1260
_t[_ndx]=to.source[i]
1261
}
1262
1263
// create a data structure that string.translate understands
1264
var _d=$B.$dict()
1265
var _kpush=_d.$keys.push
1266
var _vpush=_d.$values.push
1267
for(var i=0; i < 256; i++) {
1268
_kpush(i)
1269
_vpush(_t[i])
1270
}
1271
return _d
1272
}
1273
1274
$StringDict.partition = function(self,sep) {
1275
if (sep === undefined) {
1276
throw Error("sep argument is required");
1277
return
1278
}
1279
var i=self.indexOf(sep)
1280
if (i== -1) return _b_.tuple([self, '', ''])
1281
return _b_.tuple([self.substring(0,i), sep, self.substring(i+sep.length)])
1282
}
1283
1284
function $re_escape(str)
1285
{
1286
var specials = "[.*+?|()$^"
1287
for(var i=0;i<specials.length;i++){
1288
var re = new RegExp('\\'+specials.charAt(i),'g')
1289
str = str.replace(re, "\\"+specials.charAt(i))
1290
}
1291
return str
1292
}
1293
1294
$StringDict.replace = function(self,old,_new,count){
1295
if(count!==undefined){
1296
if(!isinstance(count,[_b_.int,_b_.float])){throw __b_.TypeError(
1297
"'"+str(count.__class__)+"' object cannot be interpreted as an integer")
1298
}
1299
var re = new RegExp($re_escape(old),'g')
1300
1301
var res = self.valueOf()
1302
while(count>0){
1303
if(self.search(re)==-1){return res}
1304
res = res.replace(re,_new)
1305
count--
1306
}
1307
return res
1308
}else{
1309
var re = new RegExp($re_escape(old),"g")
1310
return self.replace(re,_new)
1311
}
1312
}
1313
1314
$StringDict.rfind = function(self){
1315
// Return the highest index in the string where substring sub is found,
1316
// such that sub is contained within s[start:end]. Optional arguments
1317
// start and end are interpreted as in slice notation. Return -1 on failure.
1318
var start=0,end=self.length
1319
var $ns=$B.$MakeArgs("$StringDict.find",arguments,['self','sub'],
1320
['start','end'],null,null)
1321
for(var attr in $ns){eval('var '+attr+'=$ns[attr]')}
1322
if(!isinstance(sub,str)){throw _b_.TypeError(
1323
"Can't convert '"+sub.__class__.__name__+"' object to str implicitly")}
1324
if(!isinstance(start,_b_.int)||!isinstance(end,_b_.int)){throw _b_.TypeError(
1325
"slice indices must be integers or None or have an __index__ method")}
1326
1327
var s = self.substring(start,end)
1328
var reversed = '',rsub=''
1329
for(var i=s.length-1;i>=0;i--){reversed += s.charAt(i)}
1330
for(var i=sub.length-1;i>=0;i--){rsub += sub.charAt(i)}
1331
var res = reversed.search($re_escape(rsub))
1332
if(res==-1) return -1
1333
return start+s.length-1-res-sub.length+1
1334
}
1335
1336
$StringDict.rindex = function(){
1337
// Like rfind() but raises ValueError when the substring sub is not found
1338
var res = $StringDict.rfind.apply(this,arguments)
1339
if(res==-1){throw _b_.ValueError("substring not found")}
1340
return res
1341
}
1342
1343
$StringDict.rjust = function(self) {
1344
var fillchar = ' '
1345
var $ns=$B.$MakeArgs("$StringDict.rjust",arguments,['self','width'],
1346
['fillchar'],null,null)
1347
for(var attr in $ns){eval('var '+attr+'=$ns[attr]')}
1348
1349
if (width <= self.length) return self
1350
1351
return Array(width - self.length + 1).join(fillchar) + self
1352
}
1353
1354
$StringDict.rpartition = function(self,sep) {
1355
if (sep === undefined) {
1356
throw Error("sep argument is required");
1357
return
1358
}
1359
var pos=self.length-sep.length
1360
while(1){
1361
if(self.substr(pos,sep.length)==sep){
1362
return _b_.tuple([self.substr(0,pos),sep,self.substr(pos+sep.length)])
1363
}else{
1364
pos--
1365
if(pos<0){return _b_.tuple(['','',self])}
1366
}
1367
}
1368
}
1369
1370
$StringDict.rsplit = function(self) {
1371
var args = []
1372
for(var i=1;i<arguments.length;i++){args.push(arguments[i])}
1373
var $ns=$B.$MakeArgs("$StringDict.rsplit",args,[],[],'args','kw')
1374
var sep=None,maxsplit=-1
1375
if($ns['args'].length>=1){sep=$ns['args'][0]}
1376
if($ns['args'].length==2){maxsplit=$ns['args'][1]}
1377
maxsplit = $ns['kw'].get('maxsplit',maxsplit)
1378
1379
var array=$StringDict.split(self)
1380
1381
if (array.length <= maxsplit) return array
1382
1383
var s=[], j=1
1384
for (var i=0; i < maxsplit - array.length; i++) {
1385
if (i < maxsplit - array.length) {
1386
if (i > 0) { s[0]+=sep}
1387
s[0]+=array[i]
1388
} else {
1389
s[j]=array[i]
1390
j+=1
1391
}
1392
}
1393
return _b_.tuple(s)
1394
}
1395
1396
$StringDict.rstrip = function(self,x){
1397
if(x==undefined){var pattern="\\s*"}
1398
else{var pattern = "["+x+"]*"}
1399
sp = new RegExp(pattern+'$')
1400
return str(self.replace(sp,""))
1401
}
1402
1403
$StringDict.split = function(self){
1404
var args = []
1405
for(var i=1;i<arguments.length;i++){args.push(arguments[i])}
1406
var $ns=$B.$MakeArgs("$StringDict.split",args,[],[],'args','kw')
1407
var sep=None,maxsplit=-1
1408
if($ns['args'].length>=1){sep=$ns['args'][0]}
1409
if($ns['args'].length==2){maxsplit=$ns['args'][1]}
1410
maxsplit = _b_.dict.$dict.get($ns['kw'],'maxsplit',maxsplit)
1411
if(sep=='') throw _b_.ValueError('empty seperator')
1412
if(sep===None){
1413
var res = []
1414
var pos = 0
1415
while(pos<self.length&&self.charAt(pos).search(/\s/)>-1){pos++}
1416
if(pos===self.length-1){return []}
1417
var name = ''
1418
while(1){
1419
if(self.charAt(pos).search(/\s/)===-1){
1420
if(name===''){name=self.charAt(pos)}
1421
else{name+=self.charAt(pos)}
1422
}else{
1423
if(name!==''){
1424
res.push(name)
1425
if(maxsplit!==-1&&res.length===maxsplit+1){
1426
res.pop()
1427
res.push(name+self.substr(pos))
1428
return res
1429
}
1430
name=''
1431
}
1432
}
1433
pos++
1434
if(pos>self.length-1){
1435
if(name){res.push(name)}
1436
break
1437
}
1438
}
1439
return res
1440
}else{
1441
//var escaped = ['*','.','[',']','(',')','|','$','^']
1442
var esc_sep = ''
1443
for(var i=0;i<sep.length;i++){
1444
switch(sep.charAt(i)) {
1445
case '*':
1446
case '.':
1447
case '[':
1448
case ']':
1449
case '(':
1450
case ')':
1451
case '|':
1452
case '$':
1453
case '^':
1454
//if(escaped.indexOf(sep.charAt(i))>-1){esc_sep += '\\'}
1455
esc_sep += '\\'
1456
}
1457
esc_sep += sep.charAt(i)
1458
}
1459
var re = new RegExp(esc_sep)
1460
if (maxsplit==-1){
1461
// use native Javascript split on self
1462
return self.valueOf().split(re,maxsplit)
1463
}
1464
1465
// javascript split behavior is different from python when
1466
// a maxsplit argument is supplied. (see javascript string split
1467
// function docs for details)
1468
var l=self.valueOf().split(re,-1)
1469
var a=l.splice(0, maxsplit)
1470
var b=l.splice(maxsplit-1, l.length)
1471
if (b.length > 0) a.push(b.join(sep))
1472
1473
return a
1474
}
1475
}
1476
1477
$StringDict.splitlines = function(self){return $StringDict.split(self,'\n')}
1478
1479
$StringDict.startswith = function(self){
1480
// Return True if string starts with the prefix, otherwise return False.
1481
// prefix can also be a tuple of prefixes to look for. With optional
1482
// start, test string beginning at that position. With optional end,
1483
// stop comparing string at that position.
1484
var $ns=$B.$MakeArgs("$StringDict.startswith",arguments,['self','prefix'],
1485
['start','end'],null,null)
1486
var prefixes = $ns['prefix']
1487
if(!isinstance(prefixes,_b_.tuple)){prefixes=[prefixes]}
1488
var start = $ns['start'] || 0
1489
var end = $ns['end'] || self.length-1
1490
var s = self.substr(start,end+1)
1491
1492
for (var i=0; i < prefixes.length; i++) {
1493
if (s.indexOf(prefixes[i]) == 0) return true
1494
}
1495
return false
1496
}
1497
1498
$StringDict.strip = function(self,x){
1499
if(x==undefined){x = "\\s"}
1500
return $StringDict.rstrip($StringDict.lstrip(self,x),x)
1501
}
1502
1503
$StringDict.swapcase = function(self) {
1504
//inspired by http://www.geekpedia.com/code69_Swap-string-case-using-JavaScript.html
1505
return self.replace(/([a-z])|([A-Z])/g, function($0,$1,$2)
1506
{ return ($1) ? $0.toUpperCase() : $0.toLowerCase()
1507
})
1508
}
1509
1510
$StringDict.title = function(self) {
1511
//inspired from http://stackoverflow.com/questions/196972/convert-string-to-title-case-with-javascript
1512
return self.replace(/\w\S*/g, function(txt){return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();});
1513
}
1514
1515
$StringDict.translate = function(self,table) {
1516
var res = ''
1517
if (isinstance(table, _b_.dict)) {
1518
for (var i=0; i<self.length; i++) {
1519
var repl = _b_.dict.$dict.get(table,self.charCodeAt(i),-1)
1520
if(repl==-1){res += self.charAt(i)}
1521
else if(repl!==None){res += repl}
1522
}
1523
}
1524
return res
1525
}
1526
1527
$StringDict.upper = function(self){return self.toUpperCase()}
1528
1529
$StringDict.zfill = function(self, width) {
1530
if (width === undefined || width <= self.length || !self.isnumeric()) {
1531
return self
1532
}
1533
1534
return Array(width - self.length +1).join('0');
1535
}
1536
1537
function str(arg){
1538
if(arg===undefined) return ''
1539
1540
try{ // try __str__
1541
var f = getattr(arg,'__str__')
1542
// XXX fix : if not better than object.__str__, try __repr__
1543
return f()
1544
}
1545
catch(err){
1546
$B.$pop_exc()
1547
try{ // try __repr__
1548
var f = getattr(arg,'__repr__')
1549
return f()
1550
}catch(err){
1551
$B.$pop_exc()
1552
console.log(err+'\ndefault to toString '+arg);return arg.toString()
1553
}
1554
}
1555
}
1556
str.__class__ = $B.$factory
1557
str.$dict = $StringDict
1558
$StringDict.$factory = str
1559
$StringDict.__new__ = function(cls){
1560
if(cls===undefined){
1561
throw _b_.TypeError('str.__new__(): not enough arguments')
1562
}
1563
return {__class__:cls.$dict}
1564
}
1565
1566
// dictionary and factory for subclasses of string
1567
var $StringSubclassDict = {
1568
__class__:$B.$type,
1569
__name__:'str'
1570
}
1571
1572
// the methods in subclass apply the methods in $StringDict to the
1573
// result of instance.valueOf(), which is a Javascript string
1574
for(var $attr in $StringDict){
1575
if(typeof $StringDict[$attr]=='function'){
1576
$StringSubclassDict[$attr]=(function(attr){
1577
return function(){
1578
var args = []
1579
if(arguments.length>0){
1580
var args = [arguments[0].valueOf()]
1581
for(var i=1;i<arguments.length;i++){
1582
args.push(arguments[i])
1583
}
1584
}
1585
return $StringDict[attr].apply(null,args)
1586
}
1587
})($attr)
1588
}
1589
}
1590
$StringSubclassDict.__mro__ = [$StringSubclassDict,$ObjectDict]
1591
1592
// factory for str subclasses
1593
$B.$StringSubclassFactory = {
1594
__class__:$B.$factory,
1595
$dict:$StringSubclassDict
1596
}
1597
1598
_b_.str = str
1599
1600
$B.$AttrDict = {__class__:$B.$type, __name__:'attribute'}
1601
1602
$B.$AttrDict.__getitem__ = function(self, arg){
1603
var _name=self.name
1604
if(_name.substr(0,2)=='$$') _name=_name.substr(2)
1605
1606
return _b_.getattr(_name, '__getitem__')(arg)
1607
}
1608
1609
1610
$B.$AttrDict.__mro__ = [$B.$AttrDict, $ObjectDict]
1611
1612
$B.$AttrDict.__repr__ = function(self){
1613
if(self.name.substr(0,2)=='$$') return _b_.repr(self.name.substr(2))
1614
return _b_.repr(self.name)
1615
}
1616
1617
$B.$AttrDict.__str__ = function(self){
1618
if(self.name.substr(0,2)=='$$') return _b_.str(self.name.substr(2))
1619
return _b_.str(self.name)
1620
}
1621
1622
for(var method in $StringDict){
1623
if($B.$AttrDict[method]!==undefined){continue}
1624
$B.$AttrDict[method] = (function(m){
1625
return function(){
1626
var args = []
1627
for(var i=0;i<arguments.length;i++){
1628
args.push(str(arguments[i]))
1629
}
1630
return $StringDict[m].apply(null, args)
1631
}
1632
})(method)
1633
}
1634
1635
})(__BRYTHON__)