Skip to content
Permalink
Newer
Older
100644 1223 lines (1104 sloc) 36.2 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
287
dict.__class_getitem__ = function(cls, item){
288
// PEP 585
289
// Set as a classmethod at the end of this script, after $B.set_func_names()
290
if(! Array.isArray(item)){
291
item = [item]
292
}
293
return $B.GenericAlias.$factory(cls, item)
294
}
295
Feb 11, 2018
296
dict.__contains__ = function(){
Nov 21, 2015
297
298
var $ = $B.args("__contains__", 2, {self: null, key: null},
299
["self", "key"], arguments, {}, null, null),
300
self = $.self,
302
if(self.$is_namespace){key = $B.to_alias(key)} // issue 1244
303
304
if(self.$jsobj){
305
return self.$jsobj[key] !== undefined
306
}
308
switch(typeof key) {
310
return self.$string_dict[key] !== undefined
312
return self.$numeric_dict[key] !== undefined
313
}
314
315
var hash = _b_.hash(key)
316
if(self.$str_hash[hash] !== undefined &&
317
$B.rich_comp("__eq__", key, self.$str_hash[hash])){return true}
318
if(self.$numeric_dict[hash] !== undefined &&
319
$B.rich_comp("__eq__", key, hash)){return true}
320
return rank(self, hash, key) > -1
Sep 5, 2014
321
}
322
Feb 11, 2018
323
dict.__delitem__ = function(){
Nov 21, 2015
324
325
var $ = $B.args("__eq__", 2, {self: null, arg: null},
326
["self", "arg"], arguments, {}, null, null),
327
self = $.self,
Nov 21, 2015
329
330
if(self.$jsobj){
331
if(self.$jsobj[arg] === undefined){throw _b_.KeyError.$factory(arg)}
332
delete self.$jsobj[arg]
335
switch(typeof arg){
336
case "string":
337
if(self.$string_dict[arg] === undefined){
338
throw _b_.KeyError.$factory(_b_.str.$factory(arg))
339
}
340
delete self.$string_dict[arg]
341
delete self.$str_hash[str_hash(arg)]
343
return $N
344
case "number":
345
if(self.$numeric_dict[arg] === undefined){
346
throw _b_.KeyError.$factory(_b_.str.$factory(arg))
348
delete self.$numeric_dict[arg]
352
// go with defaults
353
354
var hash = _b_.hash(arg),
355
ix
357
if((ix = rank(self, hash, arg)) > -1){
358
self.$object_dict[hash].splice(ix, 1)
359
}else{
360
throw _b_.KeyError.$factory(_b_.str.$factory(arg))
Sep 5, 2014
365
}
366
Feb 11, 2018
367
dict.__eq__ = function(){
Mar 7, 2018
368
var $ = $B.args("__eq__", 2, {self: null, other: null},
369
["self", "other"], arguments, {}, null, null),
370
self = $.self,
371
other = $.other
373
if(! _b_.isinstance(other, dict)){return false}
375
if(self.$jsobj){self = jsobj2dict(self.$jsobj)}
376
if(other.$jsobj){other = jsobj2dict(other.$jsobj)}
377
if(dict.__len__(self) != dict.__len__(other)){
378
return false
379
}
381
if(self.$string_dict.length != other.$string_dict.length){
385
for(var k in self.$numeric_dict){
386
if(other.$numeric_dict.hasOwnProperty(k)){
387
if(!$B.rich_comp("__eq__", other.$numeric_dict[k][0],
388
self.$numeric_dict[k][0])){
389
return false
390
}
391
}else if(other.$object_dict.hasOwnProperty(k)){
392
var pairs = other.$object_dict[k],
393
flag = false
394
for(var i = 0, len = pairs.length; i < len; i++){
395
if($B.rich_comp("__eq__", k, pairs[i][0]) &&
396
$B.rich_comp("__eq__", self.$numeric_dict[k],
397
pairs[i][1])){
398
flag = true
399
break
400
}
402
if(! flag){return false}
Nov 21, 2015
405
}
406
}
407
for(var k in self.$string_dict){
408
if(!other.$string_dict.hasOwnProperty(k) ||
409
!$B.rich_comp("__eq__", other.$string_dict[k][0],
410
self.$string_dict[k][0])){
Nov 21, 2015
412
}
413
}
414
for(var hash in self.$object_dict){
415
var pairs = self.$object_dict[hash]
416
// Get all (key, value) pairs in other that have the same hash
417
var other_pairs = []
418
if(other.$numeric_dict[hash] !== undefined){
419
other_pairs.push([hash, other.$numeric_dict[hash]])
420
}
421
if(other.$object_dict[hash] !== undefined){
422
other_pairs = other_pairs.concat(other.$object_dict[hash])
423
}
424
if(other_pairs.length == 0){
425
return false
426
}
427
for(var i = 0, len_i = pairs.length; i < len_i; i++){
428
var flag = false
429
var key = pairs[i][0],
430
value = pairs[i][1][0]
431
for(var j = 0, len_j = other_pairs.length; j < len_j; j++){
432
if($B.rich_comp("__eq__", key, other_pairs[j][0]) &&
433
$B.rich_comp("__eq__", value, other_pairs[j][1][0])){
434
flag = true
435
break
441
}
442
}
443
return true
Sep 5, 2014
444
}
445
Feb 11, 2018
446
dict.__getitem__ = function(){
447
var $ = $B.args("__getitem__", 2, {self: null, arg: null},
448
["self", "arg"], arguments, {}, null, null),
449
self = $.self,
451
return dict.$getitem(self, arg)
452
}
453
454
dict.$getitem = function(self, arg){
455
if(self.$jsobj){
456
if(self.$jsobj[arg] === undefined){
457
if(self.$jsobj.hasOwnProperty(arg)){
459
}
460
throw _b_.KeyError.$factory(arg)
461
}
462
return self.$jsobj[arg]
464
465
switch(typeof arg){
466
case "string":
467
if(self.$string_dict[arg] !== undefined){
468
return self.$string_dict[arg][0]
470
break
471
case "number":
472
if(self.$numeric_dict[arg] !== undefined){
473
return self.$numeric_dict[arg][0]
475
break
476
}
477
478
// since the key is more complex use 'default' method of getting item
479
480
var hash = _b_.hash(arg),
481
_eq = function(other){return $B.rich_comp("__eq__", arg, other)}
482
483
if(typeof arg == "object"){
484
arg.$hash = hash // cache for setdefault
485
}
486
var sk = self.$str_hash[hash]
487
if(sk !== undefined && _eq(sk)){
488
return self.$string_dict[sk][0]
490
if(self.$numeric_dict[hash] !== undefined && _eq(hash)){
491
return self.$numeric_dict[hash][0]
493
if(_b_.isinstance(arg, _b_.str)){
494
// string subclass
495
var res = self.$string_dict[arg.valueOf()]
496
if(res !== undefined){return res[0]}
499
var ix = rank(self, hash, arg)
500
if(ix > -1){
501
return self.$object_dict[hash][ix][1][0]
504
if(self.__class__ !== dict){
506
var missing_method = getattr(self.__class__, "__missing__",
507
_b_.None)
508
}catch(err){
509
console.log(err)
510
511
}
512
if(missing_method !== _b_.None){
513
return missing_method(self, arg)
516
throw _b_.KeyError.$factory(arg)
Sep 5, 2014
517
}
518
519
dict.__hash__ = _b_.None
Sep 5, 2014
520
521
function init_from_list(self, args){
522
var i = -1,
523
stop = args.length - 1,
524
si = dict.__setitem__
525
while(i++ < stop){
526
var item = args[i]
527
switch(typeof item[0]) {
528
case 'string':
529
self.$string_dict[item[0]] = [item[1], self.$order++]
530
self.$str_hash[str_hash(item[0])] = item[0]
531
self.$version++
532
break
533
case 'number':
534
if(item[0] != 0 && item[0] != 1){
535
self.$numeric_dict[item[0]] = [item[1], self.$order++]
536
self.$version++
537
break
538
}
539
default:
540
si(self, item[0], item[1])
541
break
542
}
543
}
544
}
545
546
dict.__init__ = function(self, first, second){
548
if(first === undefined){return $N}
549
if(second === undefined){
550
if(first.$nat != 'kw' && $B.get_class(first) === $B.JSObj){
551
for(var key in first){
552
self.$string_dict[key] = [first[key], self.$order++]
553
}
554
return _b_.None
555
}else if(first.$jsobj){
556
self.$jsobj = {}
557
for(var attr in first.$jsobj){
558
self.$jsobj[attr] = first.$jsobj[attr]
561
}else if(Array.isArray(first)){
562
init_from_list(self, first)
563
return $N
Sep 5, 2014
564
}
567
$ = $ || $B.args("dict", 1, {self:null}, ["self"],
568
arguments, {}, "first", "second")
569
var args = $.first
570
if(args.length > 1){
571
throw _b_.TypeError.$factory("dict expected at most 1 argument" +
572
", got 2")
573
}else if(args.length == 1){
574
args = args[0]
575
if(args.__class__ === dict){
576
['$string_dict', '$str_hash', '$numeric_dict', '$object_dict'].
577
forEach(function(d){
578
for(key in args[d]){self[d][key] = args[d][key]}
579
})
580
}else if(_b_.isinstance(args, dict)){
583
var keys = $B.$getattr(args, "keys", null)
584
if(keys !== null){
585
var gi = $B.$getattr(args, "__getitem__", null)
586
if(gi !== null){
587
// has keys and __getitem__ : it's a mapping, iterate on
588
// keys and values
589
gi = $B.$call(gi)
590
var kiter = _b_.iter($B.$call(keys)())
591
while(true){
592
try{
593
var key = _b_.next(kiter),
594
value = gi(key)
595
dict.__setitem__(self, key, value)
596
}catch(err){
597
if(err.__class__ === _b_.StopIteration){
598
break
599
}
600
throw err
601
}
602
}
603
return $N
604
}
605
}
606
if(! Array.isArray(args)){
607
args = _b_.list.$factory(args)
608
}
609
// Form "dict([[key1, value1], [key2,value2], ...])"
610
init_from_list(self, args)
Sep 5, 2014
611
}
613
var kw = $.second.$string_dict
614
for(var attr in kw){
615
switch(typeof attr){
616
case "string":
617
self.$string_dict[attr] = [kw[attr][0], self.$order++]
618
self.$str_hash[str_hash(attr)] = attr
619
break
620
case "number":
621
self.$numeric_dict[attr] = [kw[attr][0], self.$order++]
624
si(self, attr, kw[attr][0])
Sep 5, 2014
629
}
630
Feb 11, 2018
631
dict.__iter__ = function(self) {
632
return _b_.iter(dict.$$keys(self))
Sep 5, 2014
633
}
634
635
dict.__ior__ = function(self, other){
636
// PEP 584
637
dict.update(self, other)
638
return self
639
}
640
Feb 11, 2018
641
dict.__len__ = function(self) {
644
if(self.$jsobj){
Mar 7, 2018
645
for(var attr in self.$jsobj){if(attr.charAt(0) != "$"){_count++}}
646
return _count
647
}
649
for(var k in self.$numeric_dict){_count++}
650
for(var k in self.$string_dict){_count++}
651
for(var hash in self.$object_dict){
652
_count += self.$object_dict[hash].length
653
}
Sep 5, 2014
657
Mar 7, 2018
658
dict.__ne__ = function(self, other){return ! dict.__eq__(self, other)}
Sep 5, 2014
659
Feb 11, 2018
660
dict.__new__ = function(cls){
661
if(cls === undefined){
Mar 7, 2018
662
throw _b_.TypeError.$factory("int.__new__(): not enough arguments")
664
var instance = {
666
$numeric_dict : {},
667
$object_dict : {},
670
$version: 0,
671
$order: 0
673
if(cls !== dict){
674
instance.__dict__ = $B.empty_dict()
675
}
676
return instance
679
dict.__or__ = function(self, other){
680
// PEP 584
681
if(! _b_.isinstance(other, dict)){
682
return _b_.NotImplemented
683
}
684
var res = dict.copy(self)
685
dict.update(res, other)
686
return res
687
}
688
Feb 11, 2018
689
dict.__repr__ = function(self){
690
if(self.$jsobj){ // wrapper around Javascript object
Feb 11, 2018
691
return dict.__repr__(jsobj2dict(self.$jsobj))
693
if($B.repr.enter(self)){
694
return "{...}"
695
}
696
var res = [],
698
items.forEach(function(item){
699
try{
700
res.push(repr(item[0]) + ": " + repr(item[1]))
701
}catch(err){
702
throw err
703
}
705
$B.repr.leave(self)
Mar 7, 2018
706
return "{" + res.join(", ") + "}"
Sep 5, 2014
707
}
708
709
dict.__ror__ = function(self, other){
710
// PEP 584
711
if(! _b_.isinstance(other, dict)){
712
return _b_.NotImplemented
713
}
714
var res = dict.copy(other)
715
dict.update(res, self)
716
return res
717
}
718
719
dict.__setitem__ = function(self, key, value){
Mar 7, 2018
720
var $ = $B.args("__setitem__", 3, {self: null, key: null, value: null},
721
["self", "key", "value"], arguments, {}, null, null)
722
return dict.$setitem($.self, $.key, $.value)
723
}
Nov 21, 2015
724
725
dict.$setitem = function(self, key, value, $hash){
726
// Set a dictionary item mapping key and value.
727
//
728
// If key is a string, set:
729
// - $string_dict[key] = [value, order] where "order" is an auto-increment
730
// unique id to keep track of insertion order
731
// - $str_hash[hash(key)] to key
732
//
733
// If key is a number, set $numeric_dict[key] = value
734
//
735
// If key is another object, compute its hash value:
736
// - if the hash is a key of $str_hash, and key == $str_hash[hash],
737
// replace $string_dict[$str_hash[hash]] by value
738
// - if the hash is a key of $numeric_dict, and hash == key, replace
739
// $numeric_dict[hash] by value
740
// - if the hash is a key of $object_dict: $object_dict[hash] is a list
741
// of [k, v] pairs. If key is equal to one of the "k", replace the
742
// matching v by value. Otherwise, add [key, value] to the list
743
// - else set $object_dict[hash] = [[key, value]]
744
//
745
// In all cases, increment attribute $version, used to detect dictionary
746
// changes during an iteration.
748
// Parameter $hash is only set if this method is called by setdefault.
749
// In this case the hash of key has already been computed and we
750
// know that the key is not present in the dictionary, so it's no
751
// use computing hash(key) again, nor testing equality of keys
753
if(self.$from_js){
754
// dictionary created by method to_dict of JSObj instances
755
value = $B.pyobj2jsobj(value)
756
}
757
if(self.$jsobj.__class__ === _b_.type){
758
self.$jsobj[key] = value
759
if(key == "__init__" || key == "__new__"){
760
// If class attribute __init__ or __new__ are reset,
761
// the factory function has to change
762
self.$jsobj.$factory = $B.$instance_creator(self.$jsobj)
763
}
764
}else{
765
self.$jsobj[key] = value
770
switch(typeof key){
771
case "string":
772
if(self.$string_dict === undefined){
773
console.log("pas de string dict", self, key, value)
774
}
775
if(self.$string_dict[key] !== undefined){
776
self.$string_dict[key][0] = value
777
}else{
778
self.$string_dict[key] = [value, self.$order++]
779
self.$str_hash[str_hash(key)] = key
780
self.$version++
781
}
782
return $N
783
case "number":
784
if(self.$numeric_dict[key] !== undefined){
785
// existing key: preserve order
786
self.$numeric_dict[key][0] = value
787
}else{
788
// special case for 0 and 1 if True or False are keys
789
var done = false
790
if((key == 0 || key == 1) &&
791
self.$object_dict[key] !== undefined){
792
for(const item of self.$object_dict[key]){
793
if((key == 0 && item[0] === false) ||
794
(key == 1 && item[0] === true)){
795
// replace value
796
item[1][0] = value
797
done = true
798
}
799
}
800
}
801
if(! done){
802
// new key
803
self.$numeric_dict[key] = [value, self.$order++]
804
}
807
return $N
808
case "boolean":
809
// true replaces 1 and false replaces 0
810
var num = key ? 1 : 0
811
if(self.$numeric_dict[num] !== undefined){
812
var order = self.$numeric_dict[num][1] // preserve order
813
self.$numeric_dict[num] = [value, order]
814
return
815
}
816
if(self.$object_dict[num] !== undefined){
817
self.$object_dict[num].push([key, [value, self.$order++]])
818
}else{
819
self.$object_dict[num] = [[key, [value, self.$order++]]]
820
}
823
// if we got here the key is more complex, use default method
824
825
var hash = $hash === undefined ? _b_.hash(key) : $hash,
826
_eq = function(other){return $B.rich_comp("__eq__", key, other)}
827
828
if(self.$numeric_dict[hash] !== undefined && _eq(hash)){
829
self.$numeric_dict[hash] = [value, self.$numeric_dict[hash][1]]
833
var sk = self.$str_hash[hash]
834
if(sk !== undefined && _eq(sk)){
835
self.$string_dict[sk] = [value, self.$string_dict[sk][1]]
840
// If $setitem is called from setdefault, don't test equality of key
841
// with any object
842
if($hash){
843
if(self.$object_dict[$hash] !== undefined){
844
self.$object_dict[$hash].push([key, [value, self.$order++]])
846
self.$object_dict[$hash] = [[key, [value, self.$order++]]]
847
}
848
self.$version++
849
return $N
850
}
851
var ix = rank(self, hash, key)
852
if(ix > -1){
853
// reset value
854
self.$object_dict[hash][ix][1] = [value,
855
self.$object_dict[hash][ix][1][1]]
856
return $N
857
}else if(self.$object_dict.hasOwnProperty(hash)){
858
self.$object_dict[hash].push([key, [value, self.$order++]])
860
self.$object_dict[hash] = [[key, [value, self.$order++]]]
Sep 5, 2014
864
}
865
866
dict.__str__ = function(){
867
return dict.__repr__.apply(null, arguments)
868
}
Sep 5, 2014
869
870
// add "reflected" methods
Feb 11, 2018
871
$B.make_rmethods(dict)
Sep 5, 2014
872
Feb 11, 2018
873
dict.clear = function(){
Sep 5, 2014
874
// Remove all items from the dictionary.
Mar 7, 2018
875
var $ = $B.args("clear", 1, {self: null}, ["self"], arguments, {},
876
null, null),
877
self = $.self
879
self.$numeric_dict = {}
880
self.$string_dict = {}
881
self.$str_hash = {}
882
self.$object_dict = {}
884
if(self.$jsobj){
885
for(var attr in self.$jsobj){
Mar 7, 2018
886
if(attr.charAt(0) !== "$" && attr !== "__class__"){
887
delete self.$jsobj[attr]
888
}
889
}
890
}
Sep 5, 2014
894
}
895
Feb 11, 2018
896
dict.copy = function(self){
Sep 5, 2014
897
// Return a shallow copy of the dictionary
Mar 7, 2018
898
var $ = $B.args("copy", 1, {self: null},["self"], arguments,{},
899
null, null),
900
self = $.self,
Sep 5, 2014
903
return res
904
}
905
Feb 11, 2018
906
dict.fromkeys = function(){
Nov 21, 2015
907
Mar 7, 2018
908
var $ = $B.args("fromkeys", 3, {cls: null, keys: null, value: null},
909
["cls", "keys", "value"], arguments, {value: _b_.None}, null, null),
910
keys = $.keys,
911
value = $.value
Sep 5, 2014
913
// class method
914
var klass = $.cls,
Sep 5, 2014
918
while(1){
919
try{
920
var key = _b_.next(keys_iter)
921
if(klass === dict){dict.$setitem(res, key, value)}
922
else{$B.$getattr(res, "__setitem__")(key, value)}
Sep 5, 2014
923
}catch(err){
924
if($B.is_exc(err, [_b_.StopIteration])){
Sep 5, 2014
925
return res
926
}
927
throw err
928
}
929
}
930
}
931
Feb 11, 2018
932
dict.get = function(){
Mar 7, 2018
933
var $ = $B.args("get", 3, {self: null, key: null, _default: null},
934
["self", "key", "_default"], arguments, {_default: $N}, null, null)
Feb 11, 2018
936
try{return dict.__getitem__($.self, $.key)}
937
catch(err){
938
if(_b_.isinstance(err, _b_.KeyError)){return $._default}
939
else{throw err}
940
}
941
}
942
943
var dict_items = $B.make_view("dict_items", true)
944
dict_items.$iterator = $B.make_iterator_class("dict_itemiterator")
945
Feb 11, 2018
946
dict.items = function(self){
Mar 23, 2018
947
if(arguments.length > 1){
948
var _len = arguments.length - 1,
949
_msg = "items() takes no arguments (" + _len + " given)"
950
throw _b_.TypeError.$factory(_msg)
951
}
952
var items = to_list(self),
953
set_like = true
954
// Check if all values are hashable
955
for(var i = 0, len = items.length; i < len; i++){
956
try{
957
_b_.hash(items[i][1])
958
}catch(err){
959
set_like = false
960
break
961
}
962
}
963
var it = dict_items.$factory(to_list(self), set_like)
964
it.len_func = function(){return dict.__len__(self)}
965
return it
966
}
967
968
var dict_keys = $B.make_view("dict_keys")
969
dict_keys.$iterator = $B.make_iterator_class("dict_keyiterator")
Nov 21, 2015
970
Mar 23, 2018
972
if(arguments.length > 1){
973
var _len = arguments.length - 1,
974
_msg = "keys() takes no arguments (" + _len + " given)"
975
throw _b_.TypeError.$factory(_msg)
Nov 21, 2015
976
}
977
var it = dict_keys.$factory(to_list(self, 0), true)
978
it.len_func = function(){return dict.__len__(self)}
979
return it
Nov 21, 2015
980
}
981
Feb 11, 2018
982
dict.pop = function(){
Nov 21, 2015
983
984
var missing = {},
985
$ = $B.args("pop", 3, {self: null, key: null, _default: null},
986
["self", "key", "_default"], arguments, {_default: missing}, null, null),
987
self = $.self,
988
key = $.key,
989
_default = $._default
Nov 21, 2015
990
Sep 5, 2014
991
try{
992
var res = dict.__getitem__(self, key)
993
dict.__delitem__(self, key)
Sep 5, 2014
994
return res
995
}catch(err){
996
if(err.__class__ === _b_.KeyError){
997
if(_default !== missing){return _default}
Sep 5, 2014
998
throw err
999
}
1000
throw err
1001
}
1002
}
1003
Feb 11, 2018
1004
dict.popitem = function(self){
1006
var itm = _b_.next(_b_.iter(dict.items(self)))
1007
dict.__delitem__(self, itm[0])
Feb 11, 2018
1008
return _b_.tuple.$factory(itm)
1010
if (err.__class__ == _b_.StopIteration) {
1011
throw _b_.KeyError.$factory("'popitem(): dictionary is empty'")
Sep 5, 2014
1014
}
1015
Feb 11, 2018
1016
dict.setdefault = function(){
Nov 21, 2015
1017
Mar 7, 2018
1018
var $ = $B.args("setdefault", 3, {self: null, key: null, _default: null},
1019
["self", "key", "_default"], arguments, {_default: $N}, null, null),
1020
self = $.self,
1021
key = $.key,
1022
_default = $._default
Nov 21, 2015
1023
1024
try{return dict.__getitem__(self, key)}
Sep 5, 2014
1025
catch(err){
1026
if(err.__class__ !== _b_.KeyError){
1027
throw err
1028
}
1029
if(_default === undefined){_default = $N}
1030
var hash = key.$hash
1031
key.$hash = undefined
1032
dict.$setitem(self, key, _default, hash)
Sep 5, 2014
1033
return _default
1034
}
1035
}
1036
Feb 11, 2018
1037
dict.update = function(self){
Nov 21, 2015
1038
Mar 7, 2018
1039
var $ = $B.args("update", 1, {"self": null}, ["self"], arguments,
1040
{}, "args", "kw"),
1041
self = $.self,
1042
args = $.args,
1043
kw = $.kw
1044
if(args.length > 0){
1045
var o = args[0]
1047
if(o.$jsobj){
1048
o = jsobj2dict(o.$jsobj)
1049
}
1051
}else if(_b_.hasattr(o, "keys")){
1052
var _keys = _b_.list.$factory($B.$call($B.$getattr(o, "keys"))())
1053
for(var i = 0, len = _keys.length; i < len; i++){
1054
var _value = getattr(o, "__getitem__")(_keys[i])
1055
dict.$setitem(self, _keys[i], _value)
1056
}
1057
}else{
1058
var it = _b_.iter(o),
1059
i = 0
1060
while(true){
1061
try{
1062
var item = _b_.next(it)
1063
}catch(err){
1064
if(err.__class__ === _b_.StopIteration){break}
1065
throw err
1066
}
1067
try{
1068
key_value = _b_.list.$factory(item)
1069
}catch(err){
1070
throw _b_.TypeError.$factory("cannot convert dictionary" +
1071
" update sequence element #" + i + " to a sequence")
1072
}
1073
if(key_value.length !== 2){
1074
throw _b_.ValueError.$factory("dictionary update " +
1075
"sequence element #" + i + " has length " +
1076
key_value.length + "; 2 is required")
1077
}
1078
dict.$setitem(self, key_value[0], key_value[1])
1079
i++
Sep 5, 2014
1082
}
Sep 5, 2014
1086
}
1087
1088
var dict_values = $B.make_view("dict_values")
1089
dict_values.$iterator = $B.make_iterator_class("dict_valueiterator")
Nov 21, 2015
1090
Feb 11, 2018
1091
dict.values = function(self){
Mar 23, 2018
1092
if(arguments.length > 1){
1093
var _len = arguments.length - 1,
1094
_msg = "values() takes no arguments (" + _len + " given)"
1095
throw _b_.TypeError.$factory(_msg)
Nov 21, 2015
1096
}
1097
var values = to_list(self, 1)
1098
var it = dict_values.$factory(to_list(self, 1), false)
1099
it.len_func = function(){return dict.__len__(self)}
1100
return it
Nov 21, 2015
1101
}
1102
1103
dict.$factory = function(){
1104
var res = dict.__new__(dict)
1105
var args = [res]
1106
for(var i = 0, len = arguments.length; i < len ; i++){
1107
args.push(arguments[i])
1108
}
1109
dict.__init__.apply(null, args)
Sep 5, 2014
1110
return res
1111
}
Sep 5, 2014
1113
_b_.dict = dict
Feb 11, 2018
1115
$B.set_func_names(dict, "builtins")
1116
1117
dict.__class_getitem__ = _b_.classmethod.$factory(dict.__class_getitem__)
1118
1119
$B.empty_dict = function(){
1120
return {
1121
__class__: dict,
1122
$numeric_dict : {},
1123
$object_dict : {},
1124
$string_dict : {},
1125
$str_hash: {},
1126
$version: 0,
1127
$order: 0
1131
// This must be done after set_func_names, otherwise dict.fromkeys doesn't
1132
// have the attribute $infos
1133
dict.fromkeys = _b_.classmethod.$factory(dict.fromkeys)
1134
1135
$B.getset_descriptor = $B.make_class("getset_descriptor",
1136
function(klass, attr){
1137
return {
1138
__class__: $B.getset_descriptor,
1139
__doc__: _b_.None,
1140
cls: klass,
1141
attr: attr
1142
}
1143
}
1144
)
1145
1146
$B.getset_descriptor.__repr__ = $B.getset_descriptor.__str__ = function(self){
1147
return `<attribute '${self.attr}' of '${self.cls.$infos.__name__}' objects>`
1148
}
1149
1150
$B.set_func_names($B.getset_descriptor, "builtins")
1151
1152
// Class for attribute __dict__ of classes
1153
var mappingproxy = $B.mappingproxy = $B.make_class("mappingproxy",
Feb 12, 2018
1154
function(obj){
1155
if(_b_.isinstance(obj, dict)){
1156
// obj is a dictionary, with $string_dict table such that
1157
// obj.$string_dict[key] = [value, rank]
1158
// Transform it into an object with attribute $jsobj such that
1159
// res.$jsobj[key] = value
1160
var res = $B.obj_dict(dict.$to_obj(obj))
1161
}else{
1162
var res = $B.obj_dict(obj)
1163
}
Feb 12, 2018
1164
res.__class__ = mappingproxy
1165
return res
1166
}
1167
)
Feb 12, 2018
1169
mappingproxy.__setitem__ = function(){
Mar 7, 2018
1170
throw _b_.TypeError.$factory("'mappingproxy' object does not support " +
1171
"item assignment")
1174
for(var attr in dict){
1175
if(mappingproxy[attr] !== undefined ||
1176
["__class__", "__mro__", "__new__", "__init__", "__delitem__",
1177
"clear", "fromkeys", "pop", "popitem", "setdefault",
1178
"update"].indexOf(attr) > -1){
1179
continue
1180
}
1181
if(typeof dict[attr] == "function"){
1182
mappingproxy[attr] = (function(key){
1183
return function(){
1184
return dict[key].apply(null, arguments)
1185
}
1186
})(attr)
1187
}else{
1188
mappingproxy[attr] = dict[attr]
1189
}
1190
}
1191
Feb 12, 2018
1192
$B.set_func_names(mappingproxy, "builtins")
Mar 7, 2018
1197
if(attr.charAt(0) != "$" && attr !== "__class__"){
1198
if(x[attr] === null){
1199
d.$string_dict[attr] = [_b_.None, d.$order++]
1200
}else if(x[attr] === undefined){
1201
continue
1202
}else if(x[attr].$jsobj === x){
1203
d.$string_dict[attr] = [d, d.$order++]
1205
d.$string_dict[attr] = [$B.$JS2Py(x[attr]), d.$order++]
1207
}
1208
}
1209
return d
1210
}
1212
$B.obj_dict = function(obj, from_js){
1213
var klass = obj.__class__ || $B.get_class(obj)
1214
if(klass !== undefined && klass.$native){
1215
throw _b_.AttributeError.$factory(klass.__name__ +
1216
" has no attribute '__dict__'")}
1218
res.$jsobj = obj
1219
res.$from_js = from_js // set to true if
1220
return res
1221
}
1222
Sep 5, 2014
1223
})(__BRYTHON__)