Skip to content
Permalink
Newer
Older
100644 765 lines (649 sloc) 21.3 KB
Sep 5, 2014
1
;(function($B){
2
3
eval($B.InjectBuiltins())
5
var $ObjectDict = _b_.object.$dict,
6
str_hash = _b_.str.$dict.__hash__,
7
$N = _b_.None
Sep 5, 2014
8
9
// dictionary
10
function $DictClass($keys,$values){
11
this.iter = null
12
this.__class__ = $DictDict
Feb 9, 2015
14
15
var setitem=$DictDict.__setitem__
16
var i=$keys.length
17
while(i--) setitem($keys[i], $values[i])
Sep 5, 2014
20
var $DictDict = {__class__:$B.$type,
21
__name__ : 'dict',
22
$native:true,
23
__dir__:$ObjectDict.__dir__
Sep 5, 2014
24
}
25
26
var $key_iterator = function(d) {
27
this.d = d
28
this.current = 0
29
this.iter = new $item_generator(d)
30
}
31
$key_iterator.prototype.length = function() { return this.iter.length }
32
$key_iterator.prototype.next = function() { return this.iter.next()[0] }
33
34
var $value_iterator = function(d) {
35
this.d = d
36
this.current = 0
37
this.iter = new $item_generator(d)
38
}
39
$value_iterator.prototype.length = function() { return this.iter.length }
40
$value_iterator.prototype.next = function() { return this.iter.next()[1] }
41
42
var $item_generator = function(d) {
44
this.i = 0
46
if(d.$jsobj){
47
this.items = []
49
if(attr.charAt(0)!='$'){
50
val = d.$jsobj[attr];
51
if(val === undefined){val = _b_.NotImplemented}
52
else if(val === null){val = $N}
53
this.items.push([attr, val])
56
this.length=this.items.length;
57
return
58
}
60
var items=[]
63
items[pos++]=[parseFloat(k), d.$numeric_dict[k]]
66
for (var k in d.$string_dict) {items[pos++]=[k, d.$string_dict[k]]}
68
for (var k in d.$object_dict) {items[pos++] = d.$object_dict[k]}
69
70
this.items=items
71
this.length=items.length
Feb 9, 2015
73
74
$item_generator.prototype.next = function() {
75
if (this.i < this.items.length) {
76
return this.items[this.i++]
77
}
78
throw _b_.StopIteration("StopIteration")
79
}
80
$item_generator.prototype.as_list = function() {
81
return this.items
82
}
83
84
var $item_iterator = function(d) {
85
this.d = d
86
this.current = 0
87
this.iter = new $item_generator(d)
88
}
89
$item_iterator.prototype.length = function() {return this.iter.items.length }
90
$item_iterator.prototype.next = function() { return _b_.tuple(this.iter.next()) }
91
92
var $copy_dict = function(left, right) {
93
var _l=new $item_generator(right).as_list()
94
var si=$DictDict.__setitem__
95
var i=_l.length
96
while(i--) si(left, _l[i][0], _l[i][1])
99
function toSet(items){
100
// Build a set from the iteration on items
101
var res = []
102
while(true){
103
try{res.push(items.next())}
104
catch(err){break}
105
}
106
return _b_.set(res)
107
}
108
109
var $iterator_wrapper = function(items,klass){
110
var res = {
111
__class__:klass,
112
__eq__:function(other){
113
// compare set of items to other
114
return $B.rich_comp("__eq__", toSet(items), other)
116
__iter__:function(){items.iter.i=0; return res},
117
__len__:function(){return items.length()},
118
__next__:function(){
119
return items.next()
120
},
121
__repr__:function(){
122
var s = []
123
for(var i=0, len=items.length(); i<len; i++){
124
s.push(_b_.repr(items.next()))
125
}
126
return klass.__name__+'(['+ s.join(',') + '])'
127
},
128
}
129
res.__str__ = res.toString = res.__repr__
130
return res
131
}
132
133
$DictDict.__bool__ = function () {
Nov 21, 2015
134
var $=$B.args('__bool__',1,{self:null},['self'],arguments,{},null,null)
135
return $DictDict.__len__($.self) > 0
138
$DictDict.__contains__ = function(){
Nov 21, 2015
139
140
var $ = $B.args('__contains__', 2, {self:null, item:null},
141
['self', 'item'], arguments, {}, null, null),
142
self=$.self, item=$.item
Nov 21, 2015
143
Sep 5, 2014
144
if(self.$jsobj) return self.$jsobj[item]!==undefined
Nov 21, 2015
145
146
switch(typeof item) {
147
case 'string':
148
return self.$string_dict[item] !==undefined
149
case 'number':
150
return self.$numeric_dict[item] !==undefined
152
153
var _key=hash(item)
154
if (self.$str_hash[_key]!==undefined &&
155
$B.rich_comp("__eq__", item, self.$str_hash[_key])){return true}
156
if (self.$numeric_dict[_key]!==undefined &&
157
$B.rich_comp("__eq__", item, _key)){return true}
158
if (self.$object_dict[_key] !== undefined) {
Nov 21, 2015
159
// If the key is an object, its hash must be in the dict keys but the
160
// key itself must compare equal to the key associated with the hash
161
// For instance :
162
//
163
// class X:
164
// def __hash__(self): return hash('u')
165
//
Nov 21, 2015
166
// a = {'u': 'a', X(): 'b'}
167
// assert set(a.values())=={'a', 'b'}
168
// assert not X() in a
169
return $B.rich_comp("__eq__", item, self.$object_dict[_key][0])
170
}
171
return false
Sep 5, 2014
172
}
173
Nov 21, 2015
174
$DictDict.__delitem__ = function(){
175
176
var $ = $B.args('__eq__', 2, {self:null, arg:null},
177
['self', 'arg'], arguments, {}, null, null),
178
self=$.self, arg=$.arg
179
180
if(self.$jsobj){
181
if(self.$jsobj[arg]===undefined){throw KeyError(arg)}
182
delete self.$jsobj[arg]
185
switch(typeof arg) {
186
case 'string':
187
if (self.$string_dict[arg] === undefined) throw KeyError(_b_.str(arg))
188
delete self.$string_dict[arg]
189
delete self.$str_hash[str_hash(arg)]
191
case 'number':
192
if (self.$numeric_dict[arg] === undefined) throw KeyError(_b_.str(arg))
193
delete self.$numeric_dict[arg]
196
// go with defaults
198
var _key=hash(arg)
200
if (self.$object_dict[_key] !== undefined) {
Nov 21, 2015
201
delete self.$object_dict[_key]
203
204
if(self.$jsobj) delete self.$jsobj[arg]
Sep 5, 2014
206
}
207
Nov 21, 2015
208
$DictDict.__eq__ = function(){
209
var $ = $B.args('__eq__', 2, {self:null, other:null},
210
['self', 'other'], arguments, {}, null, null),
211
self=$.self, other=$.other
212
213
if(!isinstance(other,dict)) return false
215
if(self.$jsobj){self=jsobj2dict(self.$jsobj)}
216
if(other.$jsobj){other=jsobj2dict(other.$jsobj)}
218
if ($DictDict.__len__(self) != $DictDict.__len__(other)){return false}
Nov 21, 2015
220
if((self.$numeric_dict.length!=other.$numeric_dict.length) ||
221
(self.$string_dict.length!=other.$string_dict.length) ||
222
(self.$object_dict.length!=other.$object_dict.length)){
223
return false
Nov 21, 2015
225
for(var k in self.$numeric_dict){
226
if(!$B.rich_comp("__eq__", other.$numeric_dict[k], self.$numeric_dict[k])){
Nov 21, 2015
227
return false
228
}
229
}
230
for(var k in self.$string_dict){
231
if(!$B.rich_comp("__eq__", other.$string_dict[k], self.$string_dict[k])){
Nov 21, 2015
232
return false
233
}
234
}
235
for(var k in self.$object_dict){
236
if(!$B.rich_comp("__eq__", other.$object_dict[k][1], self.$object_dict[k][1])){
Nov 21, 2015
237
return false
238
}
239
}
Nov 21, 2015
242
Sep 5, 2014
243
}
244
Nov 21, 2015
245
$DictDict.__getitem__ = function(){
246
var $ = $B.args('__getitem__', 2, {self:null, arg:null},
247
['self', 'arg'], arguments, {}, null, null),
248
self=$.self, arg=$.arg
249
250
if(self.$jsobj){
251
if(!self.$jsobj.hasOwnProperty(arg)) throw _b_.KeyError(str(arg))
252
else if(self.$jsobj[arg]===undefined) return _b_.NotImplemented
253
else if(self.$jsobj[arg]===null){return $N}
254
return self.$jsobj[arg]
255
}
256
257
258
switch(typeof arg) {
259
case 'string':
260
if (self.$string_dict[arg] !== undefined) return self.$string_dict[arg]
261
break
262
case 'number':
263
if (self.$numeric_dict[arg] !== undefined) return self.$numeric_dict[arg]
266
// since the key is more complex use 'default' method of getting item
267
268
var _key = _b_.hash(arg),
269
_eq = function(other){return $B.rich_comp('__eq__', arg, other)}
271
var sk = self.$str_hash[_key]
272
if (sk!==undefined && _eq(sk)){
273
return self.$string_dict[sk]
274
}
275
if (self.$numeric_dict[_key]!==undefined && _eq(_key)){
276
return self.$numeric_dict[_key]
278
279
var obj_ref = self.$object_dict[_key]
280
if(obj_ref!==undefined){
281
// An object with the same hash is already stored
282
// Lookup should fail if equality raises an exception
283
_eq(self.$object_dict[_key][0])
Nov 21, 2015
284
return self.$object_dict[_key][1]
286
if(self.__class__!==$DictDict){
287
try{
288
var missing_method = getattr(self.__class__.$factory, '__missing__')
289
return missing_method(self, arg)
290
}catch(err){}
291
}
Sep 5, 2014
292
throw KeyError(_b_.str(arg))
293
}
294
295
$DictDict.__hash__ = None
Sep 5, 2014
296
297
$DictDict.__init__ = function(self){
298
var args = [], pos=0
299
for(var i=1;i<arguments.length;i++){args[pos++]=arguments[i]}
301
switch(args.length) {
302
case 0:
303
return
304
case 1:
Sep 5, 2014
305
var obj = args[0]
306
if(Array.isArray(obj)){
307
var i = obj.length
308
var si = $DictDict.__setitem__
309
while(i-->0) si(self, obj[i-1][0], obj[i-1][1])
311
}else if(obj.$nat===undefined && isinstance(obj,dict)){
Sep 5, 2014
314
}
Sep 5, 2014
316
if(obj.__class__===$B.JSObject.$dict){
317
// convert a JSObject into a Python dictionary
319
// Attribute $jsobj is used to update the original JS object
320
// when the dictionary is modified
Sep 5, 2014
323
}
326
var $ns=$B.args('dict',0,{},[],args,{},'args','kw')
Sep 5, 2014
327
var args = $ns['args']
328
var kw = $ns['kw']
Sep 5, 2014
331
if(isinstance(args[0],dict)){
Sep 5, 2014
334
}
Sep 5, 2014
336
// format dict([(k1,v1),(k2,v2)...])
338
if(Array.isArray(args[0])){
339
var src = args[0]
341
var si=$DictDict.__setitem__
342
while(i-->0) si(self, src[i-1][0], src[i-1][1])
344
var iterable = $B.$iter(args[0]),
345
ce = $B.current_exception
346
while(1){
347
try{
348
var elt = next(iterable)
349
var key = getattr(elt,'__getitem__')(0)
350
var value = getattr(elt,'__getitem__')(1)
351
$DictDict.__setitem__(self, key, value)
352
}catch(err){
353
if(err.__name__==='StopIteration'){
354
$B.current_exception = ce
355
break
356
}
Sep 5, 2014
359
}
360
}
362
if($DictDict.__len__(kw) > 0) $copy_dict(self, kw)
Sep 5, 2014
364
}
365
366
var $dict_iterator = $B.$iterator_class('dict iterator')
367
$DictDict.__iter__ = function(self) {
368
return $DictDict.keys(self)
Sep 5, 2014
369
}
370
371
$DictDict.__len__ = function(self) {
372
var _count=0
374
if(self.$jsobj){
375
for(var attr in self.$jsobj){if(attr.charAt(0)!='$'){_count++}}
376
return _count
377
}
379
for (var k in self.$numeric_dict) _count++
380
for (var k in self.$string_dict) _count++
381
for (var k in self.$object_dict) _count+= self.$object_dict[k].length
383
return _count
Sep 5, 2014
385
386
$DictDict.__mro__ = [$ObjectDict]
Sep 5, 2014
387
388
$DictDict.__ne__ = function(self,other){return !$DictDict.__eq__(self,other)}
389
390
$DictDict.__next__ = function(self){
392
self.$iter = new $item_generator(self)
393
}
394
try {
395
return self.$iter.next()
396
} catch (err) {
397
if (err.__name__ !== "StopIteration") { throw err }
Sep 5, 2014
398
}
399
}
400
401
$DictDict.__repr__ = function(self){
402
if(self===undefined) return "<class 'dict'>"
403
if(self.$jsobj){ // wrapper around Javascript object
404
return $DictDict.__repr__(jsobj2dict(self.$jsobj))
406
var res=[],
407
pos=0,
408
items = new $item_generator(self).as_list()
409
for (var i=0; i < items.length; i++) {
410
var itm = items[i]
411
if(itm[1]===self){res[pos++]=repr(itm[0])+': {...}'}
412
//else if(itm[1]===undefined){continue} // XXX this shouldn't happen
413
else{res[pos++]=repr(itm[0])+': '+repr(itm[1])}
Sep 5, 2014
414
}
415
return '{'+ res.join(', ') +'}'
Sep 5, 2014
416
}
417
418
$DictDict.__setitem__ = function(self,key,value){
Nov 21, 2015
420
var $ = $B.args('__setitem__', 3, {self:null, key:null, value:null},
421
['self', 'key', 'value'], arguments, {}, null, null),
422
self=$.self, key=$.key, value=$.value
423
425
self.$jsobj[key]=$B.pyobj2jsobj(value);
429
switch(typeof key) {
430
case 'string':
431
self.$string_dict[key]=value
432
self.$str_hash[str_hash(key)]=key
434
case 'number':
435
self.$numeric_dict[key]=value
439
// if we got here the key is more complex, use default method
441
var _key=hash(key)
442
var _eq=function(other){return $B.rich_comp("__eq__", key, other)};
444
if(self.$numeric_dict[_key]!==undefined && _eq(_key)){
445
self.$numeric_dict[_key] = value
447
}
448
var sk = self.$str_hash[_key]
449
if(sk!==undefined && _eq(sk)){
450
self.$string_dict[sk] = value
452
}
453
454
var obj_ref = self.$object_dict[_key]
455
if(obj_ref!==undefined){
456
// An object with the same hash is already stored
457
// Lookup should fail if equality raises an exception
458
_eq(self.$object_dict[_key][0])
459
}
460
self.$object_dict[_key] = [key, value]
Sep 5, 2014
462
}
463
464
$DictDict.__str__ = $DictDict.__repr__
465
466
// add "reflected" methods
467
$B.make_rmethods($DictDict)
468
469
$DictDict.clear = function(){
Sep 5, 2014
470
// Remove all items from the dictionary.
471
var $ = $B.args('clear',1,{self:null},['self'],arguments,{},null,null),
472
self = $.self
474
self.$numeric_dict={}
475
self.$string_dict={}
476
self.$str_hash={}
477
self.$object_dict={}
479
if(self.$jsobj){
480
for(var attr in self.$jsobj){
481
if(attr.charAt(0) !== '$' && attr !== "__class__"){
482
delete self.$jsobj[attr]
483
}
484
}
485
}
Sep 5, 2014
487
}
488
489
$DictDict.copy = function(self){
490
// Return a shallow copy of the dictionary
491
var $ = $B.args('copy',1,{self:null},['self'],arguments,{},null,null),
492
self = $.self,
493
res = _b_.dict()
Sep 5, 2014
495
return res
496
}
497
Nov 21, 2015
498
$DictDict.fromkeys = function(){
499
500
var $ = $B.args('fromkeys', 3, {cls:null, keys:null, value:null},
501
['cls', 'keys', 'value'], arguments, {value:_b_.None}, null, null),
Nov 21, 2015
502
keys=$.keys, value=$.value
Sep 5, 2014
504
// class method
505
var klass = $.cls,
506
res = klass(),
507
keys_iter = $B.$iter(keys),
508
ce = $B.current_exception
Sep 5, 2014
510
while(1){
511
try{
512
var key = _b_.next(keys_iter)
513
if(klass===dict){$DictDict.__setitem__(res, key, value)}
514
else{_b_.getattr(res, "__setitem__")(key,value)}
Sep 5, 2014
515
}catch(err){
516
if($B.is_exc(err,[_b_.StopIteration])){
Sep 5, 2014
518
return res
519
}
520
throw err
521
}
522
}
523
}
524
$DictDict.fromkeys.$type = 'classmethod'
Sep 5, 2014
525
Nov 21, 2015
526
$DictDict.get = function(){
527
var $ = $B.args('get', 3, {self:null, key:null, _default:null},
528
['self', 'key', '_default'], arguments, {_default:$N}, null, null)
530
try{return $DictDict.__getitem__($.self, $.key)}
531
catch(err){
532
if(_b_.isinstance(err, _b_.KeyError)){return $._default}
533
else{throw err}
534
}
535
}
536
537
var $dict_itemsDict = $B.$iterator_class('dict_items')
538
539
$DictDict.items = function(self){
540
if (arguments.length > 1) {
541
var _len=arguments.length - 1
542
var _msg="items() takes no arguments ("+_len+" given)"
543
throw _b_.TypeError(_msg)
544
}
545
return $iterator_wrapper(new $item_iterator(self), $dict_itemsDict)
546
}
547
Nov 21, 2015
548
var $dict_keysDict = $B.$iterator_class('dict_keys')
549
550
$DictDict.keys = function(self){
551
if (arguments.length > 1) {
552
var _len=arguments.length - 1
553
var _msg="keys() takes no arguments ("+_len+" given)"
554
throw _b_.TypeError(_msg)
555
}
556
return $iterator_wrapper(new $key_iterator(self),$dict_keysDict)
557
}
558
559
$DictDict.pop = function(){
560
561
var $ = $B.args('pop', 3, {self:null, key: null, _default:null},
562
['self', 'key', '_default'], arguments, {_default:$N}, null, null),
563
self=$.self, key=$.key, _default=$._default
564
Sep 5, 2014
565
try{
566
var res = $DictDict.__getitem__(self,key)
567
$DictDict.__delitem__(self,key)
568
return res
569
}catch(err){
570
if(err.__name__==='KeyError'){
571
if(_default!==undefined) return _default
572
throw err
573
}
574
throw err
575
}
576
}
577
578
$DictDict.popitem = function(self){
580
try{
581
var itm = new $item_iterator(self).next()
582
$DictDict.__delitem__(self,itm[0])
583
return _b_.tuple(itm)
584
}catch(err) {
585
if (err.__name__ == "StopIteration") {
587
throw KeyError("'popitem(): dictionary is empty'")
588
}
589
}
Sep 5, 2014
590
}
591
Nov 21, 2015
592
$DictDict.setdefault = function(){
593
594
var $ = $B.args('setdefault', 3, {self:null, key: null, _default:null},
595
['self', 'key', '_default'], arguments, {_default:$N}, null, null),
Nov 21, 2015
596
self=$.self, key=$.key, _default=$._default
597
Sep 5, 2014
598
try{return $DictDict.__getitem__(self,key)}
599
catch(err){
600
if(_default===undefined) _default=$N
Sep 5, 2014
601
$DictDict.__setitem__(self,key,_default)
602
return _default
603
}
604
}
605
606
$DictDict.update = function(self){
Nov 21, 2015
607
608
var $ = $B.args('update',1,{'self':null},['self'],arguments,{},'args','kw'),
609
self=$.self, args=$.args, kw=$.kw
610
611
if(args.length>0) {
612
var o=args[0]
613
if (isinstance(o,dict)){
614
$copy_dict(self, o)
615
} else if (hasattr(o, '__getitem__') && hasattr(o, 'keys')) {
616
var _keys=_b_.list(getattr(o, 'keys')())
617
var si=$DictDict.__setitem__
618
var i=_keys.length
619
while(i--) {
620
//for (var i=0; i < _keys.length; i++) {
621
var _value = getattr(o, '__getitem__')(_keys[i])
622
si(self, _keys[i], _value)
Sep 5, 2014
625
}
Sep 5, 2014
628
}
629
Nov 21, 2015
630
var $dict_valuesDict = $B.$iterator_class('dict_values')
631
632
$DictDict.values = function(self){
633
if (arguments.length > 1) {
634
var _len=arguments.length - 1
635
var _msg="values() takes no arguments ("+_len+" given)"
636
throw _b_.TypeError(_msg)
637
}
638
return $iterator_wrapper(new $value_iterator(self), $dict_valuesDict)
639
}
640
641
function dict(args, second){
643
var res = {__class__:$DictDict,
644
$numeric_dict : {},
645
$object_dict : {},
646
$string_dict : {},
647
$str_hash: {},
648
length: 0
649
}
651
if(args===undefined){return res}
653
if(second===undefined){
654
if(Array.isArray(args)){
655
// Form "dict([[key1, value1], [key2,value2], ...])"
656
var i = -1, stop = args.length-1
657
var si = $DictDict.__setitem__
658
while(i++<stop){
659
var item=args[i]
660
switch(typeof item[0]) {
661
case 'string':
662
res.$string_dict[item[0]]=item[1]
663
res.$str_hash[str_hash(item[0])]=item[0]
664
break;
665
case 'number':
666
res.$numeric_dict[item[0]]=item[1]
667
break
668
default:
669
si(res, item[0], item[1])
670
break
671
}
672
}
673
return res
674
}else if(args.$nat=='kw'){
675
// Form dict(k1=v1, k2=v2...)
676
var kw = args['kw']
677
for(var attr in kw){
678
switch(typeof attr) {
679
case 'string':
680
res.$string_dict[attr]=kw[attr]
681
res.$str_hash[str_hash(attr)]=attr
682
break;
683
case 'number':
684
res.$numeric_dict[attr]=kw[attr]
685
break
686
default:
687
si(res, attr, kw[attr])
688
break
689
}
Sep 5, 2014
695
// apply __init__ with arguments of dict()
696
var _args = [res], pos=1
697
for(var i=0, _len_i = arguments.length; i < _len_i;i++){_args[pos++]=arguments[i]}
698
$DictDict.__init__.apply(null,_args)
Sep 5, 2014
699
return res
700
}
Sep 5, 2014
702
dict.__class__ = $B.$factory
703
dict.$dict = $DictDict
704
$DictDict.$factory = dict
705
$DictDict.__new__ = $B.$__new__(dict)
706
707
_b_.dict = dict
709
$B.set_func_names($DictDict)
710
711
// following are used for faster access elsewhere
712
$B.$dict_iterator = function(d) { return new $item_generator(d) }
713
$B.$dict_length = $DictDict.__len__
714
$B.$dict_getitem = $DictDict.__getitem__
715
$B.$dict_get = $DictDict.get
716
$B.$dict_set = $DictDict.__setitem__
717
$B.$dict_contains = $DictDict.__contains__
718
$B.$dict_items = function(d) { return new $item_generator(d).as_list() }
719
$B.$copy_dict = $copy_dict // copy from right to left
720
$B.$dict_get_copy = $DictDict.copy // return a shallow copy
721
723
// Class for attribute __dict__ of classes
724
var mappingproxyDict = {
725
__class__ : $B.$type,
726
__name__ : "mappingproxy"
727
}
728
mappingproxyDict.__mro__ = [_b_.object.$dict]
729
730
mappingproxyDict.__setitem__ = function(){
731
throw _b_.TypeError("'mappingproxy' object does not support item assignment")
732
}
733
735
function mappingproxy(obj){
736
var res = obj_dict(obj)
737
res.__class__ = mappingproxyDict
738
return res
739
}
740
mappingproxy.__class__ = $B.$factory
741
mappingproxy.$dict = mappingproxyDict
742
mappingproxyDict.$factory = mappingproxy
743
$B.mappingproxy = mappingproxy
744
745
function jsobj2dict(x){
746
var d = dict()
747
for(var attr in x){
748
if(attr.charAt(0)!='$' && attr!=='__class__'){
749
d.$string_dict[attr] = x[attr]
750
d.length++
751
}
752
}
753
return d
754
}
755
$B.obj_dict = function(obj){
756
var klass = $B.get_class(obj)
757
if(klass !==undefined && klass.$native){
758
throw _b_.AttributeError(klass.__name__+
759
" has no attribute '__dict__'")}
760
var res = dict()
761
res.$jsobj = obj
762
return res
763
}
764
Sep 5, 2014
765
})(__BRYTHON__)