Skip to content
Permalink
Newer
Older
100644 1212 lines (1095 sloc) 35.9 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 if(_b_.isinstance(d, _b_.dict)){
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]]})
229
if(ix !== undefined){
230
return items.map(function(item){return item[ix]})
231
}else{
232
items.__class__ = _b_.tuple
233
return items.map(function(item){
234
item.__class__ = _b_.tuple; return item}
235
)
236
}
Feb 9, 2015
238
239
$B.dict_to_list = to_list // used in py_types.js
240
241
// Special version of __next__ for iterators on dict keys / values / items.
242
// Checks that the dictionary size didn't change during iteration.
243
function dict_iterator_next(self){
244
if(self.len_func() != self.len){
245
throw _b_.RuntimeError.$factory("dictionary changed size during iteration")
246
}
247
self.counter++
248
if(self.counter < self.items.length){
249
return self.items[self.counter]
251
throw _b_.StopIteration.$factory("StopIteration")
254
var $copy_dict = function(left, right){
256
si = dict.$setitem
257
right.$version = right.$version || 0
258
var right_version = right.$version || 0
259
for(var i = 0, len = _l.length; i < len; i++){
260
si(left, _l[i][0], _l[i][1])
261
if(right.$version != right_version){
262
throw _b_.RuntimeError.$factory("dict mutated during update")
263
}
264
}
267
function rank(self, hash, key){
268
// Search if object key, with hash = hash(key), is in
269
// self.$object_dict
270
var pairs = self.$object_dict[hash]
271
if(pairs !== undefined){
272
for(var i = 0, len = pairs.length; i < len; i++){
273
if($B.rich_comp("__eq__", key, pairs[i][0])){
274
return i
275
}
276
}
277
}
278
return -1
279
}
280
Feb 11, 2018
281
dict.__bool__ = function () {
Mar 7, 2018
282
var $ = $B.args("__bool__", 1, {self: null}, ["self"],
283
arguments, {}, null, null)
Feb 11, 2018
284
return dict.__len__($.self) > 0
Feb 11, 2018
287
dict.__contains__ = function(){
Nov 21, 2015
288
289
var $ = $B.args("__contains__", 2, {self: null, key: null},
290
["self", "key"], arguments, {}, null, null),
291
self = $.self,
293
if(self.$is_namespace){key = $B.to_alias(key)} // issue 1244
294
295
if(self.$jsobj){
296
return self.$jsobj[key] !== undefined
297
}
299
switch(typeof key) {
301
return self.$string_dict[key] !== undefined
303
return self.$numeric_dict[key] !== undefined
304
}
305
306
var hash = _b_.hash(key)
307
if(self.$str_hash[hash] !== undefined &&
308
$B.rich_comp("__eq__", key, self.$str_hash[hash])){return true}
309
if(self.$numeric_dict[hash] !== undefined &&
310
$B.rich_comp("__eq__", key, hash)){return true}
311
return rank(self, hash, key) > -1
Sep 5, 2014
312
}
313
Feb 11, 2018
314
dict.__delitem__ = function(){
Nov 21, 2015
315
316
var $ = $B.args("__eq__", 2, {self: null, arg: null},
317
["self", "arg"], arguments, {}, null, null),
318
self = $.self,
Nov 21, 2015
320
321
if(self.$jsobj){
322
if(self.$jsobj[arg] === undefined){throw _b_.KeyError.$factory(arg)}
323
delete self.$jsobj[arg]
326
switch(typeof arg){
327
case "string":
328
if(self.$string_dict[arg] === undefined){
329
throw _b_.KeyError.$factory(_b_.str.$factory(arg))
330
}
331
delete self.$string_dict[arg]
332
delete self.$str_hash[str_hash(arg)]
334
return $N
335
case "number":
336
if(self.$numeric_dict[arg] === undefined){
337
throw _b_.KeyError.$factory(_b_.str.$factory(arg))
339
delete self.$numeric_dict[arg]
343
// go with defaults
344
345
var hash = _b_.hash(arg),
346
ix
348
if((ix = rank(self, hash, arg)) > -1){
349
self.$object_dict[hash].splice(ix, 1)
350
}else{
351
throw _b_.KeyError.$factory(_b_.str.$factory(arg))
Sep 5, 2014
356
}
357
Feb 11, 2018
358
dict.__eq__ = function(){
Mar 7, 2018
359
var $ = $B.args("__eq__", 2, {self: null, other: null},
360
["self", "other"], arguments, {}, null, null),
361
self = $.self,
362
other = $.other
364
if(! _b_.isinstance(other, dict)){return false}
366
if(self.$jsobj){self = jsobj2dict(self.$jsobj)}
367
if(other.$jsobj){other = jsobj2dict(other.$jsobj)}
368
if(dict.__len__(self) != dict.__len__(other)){
369
return false
370
}
372
if(self.$string_dict.length != other.$string_dict.length){
376
for(var k in self.$numeric_dict){
377
if(other.$numeric_dict.hasOwnProperty(k)){
378
if(!$B.rich_comp("__eq__", other.$numeric_dict[k][0],
379
self.$numeric_dict[k][0])){
380
return false
381
}
382
}else if(other.$object_dict.hasOwnProperty(k)){
383
var pairs = other.$object_dict[k],
384
flag = false
385
for(var i = 0, len = pairs.length; i < len; i++){
386
if($B.rich_comp("__eq__", k, pairs[i][0]) &&
387
$B.rich_comp("__eq__", self.$numeric_dict[k],
388
pairs[i][1])){
389
flag = true
390
break
391
}
393
if(! flag){return false}
Nov 21, 2015
396
}
397
}
398
for(var k in self.$string_dict){
399
if(!other.$string_dict.hasOwnProperty(k) ||
400
!$B.rich_comp("__eq__", other.$string_dict[k][0],
401
self.$string_dict[k][0])){
Nov 21, 2015
403
}
404
}
405
for(var hash in self.$object_dict){
406
var pairs = self.$object_dict[hash]
407
// Get all (key, value) pairs in other that have the same hash
408
var other_pairs = []
409
if(other.$numeric_dict[hash] !== undefined){
410
other_pairs.push([hash, other.$numeric_dict[hash]])
411
}
412
if(other.$object_dict[hash] !== undefined){
413
other_pairs = other_pairs.concat(other.$object_dict[hash])
414
}
415
if(other_pairs.length == 0){
416
return false
417
}
418
for(var i = 0, len_i = pairs.length; i < len_i; i++){
419
var flag = false
420
var key = pairs[i][0],
421
value = pairs[i][1][0]
422
for(var j = 0, len_j = other_pairs.length; j < len_j; j++){
423
if($B.rich_comp("__eq__", key, other_pairs[j][0]) &&
424
$B.rich_comp("__eq__", value, other_pairs[j][1][0])){
425
flag = true
426
break
432
}
433
}
434
return true
Sep 5, 2014
435
}
436
Feb 11, 2018
437
dict.__getitem__ = function(){
438
var $ = $B.args("__getitem__", 2, {self: null, arg: null},
439
["self", "arg"], arguments, {}, null, null),
440
self = $.self,
442
return dict.$getitem(self, arg)
443
}
444
445
dict.$getitem = function(self, arg){
446
if(self.$jsobj){
447
if(self.$jsobj[arg] === undefined){
448
if(self.$jsobj.hasOwnProperty(arg)){
450
}
451
throw _b_.KeyError.$factory(arg)
452
}
453
return self.$jsobj[arg]
455
456
switch(typeof arg){
457
case "string":
458
if(self.$string_dict[arg] !== undefined){
459
return self.$string_dict[arg][0]
461
break
462
case "number":
463
if(self.$numeric_dict[arg] !== undefined){
464
return self.$numeric_dict[arg][0]
466
break
467
}
468
469
// since the key is more complex use 'default' method of getting item
470
471
var hash = _b_.hash(arg),
472
_eq = function(other){return $B.rich_comp("__eq__", arg, other)}
473
474
if(typeof arg == "object"){
475
arg.$hash = hash // cache for setdefault
476
}
477
var sk = self.$str_hash[hash]
478
if(sk !== undefined && _eq(sk)){
479
return self.$string_dict[sk][0]
481
if(self.$numeric_dict[hash] !== undefined && _eq(hash)){
482
return self.$numeric_dict[hash][0]
484
if(_b_.isinstance(arg, _b_.str)){
485
// string subclass
486
var res = self.$string_dict[arg.valueOf()]
487
if(res !== undefined){return res[0]}
490
var ix = rank(self, hash, arg)
491
if(ix > -1){
492
return self.$object_dict[hash][ix][1][0]
495
if(self.__class__ !== dict){
497
var missing_method = getattr(self.__class__, "__missing__",
498
_b_.None)
499
}catch(err){
500
console.log(err)
501
502
}
503
if(missing_method !== _b_.None){
504
return missing_method(self, arg)
507
throw _b_.KeyError.$factory(arg)
Sep 5, 2014
508
}
509
510
dict.__hash__ = _b_.None
Sep 5, 2014
511
512
function init_from_list(self, args){
513
var i = -1,
514
stop = args.length - 1,
515
si = dict.__setitem__
516
while(i++ < stop){
517
var item = args[i]
518
switch(typeof item[0]) {
519
case 'string':
520
self.$string_dict[item[0]] = [item[1], self.$order++]
521
self.$str_hash[str_hash(item[0])] = item[0]
522
self.$version++
523
break
524
case 'number':
525
if(item[0] != 0 && item[0] != 1){
526
self.$numeric_dict[item[0]] = [item[1], self.$order++]
527
self.$version++
528
break
529
}
530
default:
531
si(self, item[0], item[1])
532
break
533
}
534
}
535
}
536
537
dict.__init__ = function(self, first, second){
539
if(first === undefined){return $N}
540
if(second === undefined){
541
if(first.$nat != 'kw' && $B.get_class(first) === $B.JSObj){
542
for(var key in first){
543
self.$string_dict[key] = [first[key], self.$order++]
544
}
545
return _b_.None
546
}else if(first.$jsobj){
547
self.$jsobj = {}
548
for(var attr in first.$jsobj){
549
self.$jsobj[attr] = first.$jsobj[attr]
552
}else if(Array.isArray(first)){
553
init_from_list(self, first)
554
return $N
Sep 5, 2014
555
}
558
$ = $ || $B.args("dict", 1, {self:null}, ["self"],
559
arguments, {}, "first", "second")
560
var args = $.first
561
if(args.length > 1){
562
throw _b_.TypeError.$factory("dict expected at most 1 argument" +
563
", got 2")
564
}else if(args.length == 1){
565
args = args[0]
566
if(args.__class__ === dict){
567
['$string_dict', '$str_hash', '$numeric_dict', '$object_dict'].
568
forEach(function(d){
569
for(key in args[d]){self[d][key] = args[d][key]}
570
})
571
}else if(_b_.isinstance(args, dict)){
574
var keys = $B.$getattr(args, "keys", null)
575
if(keys !== null){
576
var gi = $B.$getattr(args, "__getitem__", null)
577
if(gi !== null){
578
// has keys and __getitem__ : it's a mapping, iterate on
579
// keys and values
580
gi = $B.$call(gi)
581
var kiter = _b_.iter($B.$call(keys)())
582
while(true){
583
try{
584
var key = _b_.next(kiter),
585
value = gi(key)
586
dict.__setitem__(self, key, value)
587
}catch(err){
588
if(err.__class__ === _b_.StopIteration){
589
break
590
}
591
throw err
592
}
593
}
594
return $N
595
}
596
}
597
if(! Array.isArray(args)){
598
args = _b_.list.$factory(args)
599
}
600
// Form "dict([[key1, value1], [key2,value2], ...])"
601
init_from_list(self, args)
Sep 5, 2014
602
}
604
var kw = $.second.$string_dict
605
for(var attr in kw){
606
switch(typeof attr){
607
case "string":
608
self.$string_dict[attr] = [kw[attr][0], self.$order++]
609
self.$str_hash[str_hash(attr)] = attr
610
break
611
case "number":
612
self.$numeric_dict[attr] = [kw[attr][0], self.$order++]
615
si(self, attr, kw[attr][0])
Sep 5, 2014
620
}
621
Feb 11, 2018
622
dict.__iter__ = function(self) {
623
return _b_.iter(dict.$$keys(self))
Sep 5, 2014
624
}
625
626
dict.__ior__ = function(self, other){
627
// PEP 584
628
dict.update(self, other)
629
return self
630
}
631
Feb 11, 2018
632
dict.__len__ = function(self) {
635
if(self.$jsobj){
Mar 7, 2018
636
for(var attr in self.$jsobj){if(attr.charAt(0) != "$"){_count++}}
637
return _count
638
}
640
for(var k in self.$numeric_dict){_count++}
641
for(var k in self.$string_dict){_count++}
642
for(var hash in self.$object_dict){
643
_count += self.$object_dict[hash].length
644
}
Sep 5, 2014
648
Mar 7, 2018
649
dict.__ne__ = function(self, other){return ! dict.__eq__(self, other)}
Sep 5, 2014
650
Feb 11, 2018
651
dict.__new__ = function(cls){
652
if(cls === undefined){
Mar 7, 2018
653
throw _b_.TypeError.$factory("int.__new__(): not enough arguments")
655
var instance = {
657
$numeric_dict : {},
658
$object_dict : {},
661
$version: 0,
662
$order: 0
664
if(cls !== dict){
665
instance.__dict__ = $B.empty_dict()
666
}
667
return instance
670
dict.__or__ = function(self, other){
671
// PEP 584
672
if(! _b_.isinstance(other, dict)){
673
return _b_.NotImplemented
674
}
675
var res = dict.copy(self)
676
dict.update(res, other)
677
return res
678
}
679
Feb 11, 2018
680
dict.__repr__ = function(self){
681
if(self.$jsobj){ // wrapper around Javascript object
Feb 11, 2018
682
return dict.__repr__(jsobj2dict(self.$jsobj))
684
if($B.repr.enter(self)){
685
return "{...}"
686
}
687
var res = [],
689
items.forEach(function(item){
690
try{
691
res.push(repr(item[0]) + ": " + repr(item[1]))
692
}catch(err){
693
throw err
694
}
696
$B.repr.leave(self)
Mar 7, 2018
697
return "{" + res.join(", ") + "}"
Sep 5, 2014
698
}
699
700
dict.__ror__ = function(self, other){
701
// PEP 584
702
if(! _b_.isinstance(other, dict)){
703
return _b_.NotImplemented
704
}
705
var res = dict.copy(other)
706
dict.update(res, self)
707
return res
708
}
709
710
dict.__setitem__ = function(self, key, value){
Mar 7, 2018
711
var $ = $B.args("__setitem__", 3, {self: null, key: null, value: null},
712
["self", "key", "value"], arguments, {}, null, null)
713
return dict.$setitem($.self, $.key, $.value)
714
}
Nov 21, 2015
715
716
dict.$setitem = function(self, key, value, $hash){
717
// Set a dictionary item mapping key and value.
718
//
719
// If key is a string, set:
720
// - $string_dict[key] = [value, order] where "order" is an auto-increment
721
// unique id to keep track of insertion order
722
// - $str_hash[hash(key)] to key
723
//
724
// If key is a number, set $numeric_dict[key] = value
725
//
726
// If key is another object, compute its hash value:
727
// - if the hash is a key of $str_hash, and key == $str_hash[hash],
728
// replace $string_dict[$str_hash[hash]] by value
729
// - if the hash is a key of $numeric_dict, and hash == key, replace
730
// $numeric_dict[hash] by value
731
// - if the hash is a key of $object_dict: $object_dict[hash] is a list
732
// of [k, v] pairs. If key is equal to one of the "k", replace the
733
// matching v by value. Otherwise, add [key, value] to the list
734
// - else set $object_dict[hash] = [[key, value]]
735
//
736
// In all cases, increment attribute $version, used to detect dictionary
737
// changes during an iteration.
739
// Parameter $hash is only set if this method is called by setdefault.
740
// In this case the hash of key has already been computed and we
741
// know that the key is not present in the dictionary, so it's no
742
// use computing hash(key) again, nor testing equality of keys
744
if(self.$from_js){
745
// dictionary created by method to_dict of JSObj instances
746
value = $B.pyobj2jsobj(value)
747
}
748
if(self.$jsobj.__class__ === _b_.type){
749
self.$jsobj[key] = value
750
if(key == "__init__" || key == "__new__"){
751
// If class attribute __init__ or __new__ are reset,
752
// the factory function has to change
753
self.$jsobj.$factory = $B.$instance_creator(self.$jsobj)
754
}
755
}else{
756
self.$jsobj[key] = value
761
switch(typeof key){
762
case "string":
763
if(self.$string_dict === undefined){
764
console.log("pas de string dict", self, key, value)
765
}
766
if(self.$string_dict[key] !== undefined){
767
self.$string_dict[key][0] = value
768
}else{
769
self.$string_dict[key] = [value, self.$order++]
770
self.$str_hash[str_hash(key)] = key
771
self.$version++
772
}
773
return $N
774
case "number":
775
if(self.$numeric_dict[key] !== undefined){
776
// existing key: preserve order
777
self.$numeric_dict[key][0] = value
778
}else{
779
// special case for 0 and 1 if True or False are keys
780
var done = false
781
if((key == 0 || key == 1) &&
782
self.$object_dict[key] !== undefined){
783
for(const item of self.$object_dict[key]){
784
if((key == 0 && item[0] === false) ||
785
(key == 1 && item[0] === true)){
786
// replace value
787
item[1][0] = value
788
done = true
789
}
790
}
791
}
792
if(! done){
793
// new key
794
self.$numeric_dict[key] = [value, self.$order++]
795
}
798
return $N
799
case "boolean":
800
// true replaces 1 and false replaces 0
801
var num = key ? 1 : 0
802
if(self.$numeric_dict[num] !== undefined){
803
var order = self.$numeric_dict[num][1] // preserve order
804
self.$numeric_dict[num] = [value, order]
805
return
806
}
807
if(self.$object_dict[num] !== undefined){
808
self.$object_dict[num].push([key, [value, self.$order++]])
809
}else{
810
self.$object_dict[num] = [[key, [value, self.$order++]]]
811
}
814
// if we got here the key is more complex, use default method
815
816
var hash = $hash === undefined ? _b_.hash(key) : $hash,
817
_eq = function(other){return $B.rich_comp("__eq__", key, other)}
818
819
if(self.$numeric_dict[hash] !== undefined && _eq(hash)){
820
self.$numeric_dict[hash] = [value, self.$numeric_dict[hash][1]]
824
var sk = self.$str_hash[hash]
825
if(sk !== undefined && _eq(sk)){
826
self.$string_dict[sk] = [value, self.$string_dict[sk][1]]
831
// If $setitem is called from setdefault, don't test equality of key
832
// with any object
833
if($hash){
834
if(self.$object_dict[$hash] !== undefined){
835
self.$object_dict[$hash].push([key, [value, self.$order++]])
837
self.$object_dict[$hash] = [[key, [value, self.$order++]]]
838
}
839
self.$version++
840
return $N
841
}
842
var ix = rank(self, hash, key)
843
if(ix > -1){
844
// reset value
845
self.$object_dict[hash][ix][1] = [value,
846
self.$object_dict[hash][ix][1][1]]
847
return $N
848
}else if(self.$object_dict.hasOwnProperty(hash)){
849
self.$object_dict[hash].push([key, [value, self.$order++]])
851
self.$object_dict[hash] = [[key, [value, self.$order++]]]
Sep 5, 2014
855
}
856
857
dict.__str__ = function(){
858
return dict.__repr__.apply(null, arguments)
859
}
Sep 5, 2014
860
861
// add "reflected" methods
Feb 11, 2018
862
$B.make_rmethods(dict)
Sep 5, 2014
863
Feb 11, 2018
864
dict.clear = function(){
Sep 5, 2014
865
// Remove all items from the dictionary.
Mar 7, 2018
866
var $ = $B.args("clear", 1, {self: null}, ["self"], arguments, {},
867
null, null),
868
self = $.self
870
self.$numeric_dict = {}
871
self.$string_dict = {}
872
self.$str_hash = {}
873
self.$object_dict = {}
875
if(self.$jsobj){
876
for(var attr in self.$jsobj){
Mar 7, 2018
877
if(attr.charAt(0) !== "$" && attr !== "__class__"){
878
delete self.$jsobj[attr]
879
}
880
}
881
}
Sep 5, 2014
885
}
886
Feb 11, 2018
887
dict.copy = function(self){
Sep 5, 2014
888
// Return a shallow copy of the dictionary
Mar 7, 2018
889
var $ = $B.args("copy", 1, {self: null},["self"], arguments,{},
890
null, null),
891
self = $.self,
Sep 5, 2014
894
return res
895
}
896
Feb 11, 2018
897
dict.fromkeys = function(){
Nov 21, 2015
898
Mar 7, 2018
899
var $ = $B.args("fromkeys", 3, {cls: null, keys: null, value: null},
900
["cls", "keys", "value"], arguments, {value: _b_.None}, null, null),
901
keys = $.keys,
902
value = $.value
Sep 5, 2014
904
// class method
905
var klass = $.cls,
Sep 5, 2014
909
while(1){
910
try{
911
var key = _b_.next(keys_iter)
912
if(klass === dict){dict.$setitem(res, key, value)}
913
else{$B.$getattr(res, "__setitem__")(key, value)}
Sep 5, 2014
914
}catch(err){
915
if($B.is_exc(err, [_b_.StopIteration])){
Sep 5, 2014
916
return res
917
}
918
throw err
919
}
920
}
921
}
922
Feb 11, 2018
923
dict.get = function(){
Mar 7, 2018
924
var $ = $B.args("get", 3, {self: null, key: null, _default: null},
925
["self", "key", "_default"], arguments, {_default: $N}, null, null)
Feb 11, 2018
927
try{return dict.__getitem__($.self, $.key)}
928
catch(err){
929
if(_b_.isinstance(err, _b_.KeyError)){return $._default}
930
else{throw err}
931
}
932
}
933
934
var dict_items = $B.make_view("dict_items", true)
935
dict_items.$iterator = $B.make_iterator_class("dict_itemiterator")
936
Feb 11, 2018
937
dict.items = function(self){
Mar 23, 2018
938
if(arguments.length > 1){
939
var _len = arguments.length - 1,
940
_msg = "items() takes no arguments (" + _len + " given)"
941
throw _b_.TypeError.$factory(_msg)
942
}
943
var items = to_list(self),
944
set_like = true
945
// Check if all values are hashable
946
for(var i = 0, len = items.length; i < len; i++){
947
try{
948
_b_.hash(items[i][1])
949
}catch(err){
950
set_like = false
951
break
952
}
953
}
954
var it = dict_items.$factory(to_list(self), set_like)
955
it.len_func = function(){return dict.__len__(self)}
956
return it
957
}
958
959
var dict_keys = $B.make_view("dict_keys")
960
dict_keys.$iterator = $B.make_iterator_class("dict_keyiterator")
Nov 21, 2015
961
Mar 23, 2018
963
if(arguments.length > 1){
964
var _len = arguments.length - 1,
965
_msg = "keys() takes no arguments (" + _len + " given)"
966
throw _b_.TypeError.$factory(_msg)
Nov 21, 2015
967
}
968
var it = dict_keys.$factory(to_list(self, 0), true)
969
it.len_func = function(){return dict.__len__(self)}
970
return it
Nov 21, 2015
971
}
972
Feb 11, 2018
973
dict.pop = function(){
Nov 21, 2015
974
975
var missing = {},
976
$ = $B.args("pop", 3, {self: null, key: null, _default: null},
977
["self", "key", "_default"], arguments, {_default: missing}, null, null),
978
self = $.self,
979
key = $.key,
980
_default = $._default
Nov 21, 2015
981
Sep 5, 2014
982
try{
983
var res = dict.__getitem__(self, key)
984
dict.__delitem__(self, key)
Sep 5, 2014
985
return res
986
}catch(err){
987
if(err.__class__ === _b_.KeyError){
988
if(_default !== missing){return _default}
Sep 5, 2014
989
throw err
990
}
991
throw err
992
}
993
}
994
Feb 11, 2018
995
dict.popitem = function(self){
997
var itm = _b_.next(_b_.iter(dict.items(self)))
998
dict.__delitem__(self, itm[0])
Feb 11, 2018
999
return _b_.tuple.$factory(itm)
1001
if (err.__class__ == _b_.StopIteration) {
1002
throw _b_.KeyError.$factory("'popitem(): dictionary is empty'")
Sep 5, 2014
1005
}
1006
Feb 11, 2018
1007
dict.setdefault = function(){
Nov 21, 2015
1008
Mar 7, 2018
1009
var $ = $B.args("setdefault", 3, {self: null, key: null, _default: null},
1010
["self", "key", "_default"], arguments, {_default: $N}, null, null),
1011
self = $.self,
1012
key = $.key,
1013
_default = $._default
Nov 21, 2015
1014
1015
try{return dict.__getitem__(self, key)}
Sep 5, 2014
1016
catch(err){
1017
if(err.__class__ !== _b_.KeyError){
1018
throw err
1019
}
1020
if(_default === undefined){_default = $N}
1021
var hash = key.$hash
1022
key.$hash = undefined
1023
dict.$setitem(self, key, _default, hash)
Sep 5, 2014
1024
return _default
1025
}
1026
}
1027
Feb 11, 2018
1028
dict.update = function(self){
Nov 21, 2015
1029
Mar 7, 2018
1030
var $ = $B.args("update", 1, {"self": null}, ["self"], arguments,
1031
{}, "args", "kw"),
1032
self = $.self,
1033
args = $.args,
1034
kw = $.kw
1035
if(args.length > 0){
1036
var o = args[0]
1038
if(o.$jsobj){
1039
o = jsobj2dict(o.$jsobj)
1040
}
1042
}else if(_b_.hasattr(o, "keys")){
1043
var _keys = _b_.list.$factory($B.$call($B.$getattr(o, "keys"))())
1044
for(var i = 0, len = _keys.length; i < len; i++){
1045
var _value = getattr(o, "__getitem__")(_keys[i])
1046
dict.$setitem(self, _keys[i], _value)
1047
}
1048
}else{
1049
var it = _b_.iter(o),
1050
i = 0
1051
while(true){
1052
try{
1053
var item = _b_.next(it)
1054
}catch(err){
1055
if(err.__class__ === _b_.StopIteration){break}
1056
throw err
1057
}
1058
try{
1059
key_value = _b_.list.$factory(item)
1060
}catch(err){
1061
throw _b_.TypeError.$factory("cannot convert dictionary" +
1062
" update sequence element #" + i + " to a sequence")
1063
}
1064
if(key_value.length !== 2){
1065
throw _b_.ValueError.$factory("dictionary update " +
1066
"sequence element #" + i + " has length " +
1067
key_value.length + "; 2 is required")
1068
}
1069
dict.$setitem(self, key_value[0], key_value[1])
1070
i++
Sep 5, 2014
1073
}
Sep 5, 2014
1077
}
1078
1079
var dict_values = $B.make_view("dict_values")
1080
dict_values.$iterator = $B.make_iterator_class("dict_valueiterator")
Nov 21, 2015
1081
Feb 11, 2018
1082
dict.values = function(self){
Mar 23, 2018
1083
if(arguments.length > 1){
1084
var _len = arguments.length - 1,
1085
_msg = "values() takes no arguments (" + _len + " given)"
1086
throw _b_.TypeError.$factory(_msg)
Nov 21, 2015
1087
}
1088
var values = to_list(self, 1)
1089
var it = dict_values.$factory(to_list(self, 1), false)
1090
it.len_func = function(){return dict.__len__(self)}
1091
return it
Nov 21, 2015
1092
}
1093
1094
dict.$factory = function(){
1095
var res = dict.__new__(dict)
1096
var args = [res]
1097
for(var i = 0, len = arguments.length; i < len ; i++){
1098
args.push(arguments[i])
1099
}
1100
dict.__init__.apply(null, args)
Sep 5, 2014
1101
return res
1102
}
Sep 5, 2014
1104
_b_.dict = dict
Feb 11, 2018
1106
$B.set_func_names(dict, "builtins")
1107
1108
$B.empty_dict = function(){
1109
return {
1110
__class__: dict,
1111
$numeric_dict : {},
1112
$object_dict : {},
1113
$string_dict : {},
1114
$str_hash: {},
1115
$version: 0,
1116
$order: 0
1120
// This must be done after set_func_names, otherwise dict.fromkeys doesn't
1121
// have the attribute $infos
1122
dict.fromkeys = _b_.classmethod.$factory(dict.fromkeys)
1123
1124
$B.getset_descriptor = $B.make_class("getset_descriptor",
1125
function(klass, attr){
1126
return {
1127
__class__: $B.getset_descriptor,
1128
__doc__: _b_.None,
1129
cls: klass,
1130
attr: attr
1131
}
1132
}
1133
)
1134
1135
$B.getset_descriptor.__repr__ = $B.getset_descriptor.__str__ = function(self){
1136
return `<attribute '${self.attr}' of '${self.cls.$infos.__name__}' objects>`
1137
}
1138
1139
$B.set_func_names($B.getset_descriptor, "builtins")
1140
1141
// Class for attribute __dict__ of classes
1142
var mappingproxy = $B.mappingproxy = $B.make_class("mappingproxy",
Feb 12, 2018
1143
function(obj){
1144
if(_b_.isinstance(obj, dict)){
1145
// obj is a dictionary, with $string_dict table such that
1146
// obj.$string_dict[key] = [value, rank]
1147
// Transform it into an object with attribute $jsobj such that
1148
// res.$jsobj[key] = value
1149
var res = $B.obj_dict(dict.$to_obj(obj))
1150
}else{
1151
var res = $B.obj_dict(obj)
1152
}
Feb 12, 2018
1153
res.__class__ = mappingproxy
1154
return res
1155
}
1156
)
Feb 12, 2018
1158
mappingproxy.__setitem__ = function(){
Mar 7, 2018
1159
throw _b_.TypeError.$factory("'mappingproxy' object does not support " +
1160
"item assignment")
1163
for(var attr in dict){
1164
if(mappingproxy[attr] !== undefined ||
1165
["__class__", "__mro__", "__new__", "__init__", "__delitem__",
1166
"clear", "fromkeys", "pop", "popitem", "setdefault",
1167
"update"].indexOf(attr) > -1){
1168
continue
1169
}
1170
if(typeof dict[attr] == "function"){
1171
mappingproxy[attr] = (function(key){
1172
return function(){
1173
return dict[key].apply(null, arguments)
1174
}
1175
})(attr)
1176
}else{
1177
mappingproxy[attr] = dict[attr]
1178
}
1179
}
1180
Feb 12, 2018
1181
$B.set_func_names(mappingproxy, "builtins")
Mar 7, 2018
1186
if(attr.charAt(0) != "$" && attr !== "__class__"){
1187
if(x[attr] === null){
1188
d.$string_dict[attr] = [_b_.None, d.$order++]
1189
}else if(x[attr] === undefined){
1190
continue
1191
}else if(x[attr].$jsobj === x){
1192
d.$string_dict[attr] = [d, d.$order++]
1194
d.$string_dict[attr] = [$B.$JS2Py(x[attr]), d.$order++]
1196
}
1197
}
1198
return d
1199
}
1201
$B.obj_dict = function(obj, from_js){
1202
var klass = obj.__class__ || $B.get_class(obj)
1203
if(klass !== undefined && klass.$native){
1204
throw _b_.AttributeError.$factory(klass.__name__ +
1205
" has no attribute '__dict__'")}
1207
res.$jsobj = obj
1208
res.$from_js = from_js // set to true if
1209
return res
1210
}
1211
Sep 5, 2014
1212
})(__BRYTHON__)