Skip to content
Permalink
Newer
Older
100644 1213 lines (1095 sloc) 35.8 KB
Sep 5, 2014
1
;(function($B){
2
3
/*
4
Implementation of Python dictionaries
5
6
We can't use Javascript's Map here, because the behaviour is not exactly the
7
same (eg with keys that are instances of classes with a __hash__ method...)
8
and because Map is much slower than regular Javascript objects.
9
10
A Python dictionary is implemented as a Javascript objects with these
11
attributes:
12
. $version: an integer with an initial value of 0, incremented at each
13
insertion
14
. $numeric_dict: for keys of type int
15
. $string_dict and $str_hash: for keys of type str
16
. $object_dict: for keys of other types
17
18
The value associated to a key in $numeric_dict and $string_dict is a pair
19
[value, rank] where "value" is the value associated with the key and "rank"
20
is the value of the dict attribute $version when the pair is inserted. This
21
is required to keep track of the insertion order, mandatory since Python 3.7.
22
23
For keys that are not str or int, their hash value is computed. Since several
24
keys with the same hash can be stored in a dictionary, $object_dict[hash] is a
25
list of [key, [value, rank]] lists.
26
*/
27
28
var bltns = $B.InjectBuiltins()
29
eval(bltns)
31
var str_hash = _b_.str.__hash__,
Sep 5, 2014
33
34
var set_ops = ["eq", "le", "lt", "ge", "gt",
35
"sub", "rsub", "and", "or", "xor"]
36
37
// methods to compare non set-like views
38
function is_sublist(t1, t2){
39
// Return true if all elements of t1 are in t2
40
for(var i = 0, ilen = t1.length; i < ilen; i++){
41
var x = t1[i],
42
flag = false
43
for(var j = 0, jlen = t2.length; j < jlen; j++){
44
if($B.rich_comp("__eq__", x, t2[j])){
45
t2.splice(j, 1)
46
flag = true
47
break
48
}
49
}
50
if(! flag){
51
return false
52
}
53
}
54
return true
55
}
56
57
dict_view_op = {
58
__eq__: function(t1, t2){
59
return t1.length == t2.length && is_sublist(t1, t2)
60
},
61
__ne__: function(t1, t2){
62
return ! dict_view_op.__eq__(t1, t2)
63
},
64
__lt__: function(t1, t2){
65
return t1.length < t2.length && is_sublist(t1, t2)
66
},
67
__gt__: function(t1, t2){
68
return dict_view_op.__lt__(t2, t1)
69
},
70
__le__: function(t1, t2){
71
return t1.length <= t2.length && is_sublist(t1, t2)
72
},
73
__ge__: function(t1, t2){
74
return dict_view_op.__le__(t2, t1)
75
},
76
__and__: function(t1, t2){
77
var items = []
78
for(var i = 0, ilen = t1.length; i < ilen; i++){
79
var x = t1[i]
80
flag = false
81
for(var j = 0, jlen = t2.length; j < jlen; j++){
82
if($B.rich_comp("__eq__", x, t2[j])){
83
t2.splice(j, 1)
84
items.push(x)
85
break
86
}
87
}
88
}
89
return items
90
},
91
__or__: function(t1, t2){
92
var items = t1
93
for(var j = 0, jlen = t2.length; j < jlen; j++){
94
var y = t2[j],
95
flag = false
96
for(var i = 0, ilen = t1.length; i < ilen; i++){
97
if($B.rich_comp("__eq__", y, t1[i])){
98
t2.splice(j, 1)
99
flag = true
100
break
101
}
102
}
103
if(! flag){
104
items.push(y)
105
}
106
}
107
return items
108
}
110
}
111
112
$B.make_view = function(name){
113
var klass = $B.make_class(name, function(items, set_like){
114
return {
115
__class__: klass,
117
counter: -1,
118
items: items,
119
len: items.length,
120
set_like: set_like
121
}
122
})
123
124
for(var i = 0, len = set_ops.length; i < len; i++){
125
var op = "__" + set_ops[i] + "__"
126
klass[op] = (function(op){
127
return function(self, other){
128
// compare set of items to other
129
if(self.set_like){
130
return _b_.set[op](_b_.set.$factory(self),
131
_b_.set.$factory(other))
132
}else{
133
// Non-set like views can only be compared to
134
// instances of the same class
135
if(other.__class__ !== klass){
136
return false
137
}
138
var other_items = _b_.list.$factory(other)
139
return dict_view_op[op](self.items, other_items)
140
}
141
}
142
})(op)
143
}
144
klass.__iter__ = function(self){
145
var it = klass.$iterator.$factory(self.items)
146
it.len_func = self.len_func
147
return it
148
}
149
150
klass.__len__ = function(self){
151
return self.len
152
}
154
klass.__repr__ = function(self){
155
return klass.$infos.__name__ + '(' + _b_.repr(self.items) + ')'
156
}
157
158
$B.set_func_names(klass, "builtins")
159
return klass
160
}
161
162
// Special version of __next__ for iterators on dict keys / values / items.
163
// Checks that the dictionary size didn't change during iteration.
164
function dict_iterator_next(self){
165
if(self.len_func() != self.len){
166
throw _b_.RuntimeError.$factory("dictionary changed size during iteration")
167
}
168
self.counter++
169
if(self.counter < self.items.length){
170
return self.items[self.counter]
171
}
172
throw _b_.StopIteration.$factory("StopIteration")
173
}
174
Feb 11, 2018
175
var dict = {
Feb 11, 2018
176
__class__: _b_.type,
178
$infos: {
179
__module__: "builtins",
180
__name__: "dict"
181
},
Feb 11, 2018
182
$is_class: true,
183
$native: true
Sep 5, 2014
184
}
185
186
dict.$to_obj = function(d){
187
// Function applied to dictionary that only have string keys,
188
// return a Javascript objects with the kays mapped to the value,
189
// excluding the insertion rank
190
var res = {}
191
for(var key in d.$string_dict){
192
res[key] = d.$string_dict[key][0]
193
}
194
return res
195
}
196
197
function to_list(d, ix){
198
var items = [],
199
item
201
if(d.$jsobj){
Mar 7, 2018
204
if(attr.charAt(0) != "$"){
205
var val = d.$jsobj[attr]
206
if(val === undefined){val = _b_.NotImplemented}
207
else if(val === null){val = $N}
211
}else{
212
for(var k in d.$numeric_dict){
213
items.push([parseFloat(k), d.$numeric_dict[k]])
214
}
216
for(var k in d.$string_dict){items.push([k, d.$string_dict[k]])}
218
for(var k in d.$object_dict){
219
d.$object_dict[k].forEach(function(item){
220
items.push(item)
221
})
222
}
223
// sort by insertion order
224
items.sort(function(a, b){
225
return a[1][1] - b[1][1]
226
})
227
items = items.map(function(item){return [item[0], item[1][0]]})
230
if(ix !== undefined){
231
return items.map(function(item){return item[ix]})
232
}else{
233
items.__class__ = _b_.tuple
234
return items.map(function(item){
235
item.__class__ = _b_.tuple; return item}
236
)
237
}
Feb 9, 2015
239
240
$B.dict_to_list = to_list // used in py_types.js
241
242
// Special version of __next__ for iterators on dict keys / values / items.
243
// Checks that the dictionary size didn't change during iteration.
244
function dict_iterator_next(self){
245
if(self.len_func() != self.len){
246
throw _b_.RuntimeError.$factory("dictionary changed size during iteration")
247
}
248
self.counter++
249
if(self.counter < self.items.length){
250
return self.items[self.counter]
252
throw _b_.StopIteration.$factory("StopIteration")
255
var $copy_dict = function(left, right){
257
si = dict.$setitem
258
right.$version = right.$version || 0
259
var right_version = right.$version || 0
260
for(var i = 0, len = _l.length; i < len; i++){
261
si(left, _l[i][0], _l[i][1])
262
if(right.$version != right_version){
263
throw _b_.RuntimeError.$factory("dict mutated during update")
264
}
265
}
268
function rank(self, hash, key){
269
// Search if object key, with hash = hash(key), is in
270
// self.$object_dict
271
var pairs = self.$object_dict[hash]
272
if(pairs !== undefined){
273
for(var i = 0, len = pairs.length; i < len; i++){
274
if($B.rich_comp("__eq__", key, pairs[i][0])){
275
return i
276
}
277
}
278
}
279
return -1
280
}
281
Feb 11, 2018
282
dict.__bool__ = function () {
Mar 7, 2018
283
var $ = $B.args("__bool__", 1, {self: null}, ["self"],
284
arguments, {}, null, null)
Feb 11, 2018
285
return dict.__len__($.self) > 0
Feb 11, 2018
288
dict.__contains__ = function(){
Nov 21, 2015
289
290
var $ = $B.args("__contains__", 2, {self: null, key: null},
291
["self", "key"], arguments, {}, null, null),
292
self = $.self,
294
if(self.$is_namespace){key = $B.to_alias(key)} // issue 1244
295
296
if(self.$jsobj){
297
return self.$jsobj[key] !== undefined
298
}
300
switch(typeof key) {
302
return self.$string_dict[key] !== undefined
304
return self.$numeric_dict[key] !== undefined
305
}
306
307
var hash = _b_.hash(key)
308
if(self.$str_hash[hash] !== undefined &&
309
$B.rich_comp("__eq__", key, self.$str_hash[hash])){return true}
310
if(self.$numeric_dict[hash] !== undefined &&
311
$B.rich_comp("__eq__", key, hash)){return true}
312
return rank(self, hash, key) > -1
Sep 5, 2014
313
}
314
Feb 11, 2018
315
dict.__delitem__ = function(){
Nov 21, 2015
316
317
var $ = $B.args("__eq__", 2, {self: null, arg: null},
318
["self", "arg"], arguments, {}, null, null),
319
self = $.self,
Nov 21, 2015
321
322
if(self.$jsobj){
323
if(self.$jsobj[arg] === undefined){throw _b_.KeyError.$factory(arg)}
324
delete self.$jsobj[arg]
327
switch(typeof arg){
328
case "string":
329
if(self.$string_dict[arg] === undefined){
330
throw _b_.KeyError.$factory(_b_.str.$factory(arg))
331
}
332
delete self.$string_dict[arg]
333
delete self.$str_hash[str_hash(arg)]
335
return $N
336
case "number":
337
if(self.$numeric_dict[arg] === undefined){
338
throw _b_.KeyError.$factory(_b_.str.$factory(arg))
340
delete self.$numeric_dict[arg]
344
// go with defaults
345
346
var hash = _b_.hash(arg),
347
ix
349
if((ix = rank(self, hash, arg)) > -1){
350
self.$object_dict[hash].splice(ix, 1)
351
}else{
352
throw _b_.KeyError.$factory(_b_.str.$factory(arg))
Sep 5, 2014
357
}
358
Feb 11, 2018
359
dict.__eq__ = function(){
Mar 7, 2018
360
var $ = $B.args("__eq__", 2, {self: null, other: null},
361
["self", "other"], arguments, {}, null, null),
362
self = $.self,
363
other = $.other
365
if(! _b_.isinstance(other, dict)){return false}
367
if(self.$jsobj){self = jsobj2dict(self.$jsobj)}
368
if(other.$jsobj){other = jsobj2dict(other.$jsobj)}
369
if(dict.__len__(self) != dict.__len__(other)){
370
return false
371
}
373
if(self.$string_dict.length != other.$string_dict.length){
377
for(var k in self.$numeric_dict){
378
if(other.$numeric_dict.hasOwnProperty(k)){
379
if(!$B.rich_comp("__eq__", other.$numeric_dict[k][0],
380
self.$numeric_dict[k][0])){
381
return false
382
}
383
}else if(other.$object_dict.hasOwnProperty(k)){
384
var pairs = other.$object_dict[k],
385
flag = false
386
for(var i = 0, len = pairs.length; i < len; i++){
387
if($B.rich_comp("__eq__", k, pairs[i][0]) &&
388
$B.rich_comp("__eq__", self.$numeric_dict[k],
389
pairs[i][1])){
390
flag = true
391
break
392
}
394
if(! flag){return false}
Nov 21, 2015
397
}
398
}
399
for(var k in self.$string_dict){
400
if(!other.$string_dict.hasOwnProperty(k) ||
401
!$B.rich_comp("__eq__", other.$string_dict[k][0],
402
self.$string_dict[k][0])){
Nov 21, 2015
404
}
405
}
406
for(var hash in self.$object_dict){
407
var pairs = self.$object_dict[hash]
408
// Get all (key, value) pairs in other that have the same hash
409
var other_pairs = []
410
if(other.$numeric_dict[hash] !== undefined){
411
other_pairs.push([hash, other.$numeric_dict[hash]])
412
}
413
if(other.$object_dict[hash] !== undefined){
414
other_pairs = other_pairs.concat(other.$object_dict[hash])
415
}
416
if(other_pairs.length == 0){
417
return false
418
}
419
for(var i = 0, len_i = pairs.length; i < len_i; i++){
420
var flag = false
421
var key = pairs[i][0],
422
value = pairs[i][1][0]
423
for(var j = 0, len_j = other_pairs.length; j < len_j; j++){
424
if($B.rich_comp("__eq__", key, other_pairs[j][0]) &&
425
$B.rich_comp("__eq__", value, other_pairs[j][1][0])){
426
flag = true
427
break
433
}
434
}
435
return true
Sep 5, 2014
436
}
437
Feb 11, 2018
438
dict.__getitem__ = function(){
439
var $ = $B.args("__getitem__", 2, {self: null, arg: null},
440
["self", "arg"], arguments, {}, null, null),
441
self = $.self,
443
return dict.$getitem(self, arg)
444
}
445
446
dict.$getitem = function(self, arg){
447
if(self.$jsobj){
448
if(self.$jsobj[arg] === undefined){
449
if(self.$jsobj.hasOwnProperty(arg)){
451
}
452
throw _b_.KeyError.$factory(arg)
453
}
454
return self.$jsobj[arg]
456
457
switch(typeof arg){
458
case "string":
459
if(self.$string_dict[arg] !== undefined){
460
return self.$string_dict[arg][0]
462
break
463
case "number":
464
if(self.$numeric_dict[arg] !== undefined){
465
return self.$numeric_dict[arg][0]
467
break
468
}
469
470
// since the key is more complex use 'default' method of getting item
471
472
var hash = _b_.hash(arg),
473
_eq = function(other){return $B.rich_comp("__eq__", arg, other)}
474
475
if(typeof arg == "object"){
476
arg.$hash = hash // cache for setdefault
477
}
478
var sk = self.$str_hash[hash]
479
if(sk !== undefined && _eq(sk)){
480
return self.$string_dict[sk][0]
482
if(self.$numeric_dict[hash] !== undefined && _eq(hash)){
483
return self.$numeric_dict[hash][0]
485
if(_b_.isinstance(arg, _b_.str)){
486
// string subclass
487
var res = self.$string_dict[arg.valueOf()]
488
if(res !== undefined){return res[0]}
491
var ix = rank(self, hash, arg)
492
if(ix > -1){
493
return self.$object_dict[hash][ix][1][0]
496
if(self.__class__ !== dict){
498
var missing_method = getattr(self.__class__, "__missing__",
499
_b_.None)
500
}catch(err){
501
console.log(err)
502
503
}
504
if(missing_method !== _b_.None){
505
return missing_method(self, arg)
508
throw _b_.KeyError.$factory(arg)
Sep 5, 2014
509
}
510
511
dict.__hash__ = _b_.None
Sep 5, 2014
512
513
function init_from_list(self, args){
514
var i = -1,
515
stop = args.length - 1,
516
si = dict.__setitem__
517
while(i++ < stop){
518
var item = args[i]
519
switch(typeof item[0]) {
520
case 'string':
521
self.$string_dict[item[0]] = [item[1], self.$order++]
522
self.$str_hash[str_hash(item[0])] = item[0]
523
self.$version++
524
break
525
case 'number':
526
if(item[0] != 0 && item[0] != 1){
527
self.$numeric_dict[item[0]] = [item[1], self.$order++]
528
self.$version++
529
break
530
}
531
default:
532
si(self, item[0], item[1])
533
break
534
}
535
}
536
}
537
538
dict.__init__ = function(self, first, second){
540
if(first === undefined){return $N}
541
if(second === undefined){
542
if(first.$nat != 'kw' && $B.get_class(first) === $B.JSObj){
543
for(var key in first){
544
self.$string_dict[key] = [first[key], self.$order++]
545
}
546
return _b_.None
547
}else if(first.$jsobj){
548
self.$jsobj = {}
549
for(var attr in first.$jsobj){
550
self.$jsobj[attr] = first.$jsobj[attr]
553
}else if(Array.isArray(first)){
554
init_from_list(self, first)
555
return $N
Sep 5, 2014
556
}
559
$ = $ || $B.args("dict", 1, {self:null}, ["self"],
560
arguments, {}, "first", "second")
561
var args = $.first
562
if(args.length > 1){
563
throw _b_.TypeError.$factory("dict expected at most 1 argument" +
564
", got 2")
565
}else if(args.length == 1){
566
args = args[0]
567
if(args.__class__ === dict){
568
['$string_dict', '$str_hash', '$numeric_dict', '$object_dict'].
569
forEach(function(d){
570
for(key in args[d]){self[d][key] = args[d][key]}
571
})
572
}else if(_b_.isinstance(args, dict)){
575
var keys = $B.$getattr(args, "keys", null)
576
if(keys !== null){
577
var gi = $B.$getattr(args, "__getitem__", null)
578
if(gi !== null){
579
// has keys and __getitem__ : it's a mapping, iterate on
580
// keys and values
581
gi = $B.$call(gi)
582
var kiter = _b_.iter($B.$call(keys)())
583
while(true){
584
try{
585
var key = _b_.next(kiter),
586
value = gi(key)
587
dict.__setitem__(self, key, value)
588
}catch(err){
589
if(err.__class__ === _b_.StopIteration){
590
break
591
}
592
throw err
593
}
594
}
595
return $N
596
}
597
}
598
if(! Array.isArray(args)){
599
args = _b_.list.$factory(args)
600
}
601
// Form "dict([[key1, value1], [key2,value2], ...])"
602
init_from_list(self, args)
Sep 5, 2014
603
}
605
var kw = $.second.$string_dict
606
for(var attr in kw){
607
switch(typeof attr){
608
case "string":
609
self.$string_dict[attr] = [kw[attr][0], self.$order++]
610
self.$str_hash[str_hash(attr)] = attr
611
break
612
case "number":
613
self.$numeric_dict[attr] = [kw[attr][0], self.$order++]
616
si(self, attr, kw[attr][0])
Sep 5, 2014
621
}
622
Feb 11, 2018
623
dict.__iter__ = function(self) {
624
return _b_.iter(dict.$$keys(self))
Sep 5, 2014
625
}
626
627
dict.__ior__ = function(self, other){
628
// PEP 584
629
dict.update(self, other)
630
return self
631
}
632
Feb 11, 2018
633
dict.__len__ = function(self) {
636
if(self.$jsobj){
Mar 7, 2018
637
for(var attr in self.$jsobj){if(attr.charAt(0) != "$"){_count++}}
638
return _count
639
}
641
for(var k in self.$numeric_dict){_count++}
642
for(var k in self.$string_dict){_count++}
643
for(var hash in self.$object_dict){
644
_count += self.$object_dict[hash].length
645
}
Sep 5, 2014
649
Mar 7, 2018
650
dict.__ne__ = function(self, other){return ! dict.__eq__(self, other)}
Sep 5, 2014
651
Feb 11, 2018
652
dict.__new__ = function(cls){
653
if(cls === undefined){
Mar 7, 2018
654
throw _b_.TypeError.$factory("int.__new__(): not enough arguments")
656
var instance = {
658
$numeric_dict : {},
659
$object_dict : {},
662
$version: 0,
663
$order: 0
665
if(cls !== dict){
666
instance.__dict__ = $B.empty_dict()
667
}
668
return instance
671
dict.__or__ = function(self, other){
672
// PEP 584
673
if(! _b_.isinstance(other, dict)){
674
return _b_.NotImplemented
675
}
676
var res = dict.copy(self)
677
dict.update(res, other)
678
return res
679
}
680
Feb 11, 2018
681
dict.__repr__ = function(self){
682
if(self.$jsobj){ // wrapper around Javascript object
Feb 11, 2018
683
return dict.__repr__(jsobj2dict(self.$jsobj))
685
if($B.repr.enter(self)){
686
return "{...}"
687
}
688
var res = [],
690
items.forEach(function(item){
691
try{
692
res.push(repr(item[0]) + ": " + repr(item[1]))
693
}catch(err){
694
throw err
695
}
697
$B.repr.leave(self)
Mar 7, 2018
698
return "{" + res.join(", ") + "}"
Sep 5, 2014
699
}
700
701
dict.__ror__ = function(self, other){
702
// PEP 584
703
if(! _b_.isinstance(other, dict)){
704
return _b_.NotImplemented
705
}
706
var res = dict.copy(other)
707
dict.update(res, self)
708
return res
709
}
710
711
dict.__setitem__ = function(self, key, value){
Mar 7, 2018
712
var $ = $B.args("__setitem__", 3, {self: null, key: null, value: null},
713
["self", "key", "value"], arguments, {}, null, null)
714
return dict.$setitem($.self, $.key, $.value)
715
}
Nov 21, 2015
716
717
dict.$setitem = function(self, key, value, $hash){
718
// Set a dictionary item mapping key and value.
719
//
720
// If key is a string, set:
721
// - $string_dict[key] = [value, order] where "order" is an auto-increment
722
// unique id to keep track of insertion order
723
// - $str_hash[hash(key)] to key
724
//
725
// If key is a number, set $numeric_dict[key] = value
726
//
727
// If key is another object, compute its hash value:
728
// - if the hash is a key of $str_hash, and key == $str_hash[hash],
729
// replace $string_dict[$str_hash[hash]] by value
730
// - if the hash is a key of $numeric_dict, and hash == key, replace
731
// $numeric_dict[hash] by value
732
// - if the hash is a key of $object_dict: $object_dict[hash] is a list
733
// of [k, v] pairs. If key is equal to one of the "k", replace the
734
// matching v by value. Otherwise, add [key, value] to the list
735
// - else set $object_dict[hash] = [[key, value]]
736
//
737
// In all cases, increment attribute $version, used to detect dictionary
738
// changes during an iteration.
740
// Parameter $hash is only set if this method is called by setdefault.
741
// In this case the hash of key has already been computed and we
742
// know that the key is not present in the dictionary, so it's no
743
// use computing hash(key) again, nor testing equality of keys
745
if(self.$from_js){
746
// dictionary created by method to_dict of JSObj instances
747
value = $B.pyobj2jsobj(value)
748
}
749
if(self.$jsobj.__class__ === _b_.type){
750
self.$jsobj[key] = value
751
if(key == "__init__" || key == "__new__"){
752
// If class attribute __init__ or __new__ are reset,
753
// the factory function has to change
754
self.$jsobj.$factory = $B.$instance_creator(self.$jsobj)
755
}
756
}else{
757
self.$jsobj[key] = value
762
switch(typeof key){
763
case "string":
764
if(self.$string_dict === undefined){
765
console.log("pas de string dict", self, key, value)
766
}
767
if(self.$string_dict[key] !== undefined){
768
self.$string_dict[key][0] = value
769
}else{
770
self.$string_dict[key] = [value, self.$order++]
771
self.$str_hash[str_hash(key)] = key
772
self.$version++
773
}
774
return $N
775
case "number":
776
if(self.$numeric_dict[key] !== undefined){
777
// existing key: preserve order
778
self.$numeric_dict[key][0] = value
779
}else{
780
// special case for 0 and 1 if True or False are keys
781
var done = false
782
if((key == 0 || key == 1) &&
783
self.$object_dict[key] !== undefined){
784
for(const item of self.$object_dict[key]){
785
if((key == 0 && item[0] === false) ||
786
(key == 1 && item[0] === true)){
787
// replace value
788
item[1][0] = value
789
done = true
790
}
791
}
792
}
793
if(! done){
794
// new key
795
self.$numeric_dict[key] = [value, self.$order++]
796
}
799
return $N
800
case "boolean":
801
// true replaces 1 and false replaces 0
802
var num = key ? 1 : 0
803
if(self.$numeric_dict[num] !== undefined){
804
var order = self.$numeric_dict[num][1] // preserve order
805
self.$numeric_dict[num] = [value, order]
806
return
807
}
808
if(self.$object_dict[num] !== undefined){
809
self.$object_dict[num].push([key, [value, self.$order++]])
810
}else{
811
self.$object_dict[num] = [[key, [value, self.$order++]]]
812
}
815
// if we got here the key is more complex, use default method
816
817
var hash = $hash === undefined ? _b_.hash(key) : $hash,
818
_eq = function(other){return $B.rich_comp("__eq__", key, other)}
819
820
if(self.$numeric_dict[hash] !== undefined && _eq(hash)){
821
self.$numeric_dict[hash] = [value, self.$numeric_dict[hash][1]]
825
var sk = self.$str_hash[hash]
826
if(sk !== undefined && _eq(sk)){
827
self.$string_dict[sk] = [value, self.$string_dict[sk][1]]
832
// If $setitem is called from setdefault, don't test equality of key
833
// with any object
834
if($hash){
835
if(self.$object_dict[$hash] !== undefined){
836
self.$object_dict[$hash].push([key, [value, self.$order++]])
838
self.$object_dict[$hash] = [[key, [value, self.$order++]]]
839
}
840
self.$version++
841
return $N
842
}
843
var ix = rank(self, hash, key)
844
if(ix > -1){
845
// reset value
846
self.$object_dict[hash][ix][1] = [value,
847
self.$object_dict[hash][ix][1][1]]
848
return $N
849
}else if(self.$object_dict.hasOwnProperty(hash)){
850
self.$object_dict[hash].push([key, [value, self.$order++]])
852
self.$object_dict[hash] = [[key, [value, self.$order++]]]
Sep 5, 2014
856
}
857
858
dict.__str__ = function(){
859
return dict.__repr__.apply(null, arguments)
860
}
Sep 5, 2014
861
862
// add "reflected" methods
Feb 11, 2018
863
$B.make_rmethods(dict)
Sep 5, 2014
864
Feb 11, 2018
865
dict.clear = function(){
Sep 5, 2014
866
// Remove all items from the dictionary.
Mar 7, 2018
867
var $ = $B.args("clear", 1, {self: null}, ["self"], arguments, {},
868
null, null),
869
self = $.self
871
self.$numeric_dict = {}
872
self.$string_dict = {}
873
self.$str_hash = {}
874
self.$object_dict = {}
876
if(self.$jsobj){
877
for(var attr in self.$jsobj){
Mar 7, 2018
878
if(attr.charAt(0) !== "$" && attr !== "__class__"){
879
delete self.$jsobj[attr]
880
}
881
}
882
}
Sep 5, 2014
886
}
887
Feb 11, 2018
888
dict.copy = function(self){
Sep 5, 2014
889
// Return a shallow copy of the dictionary
Mar 7, 2018
890
var $ = $B.args("copy", 1, {self: null},["self"], arguments,{},
891
null, null),
892
self = $.self,
Sep 5, 2014
895
return res
896
}
897
Feb 11, 2018
898
dict.fromkeys = function(){
Nov 21, 2015
899
Mar 7, 2018
900
var $ = $B.args("fromkeys", 3, {cls: null, keys: null, value: null},
901
["cls", "keys", "value"], arguments, {value: _b_.None}, null, null),
902
keys = $.keys,
903
value = $.value
Sep 5, 2014
905
// class method
906
var klass = $.cls,
Sep 5, 2014
910
while(1){
911
try{
912
var key = _b_.next(keys_iter)
913
if(klass === dict){dict.$setitem(res, key, value)}
914
else{$B.$getattr(res, "__setitem__")(key, value)}
Sep 5, 2014
915
}catch(err){
916
if($B.is_exc(err, [_b_.StopIteration])){
Sep 5, 2014
917
return res
918
}
919
throw err
920
}
921
}
922
}
923
Feb 11, 2018
924
dict.get = function(){
Mar 7, 2018
925
var $ = $B.args("get", 3, {self: null, key: null, _default: null},
926
["self", "key", "_default"], arguments, {_default: $N}, null, null)
Feb 11, 2018
928
try{return dict.__getitem__($.self, $.key)}
929
catch(err){
930
if(_b_.isinstance(err, _b_.KeyError)){return $._default}
931
else{throw err}
932
}
933
}
934
935
var dict_items = $B.make_view("dict_items", true)
936
dict_items.$iterator = $B.make_iterator_class("dict_itemiterator")
937
Feb 11, 2018
938
dict.items = function(self){
Mar 23, 2018
939
if(arguments.length > 1){
940
var _len = arguments.length - 1,
941
_msg = "items() takes no arguments (" + _len + " given)"
942
throw _b_.TypeError.$factory(_msg)
943
}
944
var items = to_list(self),
945
set_like = true
946
// Check if all values are hashable
947
for(var i = 0, len = items.length; i < len; i++){
948
try{
949
_b_.hash(items[i][1])
950
}catch(err){
951
set_like = false
952
break
953
}
954
}
955
var it = dict_items.$factory(to_list(self), set_like)
956
it.len_func = function(){return dict.__len__(self)}
957
return it
958
}
959
960
var dict_keys = $B.make_view("dict_keys")
961
dict_keys.$iterator = $B.make_iterator_class("dict_keyiterator")
Nov 21, 2015
962
Mar 23, 2018
964
if(arguments.length > 1){
965
var _len = arguments.length - 1,
966
_msg = "keys() takes no arguments (" + _len + " given)"
967
throw _b_.TypeError.$factory(_msg)
Nov 21, 2015
968
}
969
var it = dict_keys.$factory(to_list(self, 0), true)
970
it.len_func = function(){return dict.__len__(self)}
971
return it
Nov 21, 2015
972
}
973
Feb 11, 2018
974
dict.pop = function(){
Nov 21, 2015
975
976
var missing = {},
977
$ = $B.args("pop", 3, {self: null, key: null, _default: null},
978
["self", "key", "_default"], arguments, {_default: missing}, null, null),
979
self = $.self,
980
key = $.key,
981
_default = $._default
Nov 21, 2015
982
Sep 5, 2014
983
try{
984
var res = dict.__getitem__(self, key)
985
dict.__delitem__(self, key)
Sep 5, 2014
986
return res
987
}catch(err){
988
if(err.__class__ === _b_.KeyError){
989
if(_default !== missing){return _default}
Sep 5, 2014
990
throw err
991
}
992
throw err
993
}
994
}
995
Feb 11, 2018
996
dict.popitem = function(self){
998
var itm = _b_.next(_b_.iter(dict.items(self)))
999
dict.__delitem__(self, itm[0])
Feb 11, 2018
1000
return _b_.tuple.$factory(itm)
1002
if (err.__class__ == _b_.StopIteration) {
1003
throw _b_.KeyError.$factory("'popitem(): dictionary is empty'")
Sep 5, 2014
1006
}
1007
Feb 11, 2018
1008
dict.setdefault = function(){
Nov 21, 2015
1009
Mar 7, 2018
1010
var $ = $B.args("setdefault", 3, {self: null, key: null, _default: null},
1011
["self", "key", "_default"], arguments, {_default: $N}, null, null),
1012
self = $.self,
1013
key = $.key,
1014
_default = $._default
Nov 21, 2015
1015
1016
try{return dict.__getitem__(self, key)}
Sep 5, 2014
1017
catch(err){
1018
if(err.__class__ !== _b_.KeyError){
1019
throw err
1020
}
1021
if(_default === undefined){_default = $N}
1022
var hash = key.$hash
1023
key.$hash = undefined
1024
dict.$setitem(self, key, _default, hash)
Sep 5, 2014
1025
return _default
1026
}
1027
}
1028
Feb 11, 2018
1029
dict.update = function(self){
Nov 21, 2015
1030
Mar 7, 2018
1031
var $ = $B.args("update", 1, {"self": null}, ["self"], arguments,
1032
{}, "args", "kw"),
1033
self = $.self,
1034
args = $.args,
1035
kw = $.kw
1036
if(args.length > 0){
1037
var o = args[0]
1039
if(o.$jsobj){
1040
o = jsobj2dict(o.$jsobj)
1041
}
1043
}else if(_b_.hasattr(o, "keys")){
1044
var _keys = _b_.list.$factory($B.$call($B.$getattr(o, "keys"))())
1045
for(var i = 0, len = _keys.length; i < len; i++){
1046
var _value = getattr(o, "__getitem__")(_keys[i])
1047
dict.$setitem(self, _keys[i], _value)
1048
}
1049
}else{
1050
var it = _b_.iter(o),
1051
i = 0
1052
while(true){
1053
try{
1054
var item = _b_.next(it)
1055
}catch(err){
1056
if(err.__class__ === _b_.StopIteration){break}
1057
throw err
1058
}
1059
try{
1060
key_value = _b_.list.$factory(item)
1061
}catch(err){
1062
throw _b_.TypeError.$factory("cannot convert dictionary" +
1063
" update sequence element #" + i + " to a sequence")
1064
}
1065
if(key_value.length !== 2){
1066
throw _b_.ValueError.$factory("dictionary update " +
1067
"sequence element #" + i + " has length " +
1068
key_value.length + "; 2 is required")
1069
}
1070
dict.$setitem(self, key_value[0], key_value[1])
1071
i++
Sep 5, 2014
1074
}
Sep 5, 2014
1078
}
1079
1080
var dict_values = $B.make_view("dict_values")
1081
dict_values.$iterator = $B.make_iterator_class("dict_valueiterator")
Nov 21, 2015
1082
Feb 11, 2018
1083
dict.values = function(self){
Mar 23, 2018
1084
if(arguments.length > 1){
1085
var _len = arguments.length - 1,
1086
_msg = "values() takes no arguments (" + _len + " given)"
1087
throw _b_.TypeError.$factory(_msg)
Nov 21, 2015
1088
}
1089
var values = to_list(self, 1)
1090
var it = dict_values.$factory(to_list(self, 1), false)
1091
it.len_func = function(){return dict.__len__(self)}
1092
return it
Nov 21, 2015
1093
}
1094
1095
dict.$factory = function(){
1096
var res = dict.__new__(dict)
1097
var args = [res]
1098
for(var i = 0, len = arguments.length; i < len ; i++){
1099
args.push(arguments[i])
1100
}
1101
dict.__init__.apply(null, args)
Sep 5, 2014
1102
return res
1103
}
Sep 5, 2014
1105
_b_.dict = dict
Feb 11, 2018
1107
$B.set_func_names(dict, "builtins")
1108
1109
$B.empty_dict = function(){
1110
return {
1111
__class__: dict,
1112
$numeric_dict : {},
1113
$object_dict : {},
1114
$string_dict : {},
1115
$str_hash: {},
1116
$version: 0,
1117
$order: 0
1121
// This must be done after set_func_names, otherwise dict.fromkeys doesn't
1122
// have the attribute $infos
1123
dict.fromkeys = _b_.classmethod.$factory(dict.fromkeys)
1124
1125
$B.getset_descriptor = $B.make_class("getset_descriptor",
1126
function(klass, attr){
1127
return {
1128
__class__: $B.getset_descriptor,
1129
__doc__: _b_.None,
1130
cls: klass,
1131
attr: attr
1132
}
1133
}
1134
)
1135
1136
$B.getset_descriptor.__repr__ = $B.getset_descriptor.__str__ = function(self){
1137
return `<attribute '${self.attr}' of '${self.cls.$infos.__name__}' objects>`
1138
}
1139
1140
$B.set_func_names($B.getset_descriptor, "builtins")
1141
1142
// Class for attribute __dict__ of classes
1143
var mappingproxy = $B.mappingproxy = $B.make_class("mappingproxy",
Feb 12, 2018
1144
function(obj){
1145
if(_b_.isinstance(obj, dict)){
1146
// obj is a dictionary, with $string_dict table such that
1147
// obj.$string_dict[key] = [value, rank]
1148
// Transform it into an object with attribute $jsobj such that
1149
// res.$jsobj[key] = value
1150
var res = $B.obj_dict(dict.$to_obj(obj))
1151
}else{
1152
var res = $B.obj_dict(obj)
1153
}
Feb 12, 2018
1154
res.__class__ = mappingproxy
1155
return res
1156
}
1157
)
Feb 12, 2018
1159
mappingproxy.__setitem__ = function(){
Mar 7, 2018
1160
throw _b_.TypeError.$factory("'mappingproxy' object does not support " +
1161
"item assignment")
1164
for(var attr in dict){
1165
if(mappingproxy[attr] !== undefined ||
1166
["__class__", "__mro__", "__new__", "__init__", "__delitem__",
1167
"clear", "fromkeys", "pop", "popitem", "setdefault",
1168
"update"].indexOf(attr) > -1){
1169
continue
1170
}
1171
if(typeof dict[attr] == "function"){
1172
mappingproxy[attr] = (function(key){
1173
return function(){
1174
return dict[key].apply(null, arguments)
1175
}
1176
})(attr)
1177
}else{
1178
mappingproxy[attr] = dict[attr]
1179
}
1180
}
1181
Feb 12, 2018
1182
$B.set_func_names(mappingproxy, "builtins")
Mar 7, 2018
1187
if(attr.charAt(0) != "$" && attr !== "__class__"){
1188
if(x[attr] === null){
1189
d.$string_dict[attr] = [_b_.None, d.$order++]
1190
}else if(x[attr] === undefined){
1191
continue
1192
}else if(x[attr].$jsobj === x){
1193
d.$string_dict[attr] = [d, d.$order++]
1195
d.$string_dict[attr] = [$B.$JS2Py(x[attr]), d.$order++]
1197
}
1198
}
1199
return d
1200
}
1202
$B.obj_dict = function(obj, from_js){
1203
var klass = obj.__class__ || $B.get_class(obj)
1204
if(klass !== undefined && klass.$native){
1205
throw _b_.AttributeError.$factory(klass.__name__ +
1206
" has no attribute '__dict__'")}
1208
res.$jsobj = obj
1209
res.$from_js = from_js // set to true if
1210
return res
1211
}
1212
Sep 5, 2014
1213
})(__BRYTHON__)