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
Feb 26, 2018
Jul 21, 2020
Dec 28, 2020
Feb 26, 2018
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
Feb 26, 2018
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
1376 lines (1239 sloc)
39.8 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
197
if(val === undefined){val = _b_.NotImplemented}
198
else if(val === null){val = $N}
203
for(var k in d.$numeric_dict){
204
items.push([parseFloat(k), d.$numeric_dict[k]])
205
}
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]]})
226
}else{
227
items.__class__ = _b_.tuple
228
return items.map(function(item){
229
item.__class__ = _b_.tuple; return item}
230
)
231
}
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
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
279
var $ = $B.args("__contains__", 2, {self: null, key: null},
280
["self", "key"], arguments, {}, null, null),
292
return self.$numeric_dict[key] !== undefined
293
}
294
295
var hash = _b_.hash(key)
296
if(self.$str_hash[hash] !== undefined &&
309
var $ = $B.args("__eq__", 2, {self: null, arg: null},
310
["self", "arg"], arguments, {}, null, null),
319
switch(typeof arg){
320
case "string":
321
if(self.$string_dict[arg] === undefined){
341
if((ix = rank(self, hash, arg)) > -1){
342
self.$object_dict[hash].splice(ix, 1)
343
}else{
352
var $ = $B.args("__eq__", 2, {self: null, other: null},
353
["self", "other"], arguments, {}, null, null),
359
if(self.$jsobj){self = jsobj2dict(self.$jsobj)}
360
if(other.$jsobj){other = jsobj2dict(other.$jsobj)}
371
if(!$B.rich_comp("__eq__", other.$numeric_dict[k][0],
372
self.$numeric_dict[k][0])){
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
}
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
}
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],
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]) &&
431
var $ = $B.args("__getitem__", 2, {self: null, arg: null},
432
["self", "arg"], arguments, {}, null, null),
462
break
463
}
464
465
// since the key is more complex use 'default' method of getting item
466
491
if(! ignore_missing){
492
if(self.__class__ !== dict && ! ignore_missing){
493
try{
516
if(item.length != 2){
517
throw _b_.ValueError.$factory("dictionary " +
518
`update sequence element #${i} has length 1; 2 is required`)
519
}
527
if(item[0] != 0 && item[0] != 1){
528
self.$numeric_dict[item[0]] = [item[1], self.$order++]
529
self.$version++
530
break
531
}
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]
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
})
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], ...])"
629
dict.__ior__ = function(self, other){
630
// PEP 584
631
dict.update(self, other)
632
return self
633
}
634
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
}
675
dict.__or__ = function(self, other){
676
// PEP 584
677
if(! _b_.isinstance(other, dict)){
678
return _b_.NotImplemented
679
}
680
var res = dict.copy(self)
681
dict.update(res, other)
682
return res
683
}
684
685
function __newobj__(){
686
// __newobj__ is called with a generator as only argument
687
var $ = $B.args('__newobj__', 0, {}, [], arguments, {}, 'args', null),
688
args = $.args
689
var res = $B.empty_dict()
690
res.__class__ = args[0]
691
return res
692
}
693
694
dict.__reduce_ex__ = function(self, protocol){
695
return $B.fast_tuple([
696
__newobj__,
697
$B.fast_tuple([self.__class__]),
698
_b_.None,
699
_b_.None,
700
dict.items(self)])
701
}
702
724
dict.__ror__ = function(self, other){
725
// PEP 584
726
if(! _b_.isinstance(other, dict)){
727
return _b_.NotImplemented
728
}
729
var res = dict.copy(other)
730
dict.update(res, self)
731
return res
732
}
733
736
["self", "key", "value"], arguments, {}, null, null)
737
return dict.$setitem($.self, $.key, $.value)
738
}
743
// If key is a string, set:
744
// - $string_dict[key] = [value, order] where "order" is an auto-increment
745
// unique id to keep track of insertion order
746
// - $str_hash[hash(key)] to key
747
//
748
// If key is a number, set $numeric_dict[key] = value
749
//
750
// If key is another object, compute its hash value:
751
// - if the hash is a key of $str_hash, and key == $str_hash[hash],
752
// replace $string_dict[$str_hash[hash]] by value
753
// - if the hash is a key of $numeric_dict, and hash == key, replace
754
// $numeric_dict[hash] by value
755
// - if the hash is a key of $object_dict: $object_dict[hash] is a list
756
// of [k, v] pairs. If key is equal to one of the "k", replace the
757
// matching v by value. Otherwise, add [key, value] to the list
758
// - else set $object_dict[hash] = [[key, value]]
759
//
760
// In all cases, increment attribute $version, used to detect dictionary
763
// Parameter $hash is only set if this method is called by setdefault.
764
// In this case the hash of key has already been computed and we
765
// know that the key is not present in the dictionary, so it's no
766
// use computing hash(key) again, nor testing equality of keys
775
// If class attribute __init__ or __new__ are reset,
776
// the factory function has to change
777
self.$jsobj.$factory = $B.$instance_creator(self.$jsobj)
778
}
779
}else{
790
if(self.$string_dict === undefined){
791
console.log("pas de string dict", self, key, value)
792
}
793
if(self.$string_dict[key] !== undefined){
794
self.$string_dict[key][0] = value
795
}else{
796
self.$string_dict[key] = [value, self.$order++]
797
self.$str_hash[str_hash(key)] = key
798
self.$version++
799
}
802
if(self.$numeric_dict[key] !== undefined){
803
// existing key: preserve order
804
self.$numeric_dict[key][0] = value
805
}else{
806
// special case for 0 and 1 if True or False are keys
807
var done = false
808
if((key == 0 || key == 1) &&
809
self.$object_dict[key] !== undefined){
810
for(const item of self.$object_dict[key]){
811
if((key == 0 && item[0] === false) ||
812
(key == 1 && item[0] === true)){
813
// replace value
814
item[1][0] = value
815
done = true
816
}
817
}
818
}
819
if(! done){
820
// new key
821
self.$numeric_dict[key] = [value, self.$order++]
822
}
826
case "boolean":
827
// true replaces 1 and false replaces 0
828
var num = key ? 1 : 0
829
if(self.$numeric_dict[num] !== undefined){
830
var order = self.$numeric_dict[num][1] // preserve order
831
self.$numeric_dict[num] = [value, order]
832
return
833
}
834
if(self.$object_dict[num] !== undefined){
835
self.$object_dict[num].push([key, [value, self.$order++]])
836
}else{
837
self.$object_dict[num] = [[key, [value, self.$order++]]]
838
}
858
// If $setitem is called from setdefault, don't test equality of key
859
// with any object
860
if($hash){
861
if(self.$object_dict[$hash] !== undefined){
865
}
866
self.$version++
867
return $N
868
}
869
var ix = rank(self, hash, key)
870
if(ix > -1){
871
// reset value
922
var $ = $B.args("fromkeys", 3, {cls: null, keys: null, value: null},
923
["cls", "keys", "value"], arguments, {value: _b_.None}, null, null),
935
if(klass === dict){dict.$setitem(res, key, value)}
936
else{$B.$getattr(res, "__setitem__")(key, value)}
947
var $ = $B.args("get", 3, {self: null, key: null, _default: null},
948
["self", "key", "_default"], arguments, {_default: $N}, null, null)
950
try{
951
// call $getitem with ignore_missign set to true
952
return dict.$getitem($.self, $.key, true)
953
}catch(err){
954
if(_b_.isinstance(err, _b_.KeyError)){return $._default}
955
else{throw err}
956
}
957
}
958
959
var dict_items = $B.make_view("dict_items", true)
960
dict_items.$iterator = $B.make_iterator_class("dict_itemiterator")
964
var _len = arguments.length - 1,
965
_msg = "items() takes no arguments (" + _len + " given)"
968
var items = to_list(self),
969
set_like = true
970
// Check if all values are hashable
971
for(var i = 0, len = items.length; i < len; i++){
972
try{
973
_b_.hash(items[i][1])
974
}catch(err){
975
set_like = false
976
break
977
}
978
}
979
var values = to_list(self)
980
var it = dict_items.$factory(self, values, set_like)
981
it.dict_version = self.$version
991
var _len = arguments.length - 1,
992
_msg = "keys() takes no arguments (" + _len + " given)"
995
var it = dict_keys.$factory(self, to_list(self, 0), true)
996
it.dict_version = self.$version
1002
var missing = {},
1003
$ = $B.args("pop", 3, {self: null, key: null, _default: null},
1004
["self", "key", "_default"], arguments, {_default: missing}, null, null),
1036
var $ = $B.args("setdefault", 3, {self: null, key: null, _default: null},
1037
["self", "key", "_default"], arguments, {_default: $N}, null, null),
1041
try{
1042
// Pass 3rd argument to dict.$getitem to avoid using __missing__
1043
// Cf. issue #1598
1044
return dict.$getitem(self, key, true)
1045
}catch(err){
1050
var hash = key.$hash
1051
key.$hash = undefined
1052
dict.$setitem(self, key, _default, hash)
1059
var $ = $B.args("update", 1, {"self": null}, ["self"], arguments,
1060
{}, "args", "kw"),
1061
self = $.self,
1062
args = $.args,
1063
kw = $.kw
1064
if(args.length > 0){
1065
var o = args[0]
1072
var _keys = _b_.list.$factory($B.$call($B.$getattr(o, "keys"))())
1073
for(var i = 0, len = _keys.length; i < len; i++){
1075
dict.$setitem(self, _keys[i], _value)
1076
}
1077
}else{
1078
var it = _b_.iter(o),
1079
i = 0
1080
while(true){
1081
try{
1082
var item = _b_.next(it)
1083
}catch(err){
1084
if(err.__class__ === _b_.StopIteration){break}
1085
throw err
1086
}
1087
try{
1088
key_value = _b_.list.$factory(item)
1089
}catch(err){
1090
throw _b_.TypeError.$factory("cannot convert dictionary" +
1091
" update sequence element #" + i + " to a sequence")
1092
}
1093
if(key_value.length !== 2){
1094
throw _b_.ValueError.$factory("dictionary update " +
1095
"sequence element #" + i + " has length " +
1096
key_value.length + "; 2 is required")
1097
}
1098
dict.$setitem(self, key_value[0], key_value[1])
1099
i++
1108
var dict_values = $B.make_view("dict_values")
1109
dict_values.$iterator = $B.make_iterator_class("dict_valueiterator")
1113
var _len = arguments.length - 1,
1114
_msg = "values() takes no arguments (" + _len + " given)"
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))
1192
throw _b_.TypeError.$factory("'mappingproxy' object does not support " +
1193
"item assignment")
1196
for(var attr in dict){
1197
if(mappingproxy[attr] !== undefined ||
1198
["__class__", "__mro__", "__new__", "__init__", "__delitem__",
1199
"clear", "fromkeys", "pop", "popitem", "setdefault",
1200
"update"].indexOf(attr) > -1){
1201
continue
1202
}
1203
if(typeof dict[attr] == "function"){
1204
mappingproxy[attr] = (function(key){
1205
return function(){
1206
return dict[key].apply(null, arguments)
1207
}
1208
})(attr)
1209
}else{
1210
mappingproxy[attr] = dict[attr]
1211
}
1212
}
1213
1245
// Wrapper around a JS object to handle it as a Python dictionary.
1246
// Some keys of the original object can be ignored by passing
1247
// the filtering function exclude().
1248
// Supports adding new keys.
1249
1250
var jsobj_as_pydict = $B.jsobj_as_pydict = $B.make_class('jsobj_as_pydict',
1251
function(jsobj, exclude){
1252
return {
1253
__class__: jsobj_as_pydict,
1254
obj: jsobj,
1255
exclude: exclude ? exclude : function(){return false},
1256
new_keys: []
1257
}
1258
}
1259
)
1260
1261
jsobj_as_pydict.__contains__ = function(self, key){
1262
if(self.new_keys.indexOf(key) > -1){
1263
return true
1264
}
1265
return ! (self.exclude(key) || self.obj[key] === undefined)
1266
}
1267
1268
jsobj_as_pydict.__delitem__ = function(self, key){
1269
jsobj_as_pydict.__getitem__(self, key) // raises KeyError if not present
1270
delete self.obj[key]
1271
var ix = self.new_keys.indexOf(key)
1272
if(ix > -1){
1273
self.new_keys.splice(ix, 1)
1274
}
1275
}
1276
1277
jsobj_as_pydict.__eq__ = function(self, other){
1278
if(other.__class__ !== jsobj_as_pydict){
1279
return _b_.NotImplemented
1280
}
1281
// create true Python dicts with the items in self and other
1282
var self1 = $B.empty_dict()
1283
other1 = $B.empty_dict()
1284
1285
dict.__init__(self1, jsobj_as_pydict.items(self))
1286
dict.__init__(other1, jsobj_as_pydict.items(other))
1287
1288
// Compare true Python dicts
1289
return dict.__eq__(self1, other1)
1290
}
1291
1292
jsobj_as_pydict.__getitem__ = function(self, key){
1293
if(jsobj_as_pydict.__contains__(self, key)){
1294
return self.obj[key]
1295
}
1296
throw _b_.KeyError.$factory(key)
1297
}
1298
1299
jsobj_as_pydict.__iter__ = function(self){
1300
return _b_.iter(jsobj_as_pydict.keys(self))
1301
}
1302
1303
jsobj_as_pydict.__len__ = function(self){
1304
var len = 0
1305
for(var key in self.obj){
1306
if(! self.exclude(key)){
1307
len++
1308
}
1309
}
1310
return len + self.new_keys.length
1311
}
1312
1313
jsobj_as_pydict.__repr__ = function(self){
1314
if($B.repr.enter(self)){
1315
return "{...}"
1316
}
1317
var res = [],
1318
items = _b_.list.$factory(jsobj_as_pydict.items(self))
1319
for(var item of items){
1320
res.push(_b_.repr(item[0]) + ": " + _b_.repr(item[1]))
1321
}
1322
$B.repr.leave(self)
1323
return "{" + res.join(", ") + "}"
1324
}
1325
1326
jsobj_as_pydict.__setitem__ = function(self, key, value){
1327
if(self.exclude(key) && self.new_keys.indexOf(key) == -1){
1328
self.new_keys.push(key)
1329
}
1330
self.obj[key] = value
1331
}
1332
1333
jsobj_as_pydict.get = function(self, key, _default){
1334
_default = _default === undefined ? _b_.None : _default
1335
if(self.exclude(key) || self.obj[key] === undefined){
1336
return _default
1337
}
1338
return self.obj[key]
1339
}
1340
1341
jsobj_as_pydict.items = function(self){
1342
var lst = []
1343
for(var key in self.obj){
1344
if(self.exclude(key) && self.new_keys.indexOf(key) == -1){
1345
continue
1346
}
1347
lst.push($B.fast_tuple([key, self.obj[key]]))
1348
}
1349
return _b_.iter(lst)
1350
}
1351
1352
jsobj_as_pydict.keys = function(self){
1353
var lst = []
1354
for(var key in self.obj){
1355
if(self.exclude(key) && self.new_keys.indexOf(key) == -1){
1356
continue
1357
}
1358
lst.push(key)
1359
}
1360
return _b_.iter(lst)
1361
}
1362
1363
jsobj_as_pydict.values = function(self){
1364
var lst = []
1365
for(var key in self.obj){
1366
if(self.exclude(key) && self.new_keys.indexOf(key) == -1){
1367
continue
1368
}
1369
lst.push(self.obj[key])
1370
}
1371
return _b_.iter(lst)
1372
}
1373
1374
$B.set_func_names(jsobj_as_pydict, 'builtins')
1375