Skip to content
Permalink
Newer
Older
100644 1239 lines (1118 sloc) 36.3 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(d, items, set_like){
114
return {
115
__class__: klass,
120
len: items.length,
121
set_like: set_like
125
for(var i = 0, len = set_ops.length; i < len; i++){
126
var op = "__" + set_ops[i] + "__"
127
klass[op] = (function(op){
128
return function(self, other){
129
// compare set of items to other
130
if(self.set_like){
131
return _b_.set[op](_b_.set.$factory(self),
132
_b_.set.$factory(other))
133
}else{
134
// Non-set like views can only be compared to
135
// instances of the same class
136
if(other.__class__ !== klass){
137
return false
139
var other_items = _b_.list.$factory(other)
140
return dict_view_op[op](self.items, other_items)
146
klass.__iter__ = function(self){
147
var it = klass.$iterator.$factory(self.items)
148
it.test_change = function(){
149
return self.dict.$version != self.dict_version
150
}
153
154
klass.__len__ = function(self){
155
return self.len
156
}
158
klass.__repr__ = function(self){
159
return klass.$infos.__name__ + '(' + _b_.repr(self.items) + ')'
160
}
161
162
$B.set_func_names(klass, "builtins")
Feb 11, 2018
166
var dict = {
Feb 11, 2018
167
__class__: _b_.type,
169
$infos: {
170
__module__: "builtins",
171
__name__: "dict"
172
},
Feb 11, 2018
173
$is_class: true,
174
$native: true
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(){
Nov 21, 2015
279
280
var $ = $B.args("__contains__", 2, {self: null, key: null},
281
["self", "key"], arguments, {}, null, null),
282
self = $.self,
284
if(self.$is_namespace){key = $B.to_alias(key)} // issue 1244
285
286
if(self.$jsobj){
287
return self.$jsobj[key] !== undefined
288
}
290
switch(typeof key) {
292
return self.$string_dict[key] !== undefined
294
return self.$numeric_dict[key] !== undefined
295
}
296
297
var hash = _b_.hash(key)
298
if(self.$str_hash[hash] !== undefined &&
299
$B.rich_comp("__eq__", key, self.$str_hash[hash])){return true}
300
if(self.$numeric_dict[hash] !== undefined &&
301
$B.rich_comp("__eq__", key, hash)){return true}
302
return rank(self, hash, key) > -1
Sep 5, 2014
303
}
304
Feb 11, 2018
305
dict.__delitem__ = function(){
Nov 21, 2015
306
307
var $ = $B.args("__eq__", 2, {self: null, arg: null},
308
["self", "arg"], arguments, {}, null, null),
309
self = $.self,
Nov 21, 2015
311
312
if(self.$jsobj){
313
if(self.$jsobj[arg] === undefined){throw _b_.KeyError.$factory(arg)}
314
delete self.$jsobj[arg]
317
switch(typeof arg){
318
case "string":
319
if(self.$string_dict[arg] === undefined){
320
throw _b_.KeyError.$factory(_b_.str.$factory(arg))
321
}
322
delete self.$string_dict[arg]
323
delete self.$str_hash[str_hash(arg)]
325
return $N
326
case "number":
327
if(self.$numeric_dict[arg] === undefined){
328
throw _b_.KeyError.$factory(_b_.str.$factory(arg))
330
delete self.$numeric_dict[arg]
334
// go with defaults
335
336
var hash = _b_.hash(arg),
337
ix
339
if((ix = rank(self, hash, arg)) > -1){
340
self.$object_dict[hash].splice(ix, 1)
341
}else{
342
throw _b_.KeyError.$factory(_b_.str.$factory(arg))
Sep 5, 2014
347
}
348
Feb 11, 2018
349
dict.__eq__ = function(){
Mar 7, 2018
350
var $ = $B.args("__eq__", 2, {self: null, other: null},
351
["self", "other"], arguments, {}, null, null),
352
self = $.self,
353
other = $.other
355
if(! _b_.isinstance(other, dict)){return false}
357
if(self.$jsobj){self = jsobj2dict(self.$jsobj)}
358
if(other.$jsobj){other = jsobj2dict(other.$jsobj)}
359
if(dict.__len__(self) != dict.__len__(other)){
360
return false
361
}
363
if(self.$string_dict.length != other.$string_dict.length){
367
for(var k in self.$numeric_dict){
368
if(other.$numeric_dict.hasOwnProperty(k)){
369
if(!$B.rich_comp("__eq__", other.$numeric_dict[k][0],
370
self.$numeric_dict[k][0])){
371
return false
372
}
373
}else if(other.$object_dict.hasOwnProperty(k)){
374
var pairs = other.$object_dict[k],
375
flag = false
376
for(var i = 0, len = pairs.length; i < len; i++){
377
if($B.rich_comp("__eq__", k, pairs[i][0]) &&
378
$B.rich_comp("__eq__", self.$numeric_dict[k],
379
pairs[i][1])){
380
flag = true
381
break
382
}
384
if(! flag){return false}
Nov 21, 2015
387
}
388
}
389
for(var k in self.$string_dict){
390
if(!other.$string_dict.hasOwnProperty(k) ||
391
!$B.rich_comp("__eq__", other.$string_dict[k][0],
392
self.$string_dict[k][0])){
Nov 21, 2015
394
}
395
}
396
for(var hash in self.$object_dict){
397
var pairs = self.$object_dict[hash]
398
// Get all (key, value) pairs in other that have the same hash
399
var other_pairs = []
400
if(other.$numeric_dict[hash] !== undefined){
401
other_pairs.push([hash, other.$numeric_dict[hash]])
402
}
403
if(other.$object_dict[hash] !== undefined){
404
other_pairs = other_pairs.concat(other.$object_dict[hash])
405
}
406
if(other_pairs.length == 0){
407
return false
408
}
409
for(var i = 0, len_i = pairs.length; i < len_i; i++){
410
var flag = false
411
var key = pairs[i][0],
412
value = pairs[i][1][0]
413
for(var j = 0, len_j = other_pairs.length; j < len_j; j++){
414
if($B.rich_comp("__eq__", key, other_pairs[j][0]) &&
415
$B.rich_comp("__eq__", value, other_pairs[j][1][0])){
416
flag = true
417
break
423
}
424
}
425
return true
Sep 5, 2014
426
}
427
Feb 11, 2018
428
dict.__getitem__ = function(){
429
var $ = $B.args("__getitem__", 2, {self: null, arg: null},
430
["self", "arg"], arguments, {}, null, null),
431
self = $.self,
433
return dict.$getitem(self, arg)
434
}
435
436
$B.string_count = 0
437
$B.num_count = 0
438
dict.$getitem = function(self, arg, ignore_missing){
439
// ignore_missing is only set in 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
$B.string_count++
455
return x[0]
457
break
458
case "number":
459
if(self.$numeric_dict[arg] !== undefined){
461
return self.$numeric_dict[arg][0]
463
break
464
}
465
466
// since the key is more complex use 'default' method of getting item
467
468
var hash = _b_.hash(arg),
469
_eq = function(other){return $B.rich_comp("__eq__", arg, other)}
470
471
if(typeof arg == "object"){
472
arg.$hash = hash // cache for setdefault
473
}
474
var sk = self.$str_hash[hash]
475
if(sk !== undefined && _eq(sk)){
476
return self.$string_dict[sk][0]
478
if(self.$numeric_dict[hash] !== undefined && _eq(hash)){
479
return self.$numeric_dict[hash][0]
481
if(_b_.isinstance(arg, _b_.str)){
482
// string subclass
483
var res = self.$string_dict[arg.valueOf()]
484
if(res !== undefined){return res[0]}
487
var ix = rank(self, hash, arg)
488
if(ix > -1){
489
return self.$object_dict[hash][ix][1][0]
492
if(! ignore_missing){
493
if(self.__class__ !== dict && ! ignore_missing){
494
try{
495
var missing_method = getattr(self.__class__, "__missing__",
496
_b_.None)
497
}catch(err){
498
console.log(err)
500
}
501
if(missing_method !== _b_.None){
502
return missing_method(self, arg)
503
}
506
throw _b_.KeyError.$factory(arg)
Sep 5, 2014
507
}
508
509
dict.__hash__ = _b_.None
Sep 5, 2014
510
511
function init_from_list(self, args){
512
var i = -1,
513
stop = args.length - 1,
514
si = dict.__setitem__
515
while(i++ < stop){
516
var item = args[i]
517
if(item.length != 2){
518
throw _b_.ValueError.$factory("dictionary " +
519
`update sequence element #${i} has length 1; 2 is required`)
520
}
521
switch(typeof item[0]) {
522
case 'string':
523
self.$string_dict[item[0]] = [item[1], self.$order++]
524
self.$str_hash[str_hash(item[0])] = item[0]
525
self.$version++
526
break
527
case 'number':
528
if(item[0] != 0 && item[0] != 1){
529
self.$numeric_dict[item[0]] = [item[1], self.$order++]
530
self.$version++
531
break
532
}
533
default:
534
si(self, item[0], item[1])
535
break
536
}
537
}
538
}
539
540
dict.__init__ = function(self, first, second){
542
if(first === undefined){return $N}
543
if(second === undefined){
544
if(first.$nat != 'kw' && $B.get_class(first) === $B.JSObj){
545
for(var key in first){
546
self.$string_dict[key] = [first[key], self.$order++]
547
}
548
return _b_.None
549
}else if(first.$jsobj){
550
self.$jsobj = {}
551
for(var attr in first.$jsobj){
552
self.$jsobj[attr] = first.$jsobj[attr]
555
}else if(Array.isArray(first)){
556
init_from_list(self, first)
557
return $N
Sep 5, 2014
558
}
561
$ = $ || $B.args("dict", 1, {self:null}, ["self"],
562
arguments, {}, "first", "second")
563
var args = $.first
564
if(args.length > 1){
565
throw _b_.TypeError.$factory("dict expected at most 1 argument" +
566
", got 2")
567
}else if(args.length == 1){
568
args = args[0]
569
if(args.__class__ === dict){
570
['$string_dict', '$str_hash', '$numeric_dict', '$object_dict'].
571
forEach(function(d){
572
for(key in args[d]){self[d][key] = args[d][key]}
573
})
574
}else if(_b_.isinstance(args, dict)){
577
var keys = $B.$getattr(args, "keys", null)
578
if(keys !== null){
579
var gi = $B.$getattr(args, "__getitem__", null)
580
if(gi !== null){
581
// has keys and __getitem__ : it's a mapping, iterate on
582
// keys and values
583
gi = $B.$call(gi)
584
var kiter = _b_.iter($B.$call(keys)())
585
while(true){
586
try{
587
var key = _b_.next(kiter),
588
value = gi(key)
589
dict.__setitem__(self, key, value)
590
}catch(err){
591
if(err.__class__ === _b_.StopIteration){
592
break
593
}
594
throw err
595
}
596
}
597
return $N
598
}
599
}
600
if(! Array.isArray(args)){
601
args = _b_.list.$factory(args)
602
}
603
// Form "dict([[key1, value1], [key2,value2], ...])"
604
init_from_list(self, args)
Sep 5, 2014
605
}
607
var kw = $.second.$string_dict
608
for(var attr in kw){
609
switch(typeof attr){
610
case "string":
611
self.$string_dict[attr] = [kw[attr][0], self.$order++]
612
self.$str_hash[str_hash(attr)] = attr
613
break
614
case "number":
615
self.$numeric_dict[attr] = [kw[attr][0], self.$order++]
618
si(self, attr, kw[attr][0])
Sep 5, 2014
623
}
624
Feb 11, 2018
625
dict.__iter__ = function(self) {
626
return _b_.iter(dict.$$keys(self))
Sep 5, 2014
627
}
628
629
dict.__ior__ = function(self, other){
630
// PEP 584
631
dict.update(self, other)
632
return self
633
}
634
Feb 11, 2018
635
dict.__len__ = function(self) {
638
if(self.$jsobj){
Mar 7, 2018
639
for(var attr in self.$jsobj){if(attr.charAt(0) != "$"){_count++}}
640
return _count
641
}
643
for(var k in self.$numeric_dict){_count++}
644
for(var k in self.$string_dict){_count++}
645
for(var hash in self.$object_dict){
646
_count += self.$object_dict[hash].length
647
}
Sep 5, 2014
651
Mar 7, 2018
652
dict.__ne__ = function(self, other){return ! dict.__eq__(self, other)}
Sep 5, 2014
653
Feb 11, 2018
654
dict.__new__ = function(cls){
655
if(cls === undefined){
Mar 7, 2018
656
throw _b_.TypeError.$factory("int.__new__(): not enough arguments")
658
var instance = {
660
$numeric_dict : {},
661
$object_dict : {},
664
$version: 0,
665
$order: 0
667
if(cls !== dict){
668
instance.__dict__ = $B.empty_dict()
669
}
670
return instance
673
dict.__or__ = function(self, other){
674
// PEP 584
675
if(! _b_.isinstance(other, dict)){
676
return _b_.NotImplemented
677
}
678
var res = dict.copy(self)
679
dict.update(res, other)
680
return res
681
}
682
683
function __newobj__(){
684
// __newobj__ is called with a generator as only argument
685
var $ = $B.args('__newobj__', 0, {}, [], arguments, {}, 'args', null),
686
args = $.args
687
var res = $B.empty_dict()
688
res.__class__ = args[0]
689
return res
690
}
691
692
dict.__reduce_ex__ = function(self, protocol){
693
return $B.fast_tuple([
694
__newobj__,
695
$B.fast_tuple([self.__class__]),
696
_b_.None,
697
_b_.None,
698
dict.items(self)])
699
}
700
Feb 11, 2018
701
dict.__repr__ = function(self){
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){
711
try{
712
res.push(repr(item[0]) + ": " + 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
782
switch(typeof key){
783
case "string":
784
if(self.$string_dict === undefined){
785
console.log("pas de string dict", self, key, value)
786
}
787
if(self.$string_dict[key] !== undefined){
788
self.$string_dict[key][0] = value
789
}else{
790
self.$string_dict[key] = [value, self.$order++]
791
self.$str_hash[str_hash(key)] = key
792
self.$version++
793
}
794
return $N
795
case "number":
796
if(self.$numeric_dict[key] !== undefined){
797
// existing key: preserve order
798
self.$numeric_dict[key][0] = value
799
}else{
800
// special case for 0 and 1 if True or False are keys
801
var done = false
802
if((key == 0 || key == 1) &&
803
self.$object_dict[key] !== undefined){
804
for(const item of self.$object_dict[key]){
805
if((key == 0 && item[0] === false) ||
806
(key == 1 && item[0] === true)){
807
// replace value
808
item[1][0] = value
809
done = true
810
}
811
}
812
}
813
if(! done){
814
// new key
815
self.$numeric_dict[key] = [value, self.$order++]
816
}
819
return $N
820
case "boolean":
821
// true replaces 1 and false replaces 0
822
var num = key ? 1 : 0
823
if(self.$numeric_dict[num] !== undefined){
824
var order = self.$numeric_dict[num][1] // preserve order
825
self.$numeric_dict[num] = [value, order]
826
return
827
}
828
if(self.$object_dict[num] !== undefined){
829
self.$object_dict[num].push([key, [value, self.$order++]])
830
}else{
831
self.$object_dict[num] = [[key, [value, self.$order++]]]
832
}
835
// if we got here the key is more complex, use default method
836
837
var hash = $hash === undefined ? _b_.hash(key) : $hash,
838
_eq = function(other){return $B.rich_comp("__eq__", key, other)}
839
840
if(self.$numeric_dict[hash] !== undefined && _eq(hash)){
841
self.$numeric_dict[hash] = [value, self.$numeric_dict[hash][1]]
845
var sk = self.$str_hash[hash]
846
if(sk !== undefined && _eq(sk)){
847
self.$string_dict[sk] = [value, self.$string_dict[sk][1]]
852
// If $setitem is called from setdefault, don't test equality of key
853
// with any object
854
if($hash){
855
if(self.$object_dict[$hash] !== undefined){
856
self.$object_dict[$hash].push([key, [value, self.$order++]])
858
self.$object_dict[$hash] = [[key, [value, self.$order++]]]
859
}
860
self.$version++
861
return $N
862
}
863
var ix = rank(self, hash, key)
864
if(ix > -1){
865
// reset value
866
self.$object_dict[hash][ix][1] = [value,
867
self.$object_dict[hash][ix][1][1]]
868
return $N
869
}else if(self.$object_dict.hasOwnProperty(hash)){
870
self.$object_dict[hash].push([key, [value, self.$order++]])
872
self.$object_dict[hash] = [[key, [value, self.$order++]]]
Sep 5, 2014
876
}
877
878
dict.__str__ = function(){
879
return dict.__repr__.apply(null, arguments)
880
}
Sep 5, 2014
881
882
// add "reflected" methods
Feb 11, 2018
883
$B.make_rmethods(dict)
Sep 5, 2014
884
Feb 11, 2018
885
dict.clear = function(){
Sep 5, 2014
886
// Remove all items from the dictionary.
Mar 7, 2018
887
var $ = $B.args("clear", 1, {self: null}, ["self"], arguments, {},
888
null, null),
889
self = $.self
891
self.$numeric_dict = {}
892
self.$string_dict = {}
893
self.$str_hash = {}
894
self.$object_dict = {}
896
if(self.$jsobj){
897
for(var attr in self.$jsobj){
Mar 7, 2018
898
if(attr.charAt(0) !== "$" && attr !== "__class__"){
899
delete self.$jsobj[attr]
900
}
901
}
902
}
Sep 5, 2014
906
}
907
Feb 11, 2018
908
dict.copy = function(self){
Sep 5, 2014
909
// Return a shallow copy of the dictionary
Mar 7, 2018
910
var $ = $B.args("copy", 1, {self: null},["self"], arguments,{},
911
null, null),
912
self = $.self,
Sep 5, 2014
915
return res
916
}
917
Feb 11, 2018
918
dict.fromkeys = function(){
Nov 21, 2015
919
Mar 7, 2018
920
var $ = $B.args("fromkeys", 3, {cls: null, keys: null, value: null},
921
["cls", "keys", "value"], arguments, {value: _b_.None}, null, null),
922
keys = $.keys,
923
value = $.value
Sep 5, 2014
925
// class method
926
var klass = $.cls,
Sep 5, 2014
930
while(1){
931
try{
932
var key = _b_.next(keys_iter)
933
if(klass === dict){dict.$setitem(res, key, value)}
934
else{$B.$getattr(res, "__setitem__")(key, value)}
Sep 5, 2014
935
}catch(err){
936
if($B.is_exc(err, [_b_.StopIteration])){
Sep 5, 2014
937
return res
938
}
939
throw err
940
}
941
}
942
}
943
Feb 11, 2018
944
dict.get = function(){
Mar 7, 2018
945
var $ = $B.args("get", 3, {self: null, key: null, _default: null},
946
["self", "key", "_default"], arguments, {_default: $N}, null, null)
Feb 11, 2018
948
try{return dict.__getitem__($.self, $.key)}
949
catch(err){
950
if(_b_.isinstance(err, _b_.KeyError)){return $._default}
951
else{throw err}
952
}
953
}
954
955
var dict_items = $B.make_view("dict_items", true)
956
dict_items.$iterator = $B.make_iterator_class("dict_itemiterator")
957
Feb 11, 2018
958
dict.items = function(self){
Mar 23, 2018
959
if(arguments.length > 1){
960
var _len = arguments.length - 1,
961
_msg = "items() takes no arguments (" + _len + " given)"
962
throw _b_.TypeError.$factory(_msg)
963
}
964
var items = to_list(self),
965
set_like = true
966
// Check if all values are hashable
967
for(var i = 0, len = items.length; i < len; i++){
968
try{
969
_b_.hash(items[i][1])
970
}catch(err){
971
set_like = false
972
break
973
}
974
}
975
var values = to_list(self)
976
var it = dict_items.$factory(self, values, set_like)
977
it.dict_version = self.$version
979
}
980
982
var dict_keys = $B.make_view("dict_keys")
983
dict_keys.$iterator = $B.make_iterator_class("dict_keyiterator")
Nov 21, 2015
984
Mar 23, 2018
986
if(arguments.length > 1){
987
var _len = arguments.length - 1,
988
_msg = "keys() takes no arguments (" + _len + " given)"
989
throw _b_.TypeError.$factory(_msg)
Nov 21, 2015
990
}
991
var it = dict_keys.$factory(self, to_list(self, 0), true)
992
it.dict_version = self.$version
Nov 21, 2015
994
}
995
Feb 11, 2018
996
dict.pop = function(){
Nov 21, 2015
997
998
var missing = {},
999
$ = $B.args("pop", 3, {self: null, key: null, _default: null},
1000
["self", "key", "_default"], arguments, {_default: missing}, null, null),
1001
self = $.self,
1002
key = $.key,
1003
_default = $._default
Nov 21, 2015
1004
Sep 5, 2014
1005
try{
1006
var res = dict.__getitem__(self, key)
1007
dict.__delitem__(self, key)
Sep 5, 2014
1008
return res
1009
}catch(err){
1010
if(err.__class__ === _b_.KeyError){
1011
if(_default !== missing){return _default}
Sep 5, 2014
1012
throw err
1013
}
1014
throw err
1015
}
1016
}
1017
Feb 11, 2018
1018
dict.popitem = function(self){
1020
var itm = _b_.next(_b_.iter(dict.items(self)))
1021
dict.__delitem__(self, itm[0])
Feb 11, 2018
1022
return _b_.tuple.$factory(itm)
1024
if (err.__class__ == _b_.StopIteration) {
1025
throw _b_.KeyError.$factory("'popitem(): dictionary is empty'")
Sep 5, 2014
1028
}
1029
Feb 11, 2018
1030
dict.setdefault = function(){
Nov 21, 2015
1031
Mar 7, 2018
1032
var $ = $B.args("setdefault", 3, {self: null, key: null, _default: null},
1033
["self", "key", "_default"], arguments, {_default: $N}, null, null),
1034
self = $.self,
1035
key = $.key,
1036
_default = $._default
1037
try{
1038
// Pass 3rd argument to dict.$getitem to avoid using __missing__
1039
// Cf. issue #1598
1040
return dict.$getitem(self, key, true)
1041
}catch(err){
1042
if(err.__class__ !== _b_.KeyError){
1043
throw err
1044
}
1045
if(_default === undefined){_default = $N}
1046
var hash = key.$hash
1047
key.$hash = undefined
1048
dict.$setitem(self, key, _default, hash)
Sep 5, 2014
1049
return _default
1050
}
1051
}
1052
Feb 11, 2018
1053
dict.update = function(self){
Nov 21, 2015
1054
Mar 7, 2018
1055
var $ = $B.args("update", 1, {"self": null}, ["self"], arguments,
1056
{}, "args", "kw"),
1057
self = $.self,
1058
args = $.args,
1059
kw = $.kw
1060
if(args.length > 0){
1061
var o = args[0]
1063
if(o.$jsobj){
1064
o = jsobj2dict(o.$jsobj)
1065
}
1067
}else if(_b_.hasattr(o, "keys")){
1068
var _keys = _b_.list.$factory($B.$call($B.$getattr(o, "keys"))())
1069
for(var i = 0, len = _keys.length; i < len; i++){
1070
var _value = getattr(o, "__getitem__")(_keys[i])
1071
dict.$setitem(self, _keys[i], _value)
1072
}
1073
}else{
1074
var it = _b_.iter(o),
1075
i = 0
1076
while(true){
1077
try{
1078
var item = _b_.next(it)
1079
}catch(err){
1080
if(err.__class__ === _b_.StopIteration){break}
1081
throw err
1082
}
1083
try{
1084
key_value = _b_.list.$factory(item)
1085
}catch(err){
1086
throw _b_.TypeError.$factory("cannot convert dictionary" +
1087
" update sequence element #" + i + " to a sequence")
1088
}
1089
if(key_value.length !== 2){
1090
throw _b_.ValueError.$factory("dictionary update " +
1091
"sequence element #" + i + " has length " +
1092
key_value.length + "; 2 is required")
1093
}
1094
dict.$setitem(self, key_value[0], key_value[1])
1095
i++
Sep 5, 2014
1098
}
Sep 5, 2014
1102
}
1103
1104
var dict_values = $B.make_view("dict_values")
1105
dict_values.$iterator = $B.make_iterator_class("dict_valueiterator")
Nov 21, 2015
1106
Feb 11, 2018
1107
dict.values = function(self){
Mar 23, 2018
1108
if(arguments.length > 1){
1109
var _len = arguments.length - 1,
1110
_msg = "values() takes no arguments (" + _len + " given)"
1111
throw _b_.TypeError.$factory(_msg)
Nov 21, 2015
1112
}
1113
var values = to_list(self, 1)
1114
var it = dict_values.$factory(self, values, false)
1115
it.dict_version = self.$version
Nov 21, 2015
1117
}
1118
1119
dict.$factory = function(){
1120
var res = dict.__new__(dict)
1121
var args = [res]
1122
for(var i = 0, len = arguments.length; i < len ; i++){
1123
args.push(arguments[i])
1124
}
1125
dict.__init__.apply(null, args)
Sep 5, 2014
1126
return res
1127
}
Sep 5, 2014
1129
_b_.dict = dict
Feb 11, 2018
1131
$B.set_func_names(dict, "builtins")
1132
1133
dict.__class_getitem__ = _b_.classmethod.$factory(dict.__class_getitem__)
1134
1135
$B.empty_dict = function(){
1136
return {
1137
__class__: dict,
1138
$numeric_dict : {},
1139
$object_dict : {},
1140
$string_dict : {},
1141
$str_hash: {},
1142
$version: 0,
1143
$order: 0
1147
// This must be done after set_func_names, otherwise dict.fromkeys doesn't
1148
// have the attribute $infos
1149
dict.fromkeys = _b_.classmethod.$factory(dict.fromkeys)
1150
1151
$B.getset_descriptor = $B.make_class("getset_descriptor",
1152
function(klass, attr){
1153
return {
1154
__class__: $B.getset_descriptor,
1155
__doc__: _b_.None,
1156
cls: klass,
1157
attr: attr
1158
}
1159
}
1160
)
1161
1162
$B.getset_descriptor.__repr__ = $B.getset_descriptor.__str__ = function(self){
1163
return `<attribute '${self.attr}' of '${self.cls.$infos.__name__}' objects>`
1164
}
1165
1166
$B.set_func_names($B.getset_descriptor, "builtins")
1167
1168
// Class for attribute __dict__ of classes
1169
var mappingproxy = $B.mappingproxy = $B.make_class("mappingproxy",
Feb 12, 2018
1170
function(obj){
1171
if(_b_.isinstance(obj, dict)){
1172
// obj is a dictionary, with $string_dict table such that
1173
// obj.$string_dict[key] = [value, rank]
1174
// Transform it into an object with attribute $jsobj such that
1175
// res.$jsobj[key] = value
1176
var res = $B.obj_dict(dict.$to_obj(obj))
1177
}else{
1178
var res = $B.obj_dict(obj)
1179
}
Feb 12, 2018
1180
res.__class__ = mappingproxy
1181
return res
1182
}
1183
)
Feb 12, 2018
1185
mappingproxy.__setitem__ = function(){
Mar 7, 2018
1186
throw _b_.TypeError.$factory("'mappingproxy' object does not support " +
1187
"item assignment")
1190
for(var attr in dict){
1191
if(mappingproxy[attr] !== undefined ||
1192
["__class__", "__mro__", "__new__", "__init__", "__delitem__",
1193
"clear", "fromkeys", "pop", "popitem", "setdefault",
1194
"update"].indexOf(attr) > -1){
1195
continue
1196
}
1197
if(typeof dict[attr] == "function"){
1198
mappingproxy[attr] = (function(key){
1199
return function(){
1200
return dict[key].apply(null, arguments)
1201
}
1202
})(attr)
1203
}else{
1204
mappingproxy[attr] = dict[attr]
1205
}
1206
}
1207
Feb 12, 2018
1208
$B.set_func_names(mappingproxy, "builtins")
Mar 7, 2018
1213
if(attr.charAt(0) != "$" && attr !== "__class__"){
1214
if(x[attr] === null){
1215
d.$string_dict[attr] = [_b_.None, d.$order++]
1216
}else if(x[attr] === undefined){
1217
continue
1218
}else if(x[attr].$jsobj === x){
1219
d.$string_dict[attr] = [d, d.$order++]
1221
d.$string_dict[attr] = [$B.$JS2Py(x[attr]), d.$order++]
1223
}
1224
}
1225
return d
1226
}
1228
$B.obj_dict = function(obj, from_js){
1229
var klass = obj.__class__ || $B.get_class(obj)
1230
if(klass !== undefined && klass.$native){
1231
throw _b_.AttributeError.$factory("'" + $B.class_name(obj) +
1232
"' object has no attribute '__dict__'")}
1234
res.$jsobj = obj
1235
res.$from_js = from_js // set to true if
1236
return res
1237
}
1238
Sep 5, 2014
1239
})(__BRYTHON__)