Skip to content
Permalink
Newer
Older
100644 1242 lines (1122 sloc) 36.4 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 _b_ = $B.builtins
30
var str_hash = _b_.str.__hash__,
Sep 5, 2014
32
33
var set_ops = ["eq", "le", "lt", "ge", "gt",
34
"sub", "rsub", "and", "or", "xor"]
35
36
// methods to compare non set-like views
37
function is_sublist(t1, t2){
38
// Return true if all elements of t1 are in t2
39
for(var i = 0, ilen = t1.length; i < ilen; i++){
40
var x = t1[i],
41
flag = false
42
for(var j = 0, jlen = t2.length; j < jlen; j++){
43
if($B.rich_comp("__eq__", x, t2[j])){
44
t2.splice(j, 1)
45
flag = true
46
break
47
}
48
}
49
if(! flag){
50
return false
51
}
52
}
53
return true
54
}
55
56
dict_view_op = {
57
__eq__: function(t1, t2){
58
return t1.length == t2.length && is_sublist(t1, t2)
59
},
60
__ne__: function(t1, t2){
61
return ! dict_view_op.__eq__(t1, t2)
62
},
63
__lt__: function(t1, t2){
64
return t1.length < t2.length && is_sublist(t1, t2)
65
},
66
__gt__: function(t1, t2){
67
return dict_view_op.__lt__(t2, t1)
68
},
69
__le__: function(t1, t2){
70
return t1.length <= t2.length && is_sublist(t1, t2)
71
},
72
__ge__: function(t1, t2){
73
return dict_view_op.__le__(t2, t1)
74
},
75
__and__: function(t1, t2){
76
var items = []
77
for(var i = 0, ilen = t1.length; i < ilen; i++){
78
var x = t1[i]
79
flag = false
80
for(var j = 0, jlen = t2.length; j < jlen; j++){
81
if($B.rich_comp("__eq__", x, t2[j])){
82
t2.splice(j, 1)
83
items.push(x)
84
break
85
}
86
}
87
}
88
return items
89
},
90
__or__: function(t1, t2){
91
var items = t1
92
for(var j = 0, jlen = t2.length; j < jlen; j++){
93
var y = t2[j],
94
flag = false
95
for(var i = 0, ilen = t1.length; i < ilen; i++){
96
if($B.rich_comp("__eq__", y, t1[i])){
97
t2.splice(j, 1)
98
flag = true
99
break
100
}
101
}
102
if(! flag){
103
items.push(y)
104
}
105
}
106
return items
107
}
109
}
110
111
$B.make_view = function(name){
112
var klass = $B.make_class(name, function(d, items, set_like){
113
return {
114
__class__: klass,
119
len: items.length,
120
set_like: set_like
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
138
var other_items = _b_.list.$factory(other)
139
return dict_view_op[op](self.items, other_items)
145
klass.__iter__ = function(self){
146
var it = klass.$iterator.$factory(self.items)
147
it.test_change = function(){
148
return self.dict.$version != self.dict_version
149
}
152
153
klass.__len__ = function(self){
154
return self.len
155
}
157
klass.__repr__ = function(self){
158
return klass.$infos.__name__ + '(' + _b_.repr(self.items) + ')'
159
}
160
161
$B.set_func_names(klass, "builtins")
Feb 11, 2018
165
var dict = {
Feb 11, 2018
166
__class__: _b_.type,
168
$infos: {
169
__module__: "builtins",
170
__name__: "dict"
171
},
Feb 11, 2018
172
$is_class: true,
173
$native: true,
174
$match_mapping_pattern: true // for pattern matching (PEP 634)
Sep 5, 2014
175
}
176
177
dict.$to_obj = function(d){
178
// Function applied to dictionary that only have string keys,
179
// return a Javascript objects with the kays mapped to the value,
180
// excluding the insertion rank
181
var res = {}
182
for(var key in d.$string_dict){
183
res[key] = d.$string_dict[key][0]
184
}
185
return res
186
}
187
188
function to_list(d, ix){
189
var items = [],
190
item
192
if(d.$jsobj){
Mar 7, 2018
195
if(attr.charAt(0) != "$"){
196
var val = d.$jsobj[attr]
197
if(val === undefined){val = _b_.NotImplemented}
198
else if(val === null){val = $N}
202
}else if(_b_.isinstance(d, _b_.dict)){
203
for(var k in d.$numeric_dict){
204
items.push([parseFloat(k), d.$numeric_dict[k]])
205
}
207
for(var k in d.$string_dict){
208
items.push([k, d.$string_dict[k]])
209
}
211
for(var k in d.$object_dict){
212
d.$object_dict[k].forEach(function(item){
213
items.push(item)
214
})
215
}
217
// sort by insertion order
218
items.sort(function(a, b){
219
return a[1][1] - b[1][1]
220
})
221
items = items.map(function(item){return [item[0], item[1][0]]})
224
res = items.map(function(item){return item[ix]})
225
return res
226
}else{
227
items.__class__ = _b_.tuple
228
return items.map(function(item){
229
item.__class__ = _b_.tuple; return item}
230
)
231
}
Feb 9, 2015
233
234
$B.dict_to_list = to_list // used in py_types.js
235
236
var $copy_dict = function(left, right){
238
si = dict.$setitem
239
right.$version = right.$version || 0
240
var right_version = right.$version || 0
241
for(var i = 0, len = _l.length; i < len; i++){
242
si(left, _l[i][0], _l[i][1])
243
if(right.$version != right_version){
244
throw _b_.RuntimeError.$factory("dict mutated during update")
245
}
246
}
249
function rank(self, hash, key){
250
// Search if object key, with hash = hash(key), is in
251
// self.$object_dict
252
var pairs = self.$object_dict[hash]
253
if(pairs !== undefined){
254
for(var i = 0, len = pairs.length; i < len; i++){
255
if($B.rich_comp("__eq__", key, pairs[i][0])){
256
return i
257
}
258
}
259
}
260
return -1
261
}
262
Feb 11, 2018
263
dict.__bool__ = function () {
Mar 7, 2018
264
var $ = $B.args("__bool__", 1, {self: null}, ["self"],
265
arguments, {}, null, null)
Feb 11, 2018
266
return dict.__len__($.self) > 0
269
dict.__class_getitem__ = function(cls, item){
270
// PEP 585
271
// Set as a classmethod at the end of this script, after $B.set_func_names()
272
if(! Array.isArray(item)){
273
item = [item]
274
}
275
return $B.GenericAlias.$factory(cls, item)
276
}
277
Feb 11, 2018
278
dict.__contains__ = function(){
279
var $ = $B.args("__contains__", 2, {self: null, key: null},
280
["self", "key"], arguments, {}, null, null),
281
self = $.self,
284
if(self.$jsobj){
285
return self.$jsobj[key] !== undefined
286
}
288
switch(typeof key) {
290
return self.$string_dict[key] !== undefined
292
return self.$numeric_dict[key] !== undefined
293
}
294
295
var hash = _b_.hash(key)
296
if(self.$str_hash[hash] !== undefined &&
297
$B.rich_comp("__eq__", key, self.$str_hash[hash])){
298
return true
299
}
300
if(self.$numeric_dict[hash] !== undefined &&
301
$B.rich_comp("__eq__", key, hash)){
302
return true
303
}
304
return rank(self, hash, key) > -1
Sep 5, 2014
305
}
306
Feb 11, 2018
307
dict.__delitem__ = function(){
Nov 21, 2015
308
309
var $ = $B.args("__eq__", 2, {self: null, arg: null},
310
["self", "arg"], arguments, {}, null, null),
311
self = $.self,
Nov 21, 2015
313
314
if(self.$jsobj){
315
if(self.$jsobj[arg] === undefined){throw _b_.KeyError.$factory(arg)}
316
delete self.$jsobj[arg]
319
switch(typeof arg){
320
case "string":
321
if(self.$string_dict[arg] === undefined){
322
throw _b_.KeyError.$factory(_b_.str.$factory(arg))
323
}
324
delete self.$string_dict[arg]
325
delete self.$str_hash[str_hash(arg)]
327
return $N
328
case "number":
329
if(self.$numeric_dict[arg] === undefined){
330
throw _b_.KeyError.$factory(_b_.str.$factory(arg))
332
delete self.$numeric_dict[arg]
336
// go with defaults
337
338
var hash = _b_.hash(arg),
339
ix
341
if((ix = rank(self, hash, arg)) > -1){
342
self.$object_dict[hash].splice(ix, 1)
343
}else{
344
throw _b_.KeyError.$factory(_b_.str.$factory(arg))
Sep 5, 2014
349
}
350
Feb 11, 2018
351
dict.__eq__ = function(){
Mar 7, 2018
352
var $ = $B.args("__eq__", 2, {self: null, other: null},
353
["self", "other"], arguments, {}, null, null),
354
self = $.self,
355
other = $.other
357
if(! _b_.isinstance(other, dict)){return false}
359
if(self.$jsobj){self = jsobj2dict(self.$jsobj)}
360
if(other.$jsobj){other = jsobj2dict(other.$jsobj)}
361
if(dict.__len__(self) != dict.__len__(other)){
362
return false
363
}
365
if(self.$string_dict.length != other.$string_dict.length){
369
for(var k in self.$numeric_dict){
370
if(other.$numeric_dict.hasOwnProperty(k)){
371
if(!$B.rich_comp("__eq__", other.$numeric_dict[k][0],
372
self.$numeric_dict[k][0])){
373
return false
374
}
375
}else if(other.$object_dict.hasOwnProperty(k)){
376
var pairs = other.$object_dict[k],
377
flag = false
378
for(var i = 0, len = pairs.length; i < len; i++){
379
if($B.rich_comp("__eq__", k, pairs[i][0]) &&
380
$B.rich_comp("__eq__", self.$numeric_dict[k],
381
pairs[i][1])){
382
flag = true
383
break
384
}
386
if(! flag){return false}
Nov 21, 2015
389
}
390
}
391
for(var k in self.$string_dict){
392
if(!other.$string_dict.hasOwnProperty(k) ||
393
!$B.rich_comp("__eq__", other.$string_dict[k][0],
394
self.$string_dict[k][0])){
Nov 21, 2015
396
}
397
}
398
for(var hash in self.$object_dict){
399
var pairs = self.$object_dict[hash]
400
// Get all (key, value) pairs in other that have the same hash
401
var other_pairs = []
402
if(other.$numeric_dict[hash] !== undefined){
403
other_pairs.push([hash, other.$numeric_dict[hash]])
404
}
405
if(other.$object_dict[hash] !== undefined){
406
other_pairs = other_pairs.concat(other.$object_dict[hash])
407
}
408
if(other_pairs.length == 0){
409
return false
410
}
411
for(var i = 0, len_i = pairs.length; i < len_i; i++){
412
var flag = false
413
var key = pairs[i][0],
414
value = pairs[i][1][0]
415
for(var j = 0, len_j = other_pairs.length; j < len_j; j++){
416
if($B.rich_comp("__eq__", key, other_pairs[j][0]) &&
417
$B.rich_comp("__eq__", value, other_pairs[j][1][0])){
418
flag = true
419
break
425
}
426
}
427
return true
Sep 5, 2014
428
}
429
Feb 11, 2018
430
dict.__getitem__ = function(){
431
var $ = $B.args("__getitem__", 2, {self: null, arg: null},
432
["self", "arg"], arguments, {}, null, null),
433
self = $.self,
435
return dict.$getitem(self, arg)
436
}
437
438
dict.$getitem = function(self, arg, ignore_missing){
439
// ignore_missing is set in dict.get and dict.setdefault
440
if(self.$jsobj){
441
if(self.$jsobj[arg] === undefined){
442
if(self.$jsobj.hasOwnProperty(arg)){
444
}
445
throw _b_.KeyError.$factory(arg)
446
}
447
return self.$jsobj[arg]
449
450
switch(typeof arg){
451
case "string":
452
var x = self.$string_dict[arg]
453
if(x !== undefined){
454
return x[0]
456
break
457
case "number":
458
if(self.$numeric_dict[arg] !== undefined){
459
return self.$numeric_dict[arg][0]
461
break
462
}
463
464
// since the key is more complex use 'default' method of getting item
465
466
var hash = _b_.hash(arg),
467
_eq = function(other){return $B.rich_comp("__eq__", arg, other)}
468
469
if(typeof arg == "object"){
470
arg.$hash = hash // cache for setdefault
471
}
472
var sk = self.$str_hash[hash]
473
if(sk !== undefined && _eq(sk)){
474
return self.$string_dict[sk][0]
476
if(self.$numeric_dict[hash] !== undefined && _eq(hash)){
477
return self.$numeric_dict[hash][0]
479
if(_b_.isinstance(arg, _b_.str)){
480
// string subclass
481
var res = self.$string_dict[arg.valueOf()]
482
if(res !== undefined){return res[0]}
485
var ix = rank(self, hash, arg)
486
if(ix > -1){
487
return self.$object_dict[hash][ix][1][0]
490
if(! ignore_missing){
491
if(self.__class__ !== dict && ! ignore_missing){
492
try{
493
var missing_method = $B.$getattr(self.__class__,
494
"__missing__", _b_.None)
495
}catch(err){
496
console.log(err)
498
}
499
if(missing_method !== _b_.None){
500
return missing_method(self, arg)
501
}
504
throw _b_.KeyError.$factory(arg)
Sep 5, 2014
505
}
506
507
dict.__hash__ = _b_.None
Sep 5, 2014
508
509
function init_from_list(self, args){
510
var i = -1,
511
stop = args.length - 1,
512
si = dict.__setitem__
513
while(i++ < stop){
514
var item = args[i]
515
if(item.length != 2){
516
throw _b_.ValueError.$factory("dictionary " +
517
`update sequence element #${i} has length 1; 2 is required`)
518
}
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){
539
if(first === undefined){
540
return $N
541
}
543
if(first.$nat != 'kw' && $B.get_class(first) === $B.JSObj){
544
for(var key in first){
545
self.$string_dict[key] = [first[key], self.$order++]
546
}
547
return _b_.None
548
}else if(first.$jsobj){
549
self.$jsobj = {}
550
for(var attr in first.$jsobj){
551
self.$jsobj[attr] = first.$jsobj[attr]
554
}else if(Array.isArray(first)){
555
init_from_list(self, first)
556
return $N
Sep 5, 2014
557
}
560
var $ = $B.args("dict", 1, {self:null}, ["self"],
561
arguments, {}, "first", "second")
562
var args = $.first
563
if(args.length > 1){
564
throw _b_.TypeError.$factory("dict expected at most 1 argument" +
565
", got 2")
566
}else if(args.length == 1){
567
args = args[0]
568
if(args.__class__ === dict){
569
['$string_dict', '$str_hash', '$numeric_dict', '$object_dict'].
570
forEach(function(d){
571
for(key in args[d]){self[d][key] = args[d][key]}
572
})
573
}else if(_b_.isinstance(args, dict)){
576
var keys = $B.$getattr(args, "keys", null)
577
if(keys !== null){
578
var gi = $B.$getattr(args, "__getitem__", null)
579
if(gi !== null){
580
// has keys and __getitem__ : it's a mapping, iterate on
581
// keys and values
582
gi = $B.$call(gi)
583
var kiter = _b_.iter($B.$call(keys)())
584
while(true){
585
try{
586
var key = _b_.next(kiter),
587
value = gi(key)
588
dict.__setitem__(self, key, value)
589
}catch(err){
590
if(err.__class__ === _b_.StopIteration){
591
break
592
}
593
throw err
594
}
595
}
596
return $N
597
}
598
}
599
if(! Array.isArray(args)){
600
args = _b_.list.$factory(args)
601
}
602
// Form "dict([[key1, value1], [key2,value2], ...])"
603
init_from_list(self, args)
Sep 5, 2014
604
}
606
var kw = $.second.$string_dict
607
for(var attr in kw){
608
switch(typeof attr){
609
case "string":
610
self.$string_dict[attr] = [kw[attr][0], self.$order++]
611
self.$str_hash[str_hash(attr)] = attr
612
break
613
case "number":
614
self.$numeric_dict[attr] = [kw[attr][0], self.$order++]
617
si(self, attr, kw[attr][0])
Sep 5, 2014
622
}
623
624
dict.__iter__ = function(self){
625
return _b_.iter(dict.keys(self))
Sep 5, 2014
626
}
627
628
dict.__ior__ = function(self, other){
629
// PEP 584
630
dict.update(self, other)
631
return self
632
}
633
Feb 11, 2018
634
dict.__len__ = function(self) {
637
if(self.$jsobj){
Mar 7, 2018
638
for(var attr in self.$jsobj){if(attr.charAt(0) != "$"){_count++}}
639
return _count
640
}
642
for(var k in self.$numeric_dict){_count++}
643
for(var k in self.$string_dict){_count++}
644
for(var hash in self.$object_dict){
645
_count += self.$object_dict[hash].length
646
}
Sep 5, 2014
650
Mar 7, 2018
651
dict.__ne__ = function(self, other){return ! dict.__eq__(self, other)}
Sep 5, 2014
652
Feb 11, 2018
653
dict.__new__ = function(cls){
654
if(cls === undefined){
Mar 7, 2018
655
throw _b_.TypeError.$factory("int.__new__(): not enough arguments")
657
var instance = {
659
$numeric_dict : {},
660
$object_dict : {},
663
$version: 0,
664
$order: 0
666
if(cls !== dict){
667
instance.__dict__ = $B.empty_dict()
668
}
669
return instance
672
dict.__or__ = function(self, other){
673
// PEP 584
674
if(! _b_.isinstance(other, dict)){
675
return _b_.NotImplemented
676
}
677
var res = dict.copy(self)
678
dict.update(res, other)
679
return res
680
}
681
682
function __newobj__(){
683
// __newobj__ is called with a generator as only argument
684
var $ = $B.args('__newobj__', 0, {}, [], arguments, {}, 'args', null),
685
args = $.args
686
var res = $B.empty_dict()
687
res.__class__ = args[0]
688
return res
689
}
690
691
dict.__reduce_ex__ = function(self, protocol){
692
return $B.fast_tuple([
693
__newobj__,
694
$B.fast_tuple([self.__class__]),
695
_b_.None,
696
_b_.None,
697
dict.items(self)])
698
}
699
Feb 11, 2018
700
dict.__repr__ = function(self){
701
$B.builtins_repr_check(dict, arguments) // in brython_builtins.js
702
if(self.$jsobj){ // wrapper around Javascript object
Feb 11, 2018
703
return dict.__repr__(jsobj2dict(self.$jsobj))
705
if($B.repr.enter(self)){
706
return "{...}"
707
}
708
var res = [],
710
items.forEach(function(item){
712
res.push(_b_.repr(item[0]) + ": " + _b_.repr(item[1]))
713
}catch(err){
714
throw err
715
}
717
$B.repr.leave(self)
Mar 7, 2018
718
return "{" + res.join(", ") + "}"
Sep 5, 2014
719
}
720
721
dict.__ror__ = function(self, other){
722
// PEP 584
723
if(! _b_.isinstance(other, dict)){
724
return _b_.NotImplemented
725
}
726
var res = dict.copy(other)
727
dict.update(res, self)
728
return res
729
}
730
731
dict.__setitem__ = function(self, key, value){
Mar 7, 2018
732
var $ = $B.args("__setitem__", 3, {self: null, key: null, value: null},
733
["self", "key", "value"], arguments, {}, null, null)
734
return dict.$setitem($.self, $.key, $.value)
735
}
Nov 21, 2015
736
737
dict.$setitem = function(self, key, value, $hash){
738
// Set a dictionary item mapping key and value.
739
//
740
// If key is a string, set:
741
// - $string_dict[key] = [value, order] where "order" is an auto-increment
742
// unique id to keep track of insertion order
743
// - $str_hash[hash(key)] to key
744
//
745
// If key is a number, set $numeric_dict[key] = value
746
//
747
// If key is another object, compute its hash value:
748
// - if the hash is a key of $str_hash, and key == $str_hash[hash],
749
// replace $string_dict[$str_hash[hash]] by value
750
// - if the hash is a key of $numeric_dict, and hash == key, replace
751
// $numeric_dict[hash] by value
752
// - if the hash is a key of $object_dict: $object_dict[hash] is a list
753
// of [k, v] pairs. If key is equal to one of the "k", replace the
754
// matching v by value. Otherwise, add [key, value] to the list
755
// - else set $object_dict[hash] = [[key, value]]
756
//
757
// In all cases, increment attribute $version, used to detect dictionary
758
// changes during an iteration.
760
// Parameter $hash is only set if this method is called by setdefault.
761
// In this case the hash of key has already been computed and we
762
// know that the key is not present in the dictionary, so it's no
763
// use computing hash(key) again, nor testing equality of keys
765
if(self.$from_js){
766
// dictionary created by method to_dict of JSObj instances
767
value = $B.pyobj2jsobj(value)
768
}
769
if(self.$jsobj.__class__ === _b_.type){
770
self.$jsobj[key] = value
771
if(key == "__init__" || key == "__new__"){
772
// If class attribute __init__ or __new__ are reset,
773
// the factory function has to change
774
self.$jsobj.$factory = $B.$instance_creator(self.$jsobj)
775
}
776
}else{
777
self.$jsobj[key] = value
781
if(key instanceof String){
782
key = key.valueOf()
783
}
785
switch(typeof key){
786
case "string":
787
if(self.$string_dict === undefined){
788
console.log("pas de string dict", self, key, value)
789
}
790
if(self.$string_dict[key] !== undefined){
791
self.$string_dict[key][0] = value
792
}else{
793
self.$string_dict[key] = [value, self.$order++]
794
self.$str_hash[str_hash(key)] = key
795
self.$version++
796
}
797
return $N
798
case "number":
799
if(self.$numeric_dict[key] !== undefined){
800
// existing key: preserve order
801
self.$numeric_dict[key][0] = value
802
}else{
803
// special case for 0 and 1 if True or False are keys
804
var done = false
805
if((key == 0 || key == 1) &&
806
self.$object_dict[key] !== undefined){
807
for(const item of self.$object_dict[key]){
808
if((key == 0 && item[0] === false) ||
809
(key == 1 && item[0] === true)){
810
// replace value
811
item[1][0] = value
812
done = true
813
}
814
}
815
}
816
if(! done){
817
// new key
818
self.$numeric_dict[key] = [value, self.$order++]
819
}
822
return $N
823
case "boolean":
824
// true replaces 1 and false replaces 0
825
var num = key ? 1 : 0
826
if(self.$numeric_dict[num] !== undefined){
827
var order = self.$numeric_dict[num][1] // preserve order
828
self.$numeric_dict[num] = [value, order]
829
return
830
}
831
if(self.$object_dict[num] !== undefined){
832
self.$object_dict[num].push([key, [value, self.$order++]])
833
}else{
834
self.$object_dict[num] = [[key, [value, self.$order++]]]
835
}
838
// if we got here the key is more complex, use default method
839
840
var hash = $hash === undefined ? _b_.hash(key) : $hash,
841
_eq = function(other){return $B.rich_comp("__eq__", key, other)}
842
843
if(self.$numeric_dict[hash] !== undefined && _eq(hash)){
844
self.$numeric_dict[hash] = [value, self.$numeric_dict[hash][1]]
848
var sk = self.$str_hash[hash]
849
if(sk !== undefined && _eq(sk)){
850
self.$string_dict[sk] = [value, self.$string_dict[sk][1]]
855
// If $setitem is called from setdefault, don't test equality of key
856
// with any object
857
if($hash){
858
if(self.$object_dict[$hash] !== undefined){
859
self.$object_dict[$hash].push([key, [value, self.$order++]])
861
self.$object_dict[$hash] = [[key, [value, self.$order++]]]
862
}
863
self.$version++
864
return $N
865
}
866
var ix = rank(self, hash, key)
867
if(ix > -1){
868
// reset value
869
self.$object_dict[hash][ix][1] = [value,
870
self.$object_dict[hash][ix][1][1]]
871
return $N
872
}else if(self.$object_dict.hasOwnProperty(hash)){
873
self.$object_dict[hash].push([key, [value, self.$order++]])
875
self.$object_dict[hash] = [[key, [value, self.$order++]]]
Sep 5, 2014
879
}
880
881
// add "reflected" methods
Feb 11, 2018
882
$B.make_rmethods(dict)
Sep 5, 2014
883
Feb 11, 2018
884
dict.clear = function(){
Sep 5, 2014
885
// Remove all items from the dictionary.
Mar 7, 2018
886
var $ = $B.args("clear", 1, {self: null}, ["self"], arguments, {},
887
null, null),
888
self = $.self
890
self.$numeric_dict = {}
891
self.$string_dict = {}
892
self.$str_hash = {}
893
self.$object_dict = {}
895
if(self.$jsobj){
896
for(var attr in self.$jsobj){
Mar 7, 2018
897
if(attr.charAt(0) !== "$" && attr !== "__class__"){
898
delete self.$jsobj[attr]
899
}
900
}
901
}
Sep 5, 2014
905
}
906
Feb 11, 2018
907
dict.copy = function(self){
Sep 5, 2014
908
// Return a shallow copy of the dictionary
Mar 7, 2018
909
var $ = $B.args("copy", 1, {self: null},["self"], arguments,{},
910
null, null),
911
self = $.self,
Sep 5, 2014
914
return res
915
}
916
Feb 11, 2018
917
dict.fromkeys = function(){
Nov 21, 2015
918
Mar 7, 2018
919
var $ = $B.args("fromkeys", 3, {cls: null, keys: null, value: null},
920
["cls", "keys", "value"], arguments, {value: _b_.None}, null, null),
921
keys = $.keys,
922
value = $.value
Sep 5, 2014
924
// class method
925
var klass = $.cls,
Sep 5, 2014
929
while(1){
930
try{
931
var key = _b_.next(keys_iter)
932
if(klass === dict){dict.$setitem(res, key, value)}
933
else{$B.$getattr(res, "__setitem__")(key, value)}
Sep 5, 2014
934
}catch(err){
935
if($B.is_exc(err, [_b_.StopIteration])){
Sep 5, 2014
936
return res
937
}
938
throw err
939
}
940
}
941
}
942
Feb 11, 2018
943
dict.get = function(){
Mar 7, 2018
944
var $ = $B.args("get", 3, {self: null, key: null, _default: null},
945
["self", "key", "_default"], arguments, {_default: $N}, null, null)
947
try{
948
// call $getitem with ignore_missign set to true
949
return dict.$getitem($.self, $.key, true)
950
}catch(err){
951
if(_b_.isinstance(err, _b_.KeyError)){return $._default}
952
else{throw err}
953
}
954
}
955
956
var dict_items = $B.make_view("dict_items", true)
957
dict_items.$iterator = $B.make_iterator_class("dict_itemiterator")
958
Feb 11, 2018
959
dict.items = function(self){
Mar 23, 2018
960
if(arguments.length > 1){
961
var _len = arguments.length - 1,
962
_msg = "items() takes no arguments (" + _len + " given)"
963
throw _b_.TypeError.$factory(_msg)
964
}
965
var items = to_list(self),
966
set_like = true
967
// Check if all values are hashable
968
for(var i = 0, len = items.length; i < len; i++){
969
try{
970
_b_.hash(items[i][1])
971
}catch(err){
972
set_like = false
973
break
974
}
975
}
976
var values = to_list(self)
977
var it = dict_items.$factory(self, values, set_like)
978
it.dict_version = self.$version
980
}
981
983
var dict_keys = $B.make_view("dict_keys")
984
dict_keys.$iterator = $B.make_iterator_class("dict_keyiterator")
Nov 21, 2015
985
986
dict.keys = function(self){
Mar 23, 2018
987
if(arguments.length > 1){
988
var _len = arguments.length - 1,
989
_msg = "keys() takes no arguments (" + _len + " given)"
990
throw _b_.TypeError.$factory(_msg)
Nov 21, 2015
991
}
992
var it = dict_keys.$factory(self, to_list(self, 0), true)
993
it.dict_version = self.$version
Nov 21, 2015
995
}
996
Feb 11, 2018
997
dict.pop = function(){
Nov 21, 2015
998
999
var missing = {},
1000
$ = $B.args("pop", 3, {self: null, key: null, _default: null},
1001
["self", "key", "_default"], arguments, {_default: missing}, null, null),
1002
self = $.self,
1003
key = $.key,
1004
_default = $._default
Nov 21, 2015
1005
Sep 5, 2014
1006
try{
1007
var res = dict.__getitem__(self, key)
1008
dict.__delitem__(self, key)
Sep 5, 2014
1009
return res
1010
}catch(err){
1011
if(err.__class__ === _b_.KeyError){
1012
if(_default !== missing){return _default}
Sep 5, 2014
1013
throw err
1014
}
1015
throw err
1016
}
1017
}
1018
Feb 11, 2018
1019
dict.popitem = function(self){
1021
var itm = _b_.next(_b_.iter(dict.items(self)))
1022
dict.__delitem__(self, itm[0])
Feb 11, 2018
1023
return _b_.tuple.$factory(itm)
1025
if (err.__class__ == _b_.StopIteration) {
1026
throw _b_.KeyError.$factory("'popitem(): dictionary is empty'")
Sep 5, 2014
1029
}
1030
Feb 11, 2018
1031
dict.setdefault = function(){
Nov 21, 2015
1032
Mar 7, 2018
1033
var $ = $B.args("setdefault", 3, {self: null, key: null, _default: null},
1034
["self", "key", "_default"], arguments, {_default: $N}, null, null),
1035
self = $.self,
1036
key = $.key,
1037
_default = $._default
1038
try{
1039
// Pass 3rd argument to dict.$getitem to avoid using __missing__
1040
// Cf. issue #1598
1041
return dict.$getitem(self, key, true)
1042
}catch(err){
1043
if(err.__class__ !== _b_.KeyError){
1044
throw err
1045
}
1046
if(_default === undefined){_default = $N}
1047
var hash = key.$hash
1048
key.$hash = undefined
1049
dict.$setitem(self, key, _default, hash)
Sep 5, 2014
1050
return _default
1051
}
1052
}
1053
Feb 11, 2018
1054
dict.update = function(self){
Nov 21, 2015
1055
Mar 7, 2018
1056
var $ = $B.args("update", 1, {"self": null}, ["self"], arguments,
1057
{}, "args", "kw"),
1058
self = $.self,
1059
args = $.args,
1060
kw = $.kw
1061
if(args.length > 0){
1062
var o = args[0]
1064
if(o.$jsobj){
1065
o = jsobj2dict(o.$jsobj)
1066
}
1068
}else if(_b_.hasattr(o, "keys")){
1069
var _keys = _b_.list.$factory($B.$call($B.$getattr(o, "keys"))())
1070
for(var i = 0, len = _keys.length; i < len; i++){
1071
var _value = $B.$getattr(o, "__getitem__")(_keys[i])
1072
dict.$setitem(self, _keys[i], _value)
1073
}
1074
}else{
1075
var it = _b_.iter(o),
1076
i = 0
1077
while(true){
1078
try{
1079
var item = _b_.next(it)
1080
}catch(err){
1081
if(err.__class__ === _b_.StopIteration){break}
1082
throw err
1083
}
1084
try{
1085
key_value = _b_.list.$factory(item)
1086
}catch(err){
1087
throw _b_.TypeError.$factory("cannot convert dictionary" +
1088
" update sequence element #" + i + " to a sequence")
1089
}
1090
if(key_value.length !== 2){
1091
throw _b_.ValueError.$factory("dictionary update " +
1092
"sequence element #" + i + " has length " +
1093
key_value.length + "; 2 is required")
1094
}
1095
dict.$setitem(self, key_value[0], key_value[1])
1096
i++
Sep 5, 2014
1099
}
Sep 5, 2014
1103
}
1104
1105
var dict_values = $B.make_view("dict_values")
1106
dict_values.$iterator = $B.make_iterator_class("dict_valueiterator")
Nov 21, 2015
1107
Feb 11, 2018
1108
dict.values = function(self){
Mar 23, 2018
1109
if(arguments.length > 1){
1110
var _len = arguments.length - 1,
1111
_msg = "values() takes no arguments (" + _len + " given)"
1112
throw _b_.TypeError.$factory(_msg)
Nov 21, 2015
1113
}
1114
var values = to_list(self, 1)
1115
var it = dict_values.$factory(self, values, false)
1116
it.dict_version = self.$version
Nov 21, 2015
1118
}
1119
1120
dict.$factory = function(){
1121
var res = dict.__new__(dict)
1122
var args = [res]
1123
for(var i = 0, len = arguments.length; i < len ; i++){
1124
args.push(arguments[i])
1125
}
1126
dict.__init__.apply(null, args)
Sep 5, 2014
1127
return res
1128
}
Sep 5, 2014
1130
_b_.dict = dict
Feb 11, 2018
1132
$B.set_func_names(dict, "builtins")
1133
1134
dict.__class_getitem__ = _b_.classmethod.$factory(dict.__class_getitem__)
1135
1136
$B.empty_dict = function(){
1137
return {
1138
__class__: dict,
1139
$numeric_dict : {},
1140
$object_dict : {},
1141
$string_dict : {},
1142
$str_hash: {},
1143
$version: 0,
1144
$order: 0
1148
// This must be done after set_func_names, otherwise dict.fromkeys doesn't
1149
// have the attribute $infos
1150
dict.fromkeys = _b_.classmethod.$factory(dict.fromkeys)
1151
1152
$B.getset_descriptor = $B.make_class("getset_descriptor",
1153
function(klass, attr){
1154
return {
1155
__class__: $B.getset_descriptor,
1156
__doc__: _b_.None,
1157
cls: klass,
1158
attr: attr
1159
}
1160
}
1161
)
1162
1163
$B.getset_descriptor.__repr__ = $B.getset_descriptor.__str__ = function(self){
1164
return `<attribute '${self.attr}' of '${self.cls.$infos.__name__}' objects>`
1165
}
1166
1167
$B.set_func_names($B.getset_descriptor, "builtins")
1168
1169
// Class for attribute __dict__ of classes
1170
var mappingproxy = $B.mappingproxy = $B.make_class("mappingproxy",
Feb 12, 2018
1171
function(obj){
1172
if(_b_.isinstance(obj, dict)){
1173
// obj is a dictionary, with $string_dict table such that
1174
// obj.$string_dict[key] = [value, rank]
1175
// Transform it into an object with attribute $jsobj such that
1176
// res.$jsobj[key] = value
1177
var res = $B.obj_dict(dict.$to_obj(obj))
1178
}else{
1179
var res = $B.obj_dict(obj)
1180
}
Feb 12, 2018
1181
res.__class__ = mappingproxy
1182
return res
1183
}
1184
)
1186
mappingproxy.$match_mapping_pattern = true // for pattern matching (PEP 634)
1187
Feb 12, 2018
1188
mappingproxy.__setitem__ = function(){
Mar 7, 2018
1189
throw _b_.TypeError.$factory("'mappingproxy' object does not support " +
1190
"item assignment")
1193
for(var attr in dict){
1194
if(mappingproxy[attr] !== undefined ||
1195
["__class__", "__mro__", "__new__", "__init__", "__delitem__",
1196
"clear", "fromkeys", "pop", "popitem", "setdefault",
1197
"update"].indexOf(attr) > -1){
1198
continue
1199
}
1200
if(typeof dict[attr] == "function"){
1201
mappingproxy[attr] = (function(key){
1202
return function(){
1203
return dict[key].apply(null, arguments)
1204
}
1205
})(attr)
1206
}else{
1207
mappingproxy[attr] = dict[attr]
1208
}
1209
}
1210
Feb 12, 2018
1211
$B.set_func_names(mappingproxy, "builtins")
Mar 7, 2018
1216
if(attr.charAt(0) != "$" && attr !== "__class__"){
1217
if(x[attr] === null){
1218
d.$string_dict[attr] = [_b_.None, d.$order++]
1219
}else if(x[attr] === undefined){
1220
continue
1221
}else if(x[attr].$jsobj === x){
1222
d.$string_dict[attr] = [d, d.$order++]
1224
d.$string_dict[attr] = [$B.$JS2Py(x[attr]), d.$order++]
1226
}
1227
}
1228
return d
1229
}
1231
$B.obj_dict = function(obj, from_js){
1232
var klass = obj.__class__ || $B.get_class(obj)
1233
if(klass !== undefined && klass.$native){
1234
throw _b_.AttributeError.$factory("'" + $B.class_name(obj) +
1235
"' object has no attribute '__dict__'")}
1237
res.$jsobj = obj
1238
res.$from_js = from_js // set to true if
1239
return res
1240
}
1241
Sep 5, 2014
1242
})(__BRYTHON__)