Skip to content
Permalink
Newer
Older
100644 1217 lines (1098 sloc) 35.7 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
switch(typeof item[0]) {
518
case 'string':
519
self.$string_dict[item[0]] = [item[1], self.$order++]
520
self.$str_hash[str_hash(item[0])] = item[0]
521
self.$version++
522
break
523
case 'number':
524
if(item[0] != 0 && item[0] != 1){
525
self.$numeric_dict[item[0]] = [item[1], self.$order++]
526
self.$version++
527
break
528
}
529
default:
530
si(self, item[0], item[1])
531
break
532
}
533
}
534
}
535
536
dict.__init__ = function(self, first, second){
538
if(first === undefined){return $N}
539
if(second === undefined){
540
if(first.$nat != 'kw' && $B.get_class(first) === $B.JSObj){
541
for(var key in first){
542
self.$string_dict[key] = [first[key], self.$order++]
543
}
544
return _b_.None
545
}else if(first.$jsobj){
546
self.$jsobj = {}
547
for(var attr in first.$jsobj){
548
self.$jsobj[attr] = first.$jsobj[attr]
551
}else if(Array.isArray(first)){
552
init_from_list(self, first)
553
return $N
Sep 5, 2014
554
}
557
$ = $ || $B.args("dict", 1, {self:null}, ["self"],
558
arguments, {}, "first", "second")
559
var args = $.first
560
if(args.length > 1){
561
throw _b_.TypeError.$factory("dict expected at most 1 argument" +
562
", got 2")
563
}else if(args.length == 1){
564
args = args[0]
565
if(args.__class__ === dict){
566
['$string_dict', '$str_hash', '$numeric_dict', '$object_dict'].
567
forEach(function(d){
568
for(key in args[d]){self[d][key] = args[d][key]}
569
})
570
}else if(_b_.isinstance(args, dict)){
573
var keys = $B.$getattr(args, "keys", null)
574
if(keys !== null){
575
var gi = $B.$getattr(args, "__getitem__", null)
576
if(gi !== null){
577
// has keys and __getitem__ : it's a mapping, iterate on
578
// keys and values
579
gi = $B.$call(gi)
580
var kiter = _b_.iter($B.$call(keys)())
581
while(true){
582
try{
583
var key = _b_.next(kiter),
584
value = gi(key)
585
dict.__setitem__(self, key, value)
586
}catch(err){
587
if(err.__class__ === _b_.StopIteration){
588
break
589
}
590
throw err
591
}
592
}
593
return $N
594
}
595
}
596
if(! Array.isArray(args)){
597
args = _b_.list.$factory(args)
598
}
599
// Form "dict([[key1, value1], [key2,value2], ...])"
600
init_from_list(self, args)
Sep 5, 2014
601
}
603
var kw = $.second.$string_dict
604
for(var attr in kw){
605
switch(typeof attr){
606
case "string":
607
self.$string_dict[attr] = [kw[attr][0], self.$order++]
608
self.$str_hash[str_hash(attr)] = attr
609
break
610
case "number":
611
self.$numeric_dict[attr] = [kw[attr][0], self.$order++]
614
si(self, attr, kw[attr][0])
Sep 5, 2014
619
}
620
Feb 11, 2018
621
dict.__iter__ = function(self) {
622
return _b_.iter(dict.$$keys(self))
Sep 5, 2014
623
}
624
625
dict.__ior__ = function(self, other){
626
// PEP 584
627
dict.update(self, other)
628
return self
629
}
630
Feb 11, 2018
631
dict.__len__ = function(self) {
634
if(self.$jsobj){
Mar 7, 2018
635
for(var attr in self.$jsobj){if(attr.charAt(0) != "$"){_count++}}
636
return _count
637
}
639
for(var k in self.$numeric_dict){_count++}
640
for(var k in self.$string_dict){_count++}
641
for(var hash in self.$object_dict){
642
_count += self.$object_dict[hash].length
643
}
Sep 5, 2014
647
Mar 7, 2018
648
dict.__ne__ = function(self, other){return ! dict.__eq__(self, other)}
Sep 5, 2014
649
Feb 11, 2018
650
dict.__new__ = function(cls){
651
if(cls === undefined){
Mar 7, 2018
652
throw _b_.TypeError.$factory("int.__new__(): not enough arguments")
654
var instance = {
656
$numeric_dict : {},
657
$object_dict : {},
660
$version: 0,
661
$order: 0
663
if(cls !== dict){
664
instance.__dict__ = $B.empty_dict()
665
}
666
return instance
669
dict.__or__ = function(self, other){
670
// PEP 584
671
if(! _b_.isinstance(other, dict)){
672
return _b_.NotImplemented
673
}
674
var res = dict.copy(self)
675
dict.update(res, other)
676
return res
677
}
678
Feb 11, 2018
679
dict.__repr__ = function(self){
680
if(self.$jsobj){ // wrapper around Javascript object
Feb 11, 2018
681
return dict.__repr__(jsobj2dict(self.$jsobj))
683
if($B.repr.enter(self)){
684
return "{...}"
685
}
686
var res = [],
688
items.forEach(function(item){
689
try{
690
res.push(repr(item[0]) + ": " + repr(item[1]))
691
}catch(err){
692
throw err
693
}
695
$B.repr.leave(self)
Mar 7, 2018
696
return "{" + res.join(", ") + "}"
Sep 5, 2014
697
}
698
699
dict.__ror__ = function(self, other){
700
// PEP 584
701
if(! _b_.isinstance(other, dict)){
702
return _b_.NotImplemented
703
}
704
var res = dict.copy(other)
705
dict.update(res, self)
706
return res
707
}
708
709
dict.__setitem__ = function(self, key, value){
Mar 7, 2018
710
var $ = $B.args("__setitem__", 3, {self: null, key: null, value: null},
711
["self", "key", "value"], arguments, {}, null, null)
712
return dict.$setitem($.self, $.key, $.value)
713
}
Nov 21, 2015
714
715
dict.$setitem = function(self, key, value, $hash){
716
// Set a dictionary item mapping key and value.
717
//
718
// If key is a string, set:
719
// - $string_dict[key] = [value, order] where "order" is an auto-increment
720
// unique id to keep track of insertion order
721
// - $str_hash[hash(key)] to key
722
//
723
// If key is a number, set $numeric_dict[key] = value
724
//
725
// If key is another object, compute its hash value:
726
// - if the hash is a key of $str_hash, and key == $str_hash[hash],
727
// replace $string_dict[$str_hash[hash]] by value
728
// - if the hash is a key of $numeric_dict, and hash == key, replace
729
// $numeric_dict[hash] by value
730
// - if the hash is a key of $object_dict: $object_dict[hash] is a list
731
// of [k, v] pairs. If key is equal to one of the "k", replace the
732
// matching v by value. Otherwise, add [key, value] to the list
733
// - else set $object_dict[hash] = [[key, value]]
734
//
735
// In all cases, increment attribute $version, used to detect dictionary
736
// changes during an iteration.
738
// Parameter $hash is only set if this method is called by setdefault.
739
// In this case the hash of key has already been computed and we
740
// know that the key is not present in the dictionary, so it's no
741
// use computing hash(key) again, nor testing equality of keys
743
if(self.$from_js){
744
// dictionary created by method to_dict of JSObj instances
745
value = $B.pyobj2jsobj(value)
746
}
747
if(self.$jsobj.__class__ === _b_.type){
748
self.$jsobj[key] = value
749
if(key == "__init__" || key == "__new__"){
750
// If class attribute __init__ or __new__ are reset,
751
// the factory function has to change
752
self.$jsobj.$factory = $B.$instance_creator(self.$jsobj)
753
}
754
}else{
755
self.$jsobj[key] = value
760
switch(typeof key){
761
case "string":
762
if(self.$string_dict === undefined){
763
console.log("pas de string dict", self, key, value)
764
}
765
if(self.$string_dict[key] !== undefined){
766
self.$string_dict[key][0] = value
767
}else{
768
self.$string_dict[key] = [value, self.$order++]
769
self.$str_hash[str_hash(key)] = key
770
self.$version++
771
}
772
return $N
773
case "number":
774
if(self.$numeric_dict[key] !== undefined){
775
// existing key: preserve order
776
self.$numeric_dict[key][0] = value
777
}else{
778
// special case for 0 and 1 if True or False are keys
779
var done = false
780
if((key == 0 || key == 1) &&
781
self.$object_dict[key] !== undefined){
782
for(const item of self.$object_dict[key]){
783
if((key == 0 && item[0] === false) ||
784
(key == 1 && item[0] === true)){
785
// replace value
786
item[1][0] = value
787
done = true
788
}
789
}
790
}
791
if(! done){
792
// new key
793
self.$numeric_dict[key] = [value, self.$order++]
794
}
797
return $N
798
case "boolean":
799
// true replaces 1 and false replaces 0
800
var num = key ? 1 : 0
801
if(self.$numeric_dict[num] !== undefined){
802
var order = self.$numeric_dict[num][1] // preserve order
803
self.$numeric_dict[num] = [value, order]
804
return
805
}
806
if(self.$object_dict[num] !== undefined){
807
self.$object_dict[num].push([key, [value, self.$order++]])
808
}else{
809
self.$object_dict[num] = [[key, [value, self.$order++]]]
810
}
813
// if we got here the key is more complex, use default method
814
815
var hash = $hash === undefined ? _b_.hash(key) : $hash,
816
_eq = function(other){return $B.rich_comp("__eq__", key, other)}
817
818
if(self.$numeric_dict[hash] !== undefined && _eq(hash)){
819
self.$numeric_dict[hash] = [value, self.$numeric_dict[hash][1]]
823
var sk = self.$str_hash[hash]
824
if(sk !== undefined && _eq(sk)){
825
self.$string_dict[sk] = [value, self.$string_dict[sk][1]]
830
// If $setitem is called from setdefault, don't test equality of key
831
// with any object
832
if($hash){
833
if(self.$object_dict[$hash] !== undefined){
834
self.$object_dict[$hash].push([key, [value, self.$order++]])
836
self.$object_dict[$hash] = [[key, [value, self.$order++]]]
837
}
838
self.$version++
839
return $N
840
}
841
var ix = rank(self, hash, key)
842
if(ix > -1){
843
// reset value
844
self.$object_dict[hash][ix][1] = [value,
845
self.$object_dict[hash][ix][1][1]]
846
return $N
847
}else if(self.$object_dict.hasOwnProperty(hash)){
848
self.$object_dict[hash].push([key, [value, self.$order++]])
850
self.$object_dict[hash] = [[key, [value, self.$order++]]]
Sep 5, 2014
854
}
855
856
dict.__str__ = function(){
857
return dict.__repr__.apply(null, arguments)
858
}
Sep 5, 2014
859
860
// add "reflected" methods
Feb 11, 2018
861
$B.make_rmethods(dict)
Sep 5, 2014
862
Feb 11, 2018
863
dict.clear = function(){
Sep 5, 2014
864
// Remove all items from the dictionary.
Mar 7, 2018
865
var $ = $B.args("clear", 1, {self: null}, ["self"], arguments, {},
866
null, null),
867
self = $.self
869
self.$numeric_dict = {}
870
self.$string_dict = {}
871
self.$str_hash = {}
872
self.$object_dict = {}
874
if(self.$jsobj){
875
for(var attr in self.$jsobj){
Mar 7, 2018
876
if(attr.charAt(0) !== "$" && attr !== "__class__"){
877
delete self.$jsobj[attr]
878
}
879
}
880
}
Sep 5, 2014
884
}
885
Feb 11, 2018
886
dict.copy = function(self){
Sep 5, 2014
887
// Return a shallow copy of the dictionary
Mar 7, 2018
888
var $ = $B.args("copy", 1, {self: null},["self"], arguments,{},
889
null, null),
890
self = $.self,
Sep 5, 2014
893
return res
894
}
895
Feb 11, 2018
896
dict.fromkeys = function(){
Nov 21, 2015
897
Mar 7, 2018
898
var $ = $B.args("fromkeys", 3, {cls: null, keys: null, value: null},
899
["cls", "keys", "value"], arguments, {value: _b_.None}, null, null),
900
keys = $.keys,
901
value = $.value
Sep 5, 2014
903
// class method
904
var klass = $.cls,
Sep 5, 2014
908
while(1){
909
try{
910
var key = _b_.next(keys_iter)
911
if(klass === dict){dict.$setitem(res, key, value)}
912
else{$B.$getattr(res, "__setitem__")(key, value)}
Sep 5, 2014
913
}catch(err){
914
if($B.is_exc(err, [_b_.StopIteration])){
Sep 5, 2014
915
return res
916
}
917
throw err
918
}
919
}
920
}
921
Feb 11, 2018
922
dict.get = function(){
Mar 7, 2018
923
var $ = $B.args("get", 3, {self: null, key: null, _default: null},
924
["self", "key", "_default"], arguments, {_default: $N}, null, null)
Feb 11, 2018
926
try{return dict.__getitem__($.self, $.key)}
927
catch(err){
928
if(_b_.isinstance(err, _b_.KeyError)){return $._default}
929
else{throw err}
930
}
931
}
932
933
var dict_items = $B.make_view("dict_items", true)
934
dict_items.$iterator = $B.make_iterator_class("dict_itemiterator")
935
Feb 11, 2018
936
dict.items = function(self){
Mar 23, 2018
937
if(arguments.length > 1){
938
var _len = arguments.length - 1,
939
_msg = "items() takes no arguments (" + _len + " given)"
940
throw _b_.TypeError.$factory(_msg)
941
}
942
var items = to_list(self),
943
set_like = true
944
// Check if all values are hashable
945
for(var i = 0, len = items.length; i < len; i++){
946
try{
947
_b_.hash(items[i][1])
948
}catch(err){
949
set_like = false
950
break
951
}
952
}
953
var values = to_list(self)
954
var it = dict_items.$factory(self, values, set_like)
955
it.dict_version = self.$version
957
}
958
960
var dict_keys = $B.make_view("dict_keys")
961
dict_keys.$iterator = $B.make_iterator_class("dict_keyiterator")
Nov 21, 2015
962
Mar 23, 2018
964
if(arguments.length > 1){
965
var _len = arguments.length - 1,
966
_msg = "keys() takes no arguments (" + _len + " given)"
967
throw _b_.TypeError.$factory(_msg)
Nov 21, 2015
968
}
969
var it = dict_keys.$factory(self, to_list(self, 0), true)
970
it.dict_version = self.$version
Nov 21, 2015
972
}
973
Feb 11, 2018
974
dict.pop = function(){
Nov 21, 2015
975
976
var missing = {},
977
$ = $B.args("pop", 3, {self: null, key: null, _default: null},
978
["self", "key", "_default"], arguments, {_default: missing}, null, null),
979
self = $.self,
980
key = $.key,
981
_default = $._default
Nov 21, 2015
982
Sep 5, 2014
983
try{
984
var res = dict.__getitem__(self, key)
985
dict.__delitem__(self, key)
Sep 5, 2014
986
return res
987
}catch(err){
988
if(err.__class__ === _b_.KeyError){
989
if(_default !== missing){return _default}
Sep 5, 2014
990
throw err
991
}
992
throw err
993
}
994
}
995
Feb 11, 2018
996
dict.popitem = function(self){
998
var itm = _b_.next(_b_.iter(dict.items(self)))
999
dict.__delitem__(self, itm[0])
Feb 11, 2018
1000
return _b_.tuple.$factory(itm)
1002
if (err.__class__ == _b_.StopIteration) {
1003
throw _b_.KeyError.$factory("'popitem(): dictionary is empty'")
Sep 5, 2014
1006
}
1007
Feb 11, 2018
1008
dict.setdefault = function(){
Nov 21, 2015
1009
Mar 7, 2018
1010
var $ = $B.args("setdefault", 3, {self: null, key: null, _default: null},
1011
["self", "key", "_default"], arguments, {_default: $N}, null, null),
1012
self = $.self,
1013
key = $.key,
1014
_default = $._default
1015
try{
1016
// Pass 3rd argument to dict.$getitem to avoid using __missing__
1017
// Cf. issue #1598
1018
return dict.$getitem(self, key, true)
1019
}catch(err){
1020
if(err.__class__ !== _b_.KeyError){
1021
throw err
1022
}
1023
if(_default === undefined){_default = $N}
1024
var hash = key.$hash
1025
key.$hash = undefined
1026
dict.$setitem(self, key, _default, hash)
Sep 5, 2014
1027
return _default
1028
}
1029
}
1030
Feb 11, 2018
1031
dict.update = function(self){
Nov 21, 2015
1032
Mar 7, 2018
1033
var $ = $B.args("update", 1, {"self": null}, ["self"], arguments,
1034
{}, "args", "kw"),
1035
self = $.self,
1036
args = $.args,
1037
kw = $.kw
1038
if(args.length > 0){
1039
var o = args[0]
1041
if(o.$jsobj){
1042
o = jsobj2dict(o.$jsobj)
1043
}
1045
}else if(_b_.hasattr(o, "keys")){
1046
var _keys = _b_.list.$factory($B.$call($B.$getattr(o, "keys"))())
1047
for(var i = 0, len = _keys.length; i < len; i++){
1048
var _value = getattr(o, "__getitem__")(_keys[i])
1049
dict.$setitem(self, _keys[i], _value)
1050
}
1051
}else{
1052
var it = _b_.iter(o),
1053
i = 0
1054
while(true){
1055
try{
1056
var item = _b_.next(it)
1057
}catch(err){
1058
if(err.__class__ === _b_.StopIteration){break}
1059
throw err
1060
}
1061
try{
1062
key_value = _b_.list.$factory(item)
1063
}catch(err){
1064
throw _b_.TypeError.$factory("cannot convert dictionary" +
1065
" update sequence element #" + i + " to a sequence")
1066
}
1067
if(key_value.length !== 2){
1068
throw _b_.ValueError.$factory("dictionary update " +
1069
"sequence element #" + i + " has length " +
1070
key_value.length + "; 2 is required")
1071
}
1072
dict.$setitem(self, key_value[0], key_value[1])
1073
i++
Sep 5, 2014
1076
}
Sep 5, 2014
1080
}
1081
1082
var dict_values = $B.make_view("dict_values")
1083
dict_values.$iterator = $B.make_iterator_class("dict_valueiterator")
Nov 21, 2015
1084
Feb 11, 2018
1085
dict.values = function(self){
Mar 23, 2018
1086
if(arguments.length > 1){
1087
var _len = arguments.length - 1,
1088
_msg = "values() takes no arguments (" + _len + " given)"
1089
throw _b_.TypeError.$factory(_msg)
Nov 21, 2015
1090
}
1091
var values = to_list(self, 1)
1092
var it = dict_values.$factory(self, values, false)
1093
it.dict_version = self.$version
Nov 21, 2015
1095
}
1096
1097
dict.$factory = function(){
1098
var res = dict.__new__(dict)
1099
var args = [res]
1100
for(var i = 0, len = arguments.length; i < len ; i++){
1101
args.push(arguments[i])
1102
}
1103
dict.__init__.apply(null, args)
Sep 5, 2014
1104
return res
1105
}
Sep 5, 2014
1107
_b_.dict = dict
Feb 11, 2018
1109
$B.set_func_names(dict, "builtins")
1110
1111
dict.__class_getitem__ = _b_.classmethod.$factory(dict.__class_getitem__)
1112
1113
$B.empty_dict = function(){
1114
return {
1115
__class__: dict,
1116
$numeric_dict : {},
1117
$object_dict : {},
1118
$string_dict : {},
1119
$str_hash: {},
1120
$version: 0,
1121
$order: 0
1125
// This must be done after set_func_names, otherwise dict.fromkeys doesn't
1126
// have the attribute $infos
1127
dict.fromkeys = _b_.classmethod.$factory(dict.fromkeys)
1128
1129
$B.getset_descriptor = $B.make_class("getset_descriptor",
1130
function(klass, attr){
1131
return {
1132
__class__: $B.getset_descriptor,
1133
__doc__: _b_.None,
1134
cls: klass,
1135
attr: attr
1136
}
1137
}
1138
)
1139
1140
$B.getset_descriptor.__repr__ = $B.getset_descriptor.__str__ = function(self){
1141
return `<attribute '${self.attr}' of '${self.cls.$infos.__name__}' objects>`
1142
}
1143
1144
$B.set_func_names($B.getset_descriptor, "builtins")
1145
1146
// Class for attribute __dict__ of classes
1147
var mappingproxy = $B.mappingproxy = $B.make_class("mappingproxy",
Feb 12, 2018
1148
function(obj){
1149
if(_b_.isinstance(obj, dict)){
1150
// obj is a dictionary, with $string_dict table such that
1151
// obj.$string_dict[key] = [value, rank]
1152
// Transform it into an object with attribute $jsobj such that
1153
// res.$jsobj[key] = value
1154
var res = $B.obj_dict(dict.$to_obj(obj))
1155
}else{
1156
var res = $B.obj_dict(obj)
1157
}
Feb 12, 2018
1158
res.__class__ = mappingproxy
1159
return res
1160
}
1161
)
Feb 12, 2018
1163
mappingproxy.__setitem__ = function(){
Mar 7, 2018
1164
throw _b_.TypeError.$factory("'mappingproxy' object does not support " +
1165
"item assignment")
1168
for(var attr in dict){
1169
if(mappingproxy[attr] !== undefined ||
1170
["__class__", "__mro__", "__new__", "__init__", "__delitem__",
1171
"clear", "fromkeys", "pop", "popitem", "setdefault",
1172
"update"].indexOf(attr) > -1){
1173
continue
1174
}
1175
if(typeof dict[attr] == "function"){
1176
mappingproxy[attr] = (function(key){
1177
return function(){
1178
return dict[key].apply(null, arguments)
1179
}
1180
})(attr)
1181
}else{
1182
mappingproxy[attr] = dict[attr]
1183
}
1184
}
1185
Feb 12, 2018
1186
$B.set_func_names(mappingproxy, "builtins")
Mar 7, 2018
1191
if(attr.charAt(0) != "$" && attr !== "__class__"){
1192
if(x[attr] === null){
1193
d.$string_dict[attr] = [_b_.None, d.$order++]
1194
}else if(x[attr] === undefined){
1195
continue
1196
}else if(x[attr].$jsobj === x){
1197
d.$string_dict[attr] = [d, d.$order++]
1199
d.$string_dict[attr] = [$B.$JS2Py(x[attr]), d.$order++]
1201
}
1202
}
1203
return d
1204
}
1206
$B.obj_dict = function(obj, from_js){
1207
var klass = obj.__class__ || $B.get_class(obj)
1208
if(klass !== undefined && klass.$native){
1209
throw _b_.AttributeError.$factory("'" + $B.class_name(obj) +
1210
"' object has no attribute '__dict__'")}
1212
res.$jsobj = obj
1213
res.$from_js = from_js // set to true if
1214
return res
1215
}
1216
Sep 5, 2014
1217
})(__BRYTHON__)