Permalink
Feb 1, 2020
Jul 21, 2020
Dec 28, 2020
Dec 28, 2020
Dec 28, 2020
May 17, 2019
Feb 1, 2020
Jan 15, 2018
Apr 3, 2019
Apr 3, 2019
Feb 1, 2020
Apr 3, 2019
Dec 13, 2018
Oct 5, 2020
Dec 10, 2018
Dec 10, 2018
Mar 7, 2018
Feb 26, 2018
Feb 1, 2020
Dec 10, 2018
Dec 10, 2018
Jan 29, 2021
Jul 30, 2020
Jul 14, 2020
Jul 31, 2018
Jul 31, 2018
Dec 10, 2018
Nov 2, 2018
Jul 31, 2018
Jun 11, 2020
Dec 10, 2018
Jun 11, 2020
Jun 11, 2020
May 27, 2018
Apr 18, 2020
Feb 1, 2020
Feb 3, 2018
Feb 1, 2020
Jul 4, 2020
Jul 4, 2020
Jul 30, 2020
Jul 30, 2020
Mar 7, 2018
Mar 7, 2018
Jul 24, 2021
Nov 9, 2015
May 17, 2019
Jul 21, 2020
Dec 28, 2020
Dec 28, 2020
Dec 13, 2018
Mar 7, 2018
Jan 29, 2021
Mar 7, 2018
Feb 26, 2018
Apr 14, 2019
Dec 13, 2018
May 17, 2019
Dec 28, 2020
Dec 1, 2018
Jun 29, 2020
Jun 28, 2018
May 16, 2020
May 16, 2020
Feb 1, 2020
Mar 7, 2018
Aug 2, 2018
Newer
100644
1397 lines (1259 sloc)
40.4 KB
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
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
}
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)
147
it.test_change = function(){
148
return self.dict.$version != self.dict_version
149
}
157
klass.__repr__ = function(self){
158
return klass.$infos.__name__ + '(' + _b_.repr(self.items) + ')'
159
}
160
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
198
if(val === undefined){val = _b_.NotImplemented}
199
else if(val === null){val = $N}
204
for(var k in d.$numeric_dict){
205
items.push([parseFloat(k), d.$numeric_dict[k]])
206
}
212
for(var k in d.$object_dict){
213
d.$object_dict[k].forEach(function(item){
214
items.push(item)
215
})
216
}
218
// sort by insertion order
219
items.sort(function(a, b){
220
return a[1][1] - b[1][1]
221
})
222
items = items.map(function(item){return [item[0], item[1][0]]})
227
}else{
228
items.__class__ = _b_.tuple
229
return items.map(function(item){
230
item.__class__ = _b_.tuple; return item}
231
)
232
}
243
si(left, _l[i][0], _l[i][1])
244
if(right.$version != right_version){
245
throw _b_.RuntimeError.$factory("dict mutated during update")
246
}
247
}
250
function rank(self, hash, key){
251
// Search if object key, with hash = hash(key), is in
252
// self.$object_dict
253
var pairs = self.$object_dict[hash]
254
if(pairs !== undefined){
255
for(var i = 0, len = pairs.length; i < len; i++){
256
if($B.rich_comp("__eq__", key, pairs[i][0])){
257
return i
258
}
259
}
260
}
261
return -1
262
}
263
270
dict.__class_getitem__ = function(cls, item){
271
// PEP 585
272
// Set as a classmethod at the end of this script, after $B.set_func_names()
273
if(! Array.isArray(item)){
274
item = [item]
275
}
276
return $B.GenericAlias.$factory(cls, item)
277
}
278
280
var $ = $B.args("__contains__", 2, {self: null, key: null},
281
["self", "key"], arguments, {}, null, null),
293
return self.$numeric_dict[key] !== undefined
294
}
295
296
var hash = _b_.hash(key)
297
if(self.$str_hash[hash] !== undefined &&
310
var $ = $B.args("__eq__", 2, {self: null, arg: null},
311
["self", "arg"], arguments, {}, null, null),
320
switch(typeof arg){
321
case "string":
322
if(self.$string_dict[arg] === undefined){
342
if((ix = rank(self, hash, arg)) > -1){
343
self.$object_dict[hash].splice(ix, 1)
344
}else{
353
var $ = $B.args("__eq__", 2, {self: null, other: null},
354
["self", "other"], arguments, {}, null, null),
360
if(self.$jsobj){self = jsobj2dict(self.$jsobj)}
361
if(other.$jsobj){other = jsobj2dict(other.$jsobj)}
372
if(!$B.rich_comp("__eq__", other.$numeric_dict[k][0],
373
self.$numeric_dict[k][0])){
377
var pairs = other.$object_dict[k],
378
flag = false
379
for(var i = 0, len = pairs.length; i < len; i++){
380
if($B.rich_comp("__eq__", k, pairs[i][0]) &&
381
$B.rich_comp("__eq__", self.$numeric_dict[k],
382
pairs[i][1])){
383
flag = true
384
break
385
}
400
var pairs = self.$object_dict[hash]
401
// Get all (key, value) pairs in other that have the same hash
402
var other_pairs = []
403
if(other.$numeric_dict[hash] !== undefined){
404
other_pairs.push([hash, other.$numeric_dict[hash]])
405
}
407
other_pairs = other_pairs.concat(other.$object_dict[hash])
408
}
409
if(other_pairs.length == 0){
410
return false
411
}
412
for(var i = 0, len_i = pairs.length; i < len_i; i++){
413
var flag = false
414
var key = pairs[i][0],
416
for(var j = 0, len_j = other_pairs.length; j < len_j; j++){
417
if($B.rich_comp("__eq__", key, other_pairs[j][0]) &&
432
var $ = $B.args("__getitem__", 2, {self: null, arg: null},
433
["self", "arg"], arguments, {}, null, null),
442
if(self.$exclude && self.$exclude(arg)){
443
throw _b_.KeyError.$factory(arg)
444
}
465
break
466
}
467
468
// since the key is more complex use 'default' method of getting item
469
485
if(self.$string_dict.hasOwnProperty(arg.valueOf())){
486
return self.$string_dict[arg.valueOf()][0]
487
}
495
if(! ignore_missing){
496
if(self.__class__ !== dict && ! ignore_missing){
497
try{
520
if(item.length != 2){
521
throw _b_.ValueError.$factory("dictionary " +
522
`update sequence element #${i} has length 1; 2 is required`)
523
}
531
if(item[0] != 0 && item[0] != 1){
532
self.$numeric_dict[item[0]] = [item[1], self.$order++]
533
self.$version++
534
break
535
}
549
for(var key in first){
550
self.$string_dict[key] = [first[key], self.$order++]
551
}
552
return _b_.None
553
}else if(first.$jsobj){
554
self.$jsobj = {}
555
for(var attr in first.$jsobj){
556
self.$jsobj[attr] = first.$jsobj[attr]
566
arguments, {}, "first", "second")
567
var args = $.first
568
if(args.length > 1){
569
throw _b_.TypeError.$factory("dict expected at most 1 argument" +
570
", got 2")
571
}else if(args.length == 1){
572
args = args[0]
573
if(args.__class__ === dict){
574
['$string_dict', '$str_hash', '$numeric_dict', '$object_dict'].
575
forEach(function(d){
576
for(key in args[d]){self[d][key] = args[d][key]}
577
})
581
var keys = $B.$getattr(args, "keys", null)
582
if(keys !== null){
583
var gi = $B.$getattr(args, "__getitem__", null)
584
if(gi !== null){
585
// has keys and __getitem__ : it's a mapping, iterate on
586
// keys and values
587
gi = $B.$call(gi)
588
var kiter = _b_.iter($B.$call(keys)())
589
while(true){
590
try{
591
var key = _b_.next(kiter),
592
value = gi(key)
593
dict.__setitem__(self, key, value)
594
}catch(err){
595
if(err.__class__ === _b_.StopIteration){
596
break
597
}
598
throw err
599
}
600
}
601
return $N
602
}
603
}
604
if(! Array.isArray(args)){
605
args = _b_.list.$factory(args)
606
}
607
// Form "dict([[key1, value1], [key2,value2], ...])"
633
dict.__ior__ = function(self, other){
634
// PEP 584
635
dict.update(self, other)
636
return self
637
}
638
643
for(var attr in self.$jsobj){
644
if(attr.charAt(0) != "$" &&
645
((! self.$exclude) || ! self.$exclude(attr))){
646
_count++
647
}
648
}
652
for(var k in self.$numeric_dict){_count++}
653
for(var k in self.$string_dict){_count++}
654
for(var hash in self.$object_dict){
655
_count += self.$object_dict[hash].length
656
}
684
dict.__or__ = function(self, other){
685
// PEP 584
686
if(! _b_.isinstance(other, dict)){
687
return _b_.NotImplemented
688
}
689
var res = dict.copy(self)
690
dict.update(res, other)
691
return res
692
}
693
694
function __newobj__(){
695
// __newobj__ is called with a generator as only argument
696
var $ = $B.args('__newobj__', 0, {}, [], arguments, {}, 'args', null),
697
args = $.args
698
var res = $B.empty_dict()
699
res.__class__ = args[0]
700
return res
701
}
702
703
dict.__reduce_ex__ = function(self, protocol){
704
return $B.fast_tuple([
705
__newobj__,
706
$B.fast_tuple([self.__class__]),
707
_b_.None,
708
_b_.None,
709
dict.items(self)])
710
}
711
733
dict.__ror__ = function(self, other){
734
// PEP 584
735
if(! _b_.isinstance(other, dict)){
736
return _b_.NotImplemented
737
}
738
var res = dict.copy(other)
739
dict.update(res, self)
740
return res
741
}
742
745
["self", "key", "value"], arguments, {}, null, null)
746
return dict.$setitem($.self, $.key, $.value)
747
}
752
// If key is a string, set:
753
// - $string_dict[key] = [value, order] where "order" is an auto-increment
754
// unique id to keep track of insertion order
755
// - $str_hash[hash(key)] to key
756
//
757
// If key is a number, set $numeric_dict[key] = value
758
//
759
// If key is another object, compute its hash value:
760
// - if the hash is a key of $str_hash, and key == $str_hash[hash],
761
// replace $string_dict[$str_hash[hash]] by value
762
// - if the hash is a key of $numeric_dict, and hash == key, replace
763
// $numeric_dict[hash] by value
764
// - if the hash is a key of $object_dict: $object_dict[hash] is a list
765
// of [k, v] pairs. If key is equal to one of the "k", replace the
766
// matching v by value. Otherwise, add [key, value] to the list
767
// - else set $object_dict[hash] = [[key, value]]
768
//
769
// In all cases, increment attribute $version, used to detect dictionary
772
// Parameter $hash is only set if this method is called by setdefault.
773
// In this case the hash of key has already been computed and we
774
// know that the key is not present in the dictionary, so it's no
775
// use computing hash(key) again, nor testing equality of keys
784
// If class attribute __init__ or __new__ are reset,
785
// the factory function has to change
786
self.$jsobj.$factory = $B.$instance_creator(self.$jsobj)
787
}
788
}else{
799
if(self.$string_dict === undefined){
800
console.log("pas de string dict", self, key, value)
801
}
803
self.$string_dict[key][0] = value
804
}else{
805
self.$string_dict[key] = [value, self.$order++]
806
self.$str_hash[str_hash(key)] = key
807
self.$version++
808
}
811
if(self.$numeric_dict[key] !== undefined){
812
// existing key: preserve order
813
self.$numeric_dict[key][0] = value
814
}else{
815
// special case for 0 and 1 if True or False are keys
816
var done = false
817
if((key == 0 || key == 1) &&
818
self.$object_dict[key] !== undefined){
819
for(const item of self.$object_dict[key]){
820
if((key == 0 && item[0] === false) ||
821
(key == 1 && item[0] === true)){
822
// replace value
823
item[1][0] = value
824
done = true
825
}
826
}
827
}
828
if(! done){
829
// new key
830
self.$numeric_dict[key] = [value, self.$order++]
831
}
835
case "boolean":
836
// true replaces 1 and false replaces 0
837
var num = key ? 1 : 0
838
if(self.$numeric_dict[num] !== undefined){
839
var order = self.$numeric_dict[num][1] // preserve order
840
self.$numeric_dict[num] = [value, order]
841
return
842
}
843
if(self.$object_dict[num] !== undefined){
844
self.$object_dict[num].push([key, [value, self.$order++]])
845
}else{
846
self.$object_dict[num] = [[key, [value, self.$order++]]]
847
}
867
// If $setitem is called from setdefault, don't test equality of key
868
// with any object
869
if($hash){
870
if(self.$object_dict[$hash] !== undefined){
874
}
875
self.$version++
876
return $N
877
}
878
var ix = rank(self, hash, key)
879
if(ix > -1){
880
// reset value
931
var $ = $B.args("fromkeys", 3, {cls: null, keys: null, value: null},
932
["cls", "keys", "value"], arguments, {value: _b_.None}, null, null),
944
if(klass === dict){dict.$setitem(res, key, value)}
945
else{$B.$getattr(res, "__setitem__")(key, value)}
956
var $ = $B.args("get", 3, {self: null, key: null, _default: null},
957
["self", "key", "_default"], arguments, {_default: $N}, null, null)
959
try{
960
// call $getitem with ignore_missign set to true
961
return dict.$getitem($.self, $.key, true)
962
}catch(err){
963
if(_b_.isinstance(err, _b_.KeyError)){return $._default}
964
else{throw err}
965
}
966
}
967
968
var dict_items = $B.make_view("dict_items", true)
969
dict_items.$iterator = $B.make_iterator_class("dict_itemiterator")
974
var items = to_list(self),
975
set_like = true
976
// Check if all values are hashable
977
for(var i = 0, len = items.length; i < len; i++){
978
try{
979
_b_.hash(items[i][1])
980
}catch(err){
981
set_like = false
982
break
983
}
984
}
985
var values = to_list(self)
986
var it = dict_items.$factory(self, values, set_like)
987
it.dict_version = self.$version
998
var it = dict_keys.$factory(self, to_list(self, 0), true)
999
it.dict_version = self.$version
1005
var missing = {},
1006
$ = $B.args("pop", 3, {self: null, key: null, _default: null},
1007
["self", "key", "_default"], arguments, {_default: missing}, null, null),
1039
var $ = $B.args("setdefault", 3, {self: null, key: null, _default: null},
1040
["self", "key", "_default"], arguments, {_default: $N}, null, null),
1044
try{
1045
// Pass 3rd argument to dict.$getitem to avoid using __missing__
1046
// Cf. issue #1598
1047
return dict.$getitem(self, key, true)
1048
}catch(err){
1053
var hash = key.$hash
1054
key.$hash = undefined
1055
dict.$setitem(self, key, _default, hash)
1062
var $ = $B.args("update", 1, {"self": null}, ["self"], arguments,
1063
{}, "args", "kw"),
1064
self = $.self,
1065
args = $.args,
1066
kw = $.kw
1067
if(args.length > 0){
1068
var o = args[0]
1075
var _keys = _b_.list.$factory($B.$call($B.$getattr(o, "keys"))())
1076
for(var i = 0, len = _keys.length; i < len; i++){
1078
dict.$setitem(self, _keys[i], _value)
1079
}
1080
}else{
1081
var it = _b_.iter(o),
1082
i = 0
1083
while(true){
1084
try{
1085
var item = _b_.next(it)
1086
}catch(err){
1087
if(err.__class__ === _b_.StopIteration){break}
1088
throw err
1089
}
1090
try{
1091
key_value = _b_.list.$factory(item)
1092
}catch(err){
1093
throw _b_.TypeError.$factory("cannot convert dictionary" +
1094
" update sequence element #" + i + " to a sequence")
1095
}
1096
if(key_value.length !== 2){
1097
throw _b_.ValueError.$factory("dictionary update " +
1098
"sequence element #" + i + " has length " +
1099
key_value.length + "; 2 is required")
1100
}
1101
dict.$setitem(self, key_value[0], key_value[1])
1102
i++
1111
var dict_values = $B.make_view("dict_values")
1112
dict_values.$iterator = $B.make_iterator_class("dict_valueiterator")
1115
var $ = $B.args('values', 1, {self: null}, ['self'], arguments,
1116
{}, null, null)
1118
var it = dict_values.$factory(self, values, false)
1119
it.dict_version = self.$version
1125
var args = [res]
1126
for(var i = 0, len = arguments.length; i < len ; i++){
1127
args.push(arguments[i])
1128
}
1129
dict.__init__.apply(null, args)
1139
$B.empty_dict = function(){
1140
return {
1141
__class__: dict,
1142
$numeric_dict : {},
1143
$object_dict : {},
1144
$string_dict : {},
1145
$str_hash: {},
1151
// This must be done after set_func_names, otherwise dict.fromkeys doesn't
1152
// have the attribute $infos
1153
dict.fromkeys = _b_.classmethod.$factory(dict.fromkeys)
1154
1155
$B.getset_descriptor = $B.make_class("getset_descriptor",
1156
function(klass, attr){
1157
return {
1158
__class__: $B.getset_descriptor,
1160
cls: klass,
1161
attr: attr
1162
}
1163
}
1164
)
1165
1166
$B.getset_descriptor.__repr__ = $B.getset_descriptor.__str__ = function(self){
1167
return `<attribute '${self.attr}' of '${self.cls.$infos.__name__}' objects>`
1168
}
1169
1170
$B.set_func_names($B.getset_descriptor, "builtins")
1171
1176
// obj is a dictionary, with $string_dict table such that
1177
// obj.$string_dict[key] = [value, rank]
1178
// Transform it into an object with attribute $jsobj such that
1179
// res.$jsobj[key] = value
1180
var res = $B.obj_dict(dict.$to_obj(obj))
1191
mappingproxy.__repr__ = function(){
1192
return '<mappingproxy object>'
1193
}
1194
1196
throw _b_.TypeError.$factory("'mappingproxy' object does not support " +
1197
"item assignment")
1200
for(var attr in dict){
1201
if(mappingproxy[attr] !== undefined ||
1202
["__class__", "__mro__", "__new__", "__init__", "__delitem__",
1203
"clear", "fromkeys", "pop", "popitem", "setdefault",
1204
"update"].indexOf(attr) > -1){
1205
continue
1206
}
1207
if(typeof dict[attr] == "function"){
1208
mappingproxy[attr] = (function(key){
1209
return function(){
1210
return dict[key].apply(null, arguments)
1211
}
1212
})(attr)
1213
}else{
1214
mappingproxy[attr] = dict[attr]
1215
}
1216
}
1217
1220
function jsobj2dict(x, exclude){
1221
exclude = exclude || function(){return false}
1250
// Wrapper around a JS object to handle it as a Python dictionary.
1251
// Some keys of the original object can be ignored by passing
1252
// the filtering function exclude().
1253
// Supports adding new keys.
1254
1255
var jsobj_as_pydict = $B.jsobj_as_pydict = $B.make_class('jsobj_as_pydict',
1256
function(jsobj, exclude){
1257
return {
1258
__class__: jsobj_as_pydict,
1259
obj: jsobj,
1260
exclude: exclude ? exclude : function(){return false},
1261
new_keys: []
1262
}
1263
}
1264
)
1265
1266
jsobj_as_pydict.__contains__ = function(self, key){
1267
if(self.new_keys.indexOf(key) > -1){
1268
return true
1269
}
1270
return ! (self.exclude(key) || self.obj[key] === undefined)
1271
}
1272
1273
jsobj_as_pydict.__delitem__ = function(self, key){
1274
jsobj_as_pydict.__getitem__(self, key) // raises KeyError if not present
1275
delete self.obj[key]
1276
var ix = self.new_keys.indexOf(key)
1277
if(ix > -1){
1278
self.new_keys.splice(ix, 1)
1279
}
1280
}
1281
1282
jsobj_as_pydict.__eq__ = function(self, other){
1283
if(other.__class__ !== jsobj_as_pydict){
1284
return _b_.NotImplemented
1285
}
1286
// create true Python dicts with the items in self and other
1287
var self1 = $B.empty_dict()
1288
other1 = $B.empty_dict()
1289
1290
dict.__init__(self1, jsobj_as_pydict.items(self))
1291
dict.__init__(other1, jsobj_as_pydict.items(other))
1292
1293
// Compare true Python dicts
1294
return dict.__eq__(self1, other1)
1295
}
1296
1297
jsobj_as_pydict.__getitem__ = function(self, key){
1298
if(jsobj_as_pydict.__contains__(self, key)){
1299
return self.obj[key]
1300
}
1301
throw _b_.KeyError.$factory(key)
1302
}
1303
1304
jsobj_as_pydict.__iter__ = function(self){
1305
return _b_.iter(jsobj_as_pydict.keys(self))
1306
}
1307
1308
jsobj_as_pydict.__len__ = function(self){
1309
var len = 0
1310
for(var key in self.obj){
1311
if(! self.exclude(key)){
1312
len++
1313
}
1314
}
1315
return len + self.new_keys.length
1316
}
1317
1318
jsobj_as_pydict.__repr__ = function(self){
1319
if($B.repr.enter(self)){
1320
return "{...}"
1321
}
1322
var res = [],
1323
items = _b_.list.$factory(jsobj_as_pydict.items(self))
1324
for(var item of items){
1325
res.push(_b_.repr(item[0]) + ": " + _b_.repr(item[1]))
1326
}
1327
$B.repr.leave(self)
1328
return "{" + res.join(", ") + "}"
1329
}
1330
1331
jsobj_as_pydict.__setitem__ = function(self, key, value){
1332
if(self.exclude(key) && self.new_keys.indexOf(key) == -1){
1333
self.new_keys.push(key)
1334
}
1335
self.obj[key] = value
1336
}
1337
1338
jsobj_as_pydict.get = function(self, key, _default){
1339
_default = _default === undefined ? _b_.None : _default
1340
if(self.exclude(key) || self.obj[key] === undefined){
1341
return _default
1342
}
1343
return self.obj[key]
1344
}
1345
1346
jsobj_as_pydict.items = function(self){
1348
for(var key in self.obj){
1349
if(self.exclude(key) && self.new_keys.indexOf(key) == -1){
1350
continue
1351
}
1352
items.push($B.fast_tuple([key, self.obj[key]]))
1353
}
1354
var set_like = true
1355
// Check if all values are hashable
1356
for(var item of items){
1357
try{
1358
_b_.hash(item[1])
1359
}catch(err){
1360
set_like = false
1361
break
1362
}
1364
var it = dict_items.$factory(self, items, set_like)
1365
it.dict_version = self.$version
1366
return it
1367
}
1368
1369
jsobj_as_pydict.keys = function(self){
1370
var lst = []
1371
for(var key in self.obj){
1372
if(self.exclude(key) && self.new_keys.indexOf(key) == -1){
1373
continue
1374
}
1375
lst.push(key)
1376
}
1377
var it = dict_keys.$factory(self, lst, true)
1378
it.dict_version = self.$version
1379
return it
1384
for(var key in self.obj){
1385
if(self.exclude(key) && self.new_keys.indexOf(key) == -1){
1386
continue
1387
}
1390
var it = dict_values.$factory(self, values, false)
1391
it.dict_version = self.$version
1392
return it