Skip to content
Permalink
Newer
Older
100644 1235 lines (1114 sloc) 36.1 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
679
function __newobj__(){
680
// __newobj__ is called with a generator as only argument
681
var $ = $B.args('__newobj__', 0, {}, [], arguments, {}, 'args', null),
682
args = $.args
683
var res = $B.empty_dict()
684
res.__class__ = args[0]
685
return res
686
}
687
688
dict.__reduce_ex__ = function(self, protocol){
689
return $B.fast_tuple([
690
__newobj__,
691
$B.fast_tuple([self.__class__]),
692
_b_.None,
693
_b_.None,
694
dict.items(self)])
695
}
696
Feb 11, 2018
697
dict.__repr__ = function(self){
698
if(self.$jsobj){ // wrapper around Javascript object
Feb 11, 2018
699
return dict.__repr__(jsobj2dict(self.$jsobj))
701
if($B.repr.enter(self)){
702
return "{...}"
703
}
704
var res = [],
706
items.forEach(function(item){
707
try{
708
res.push(repr(item[0]) + ": " + repr(item[1]))
709
}catch(err){
710
throw err
711
}
713
$B.repr.leave(self)
Mar 7, 2018
714
return "{" + res.join(", ") + "}"
Sep 5, 2014
715
}
716
717
dict.__ror__ = function(self, other){
718
// PEP 584
719
if(! _b_.isinstance(other, dict)){
720
return _b_.NotImplemented
721
}
722
var res = dict.copy(other)
723
dict.update(res, self)
724
return res
725
}
726
727
dict.__setitem__ = function(self, key, value){
Mar 7, 2018
728
var $ = $B.args("__setitem__", 3, {self: null, key: null, value: null},
729
["self", "key", "value"], arguments, {}, null, null)
730
return dict.$setitem($.self, $.key, $.value)
731
}
Nov 21, 2015
732
733
dict.$setitem = function(self, key, value, $hash){
734
// Set a dictionary item mapping key and value.
735
//
736
// If key is a string, set:
737
// - $string_dict[key] = [value, order] where "order" is an auto-increment
738
// unique id to keep track of insertion order
739
// - $str_hash[hash(key)] to key
740
//
741
// If key is a number, set $numeric_dict[key] = value
742
//
743
// If key is another object, compute its hash value:
744
// - if the hash is a key of $str_hash, and key == $str_hash[hash],
745
// replace $string_dict[$str_hash[hash]] by value
746
// - if the hash is a key of $numeric_dict, and hash == key, replace
747
// $numeric_dict[hash] by value
748
// - if the hash is a key of $object_dict: $object_dict[hash] is a list
749
// of [k, v] pairs. If key is equal to one of the "k", replace the
750
// matching v by value. Otherwise, add [key, value] to the list
751
// - else set $object_dict[hash] = [[key, value]]
752
//
753
// In all cases, increment attribute $version, used to detect dictionary
754
// changes during an iteration.
756
// Parameter $hash is only set if this method is called by setdefault.
757
// In this case the hash of key has already been computed and we
758
// know that the key is not present in the dictionary, so it's no
759
// use computing hash(key) again, nor testing equality of keys
761
if(self.$from_js){
762
// dictionary created by method to_dict of JSObj instances
763
value = $B.pyobj2jsobj(value)
764
}
765
if(self.$jsobj.__class__ === _b_.type){
766
self.$jsobj[key] = value
767
if(key == "__init__" || key == "__new__"){
768
// If class attribute __init__ or __new__ are reset,
769
// the factory function has to change
770
self.$jsobj.$factory = $B.$instance_creator(self.$jsobj)
771
}
772
}else{
773
self.$jsobj[key] = value
778
switch(typeof key){
779
case "string":
780
if(self.$string_dict === undefined){
781
console.log("pas de string dict", self, key, value)
782
}
783
if(self.$string_dict[key] !== undefined){
784
self.$string_dict[key][0] = value
785
}else{
786
self.$string_dict[key] = [value, self.$order++]
787
self.$str_hash[str_hash(key)] = key
788
self.$version++
789
}
790
return $N
791
case "number":
792
if(self.$numeric_dict[key] !== undefined){
793
// existing key: preserve order
794
self.$numeric_dict[key][0] = value
795
}else{
796
// special case for 0 and 1 if True or False are keys
797
var done = false
798
if((key == 0 || key == 1) &&
799
self.$object_dict[key] !== undefined){
800
for(const item of self.$object_dict[key]){
801
if((key == 0 && item[0] === false) ||
802
(key == 1 && item[0] === true)){
803
// replace value
804
item[1][0] = value
805
done = true
806
}
807
}
808
}
809
if(! done){
810
// new key
811
self.$numeric_dict[key] = [value, self.$order++]
812
}
815
return $N
816
case "boolean":
817
// true replaces 1 and false replaces 0
818
var num = key ? 1 : 0
819
if(self.$numeric_dict[num] !== undefined){
820
var order = self.$numeric_dict[num][1] // preserve order
821
self.$numeric_dict[num] = [value, order]
822
return
823
}
824
if(self.$object_dict[num] !== undefined){
825
self.$object_dict[num].push([key, [value, self.$order++]])
826
}else{
827
self.$object_dict[num] = [[key, [value, self.$order++]]]
828
}
831
// if we got here the key is more complex, use default method
832
833
var hash = $hash === undefined ? _b_.hash(key) : $hash,
834
_eq = function(other){return $B.rich_comp("__eq__", key, other)}
835
836
if(self.$numeric_dict[hash] !== undefined && _eq(hash)){
837
self.$numeric_dict[hash] = [value, self.$numeric_dict[hash][1]]
841
var sk = self.$str_hash[hash]
842
if(sk !== undefined && _eq(sk)){
843
self.$string_dict[sk] = [value, self.$string_dict[sk][1]]
848
// If $setitem is called from setdefault, don't test equality of key
849
// with any object
850
if($hash){
851
if(self.$object_dict[$hash] !== undefined){
852
self.$object_dict[$hash].push([key, [value, self.$order++]])
854
self.$object_dict[$hash] = [[key, [value, self.$order++]]]
855
}
856
self.$version++
857
return $N
858
}
859
var ix = rank(self, hash, key)
860
if(ix > -1){
861
// reset value
862
self.$object_dict[hash][ix][1] = [value,
863
self.$object_dict[hash][ix][1][1]]
864
return $N
865
}else if(self.$object_dict.hasOwnProperty(hash)){
866
self.$object_dict[hash].push([key, [value, self.$order++]])
868
self.$object_dict[hash] = [[key, [value, self.$order++]]]
Sep 5, 2014
872
}
873
874
dict.__str__ = function(){
875
return dict.__repr__.apply(null, arguments)
876
}
Sep 5, 2014
877
878
// add "reflected" methods
Feb 11, 2018
879
$B.make_rmethods(dict)
Sep 5, 2014
880
Feb 11, 2018
881
dict.clear = function(){
Sep 5, 2014
882
// Remove all items from the dictionary.
Mar 7, 2018
883
var $ = $B.args("clear", 1, {self: null}, ["self"], arguments, {},
884
null, null),
885
self = $.self
887
self.$numeric_dict = {}
888
self.$string_dict = {}
889
self.$str_hash = {}
890
self.$object_dict = {}
892
if(self.$jsobj){
893
for(var attr in self.$jsobj){
Mar 7, 2018
894
if(attr.charAt(0) !== "$" && attr !== "__class__"){
895
delete self.$jsobj[attr]
896
}
897
}
898
}
Sep 5, 2014
902
}
903
Feb 11, 2018
904
dict.copy = function(self){
Sep 5, 2014
905
// Return a shallow copy of the dictionary
Mar 7, 2018
906
var $ = $B.args("copy", 1, {self: null},["self"], arguments,{},
907
null, null),
908
self = $.self,
Sep 5, 2014
911
return res
912
}
913
Feb 11, 2018
914
dict.fromkeys = function(){
Nov 21, 2015
915
Mar 7, 2018
916
var $ = $B.args("fromkeys", 3, {cls: null, keys: null, value: null},
917
["cls", "keys", "value"], arguments, {value: _b_.None}, null, null),
918
keys = $.keys,
919
value = $.value
Sep 5, 2014
921
// class method
922
var klass = $.cls,
Sep 5, 2014
926
while(1){
927
try{
928
var key = _b_.next(keys_iter)
929
if(klass === dict){dict.$setitem(res, key, value)}
930
else{$B.$getattr(res, "__setitem__")(key, value)}
Sep 5, 2014
931
}catch(err){
932
if($B.is_exc(err, [_b_.StopIteration])){
Sep 5, 2014
933
return res
934
}
935
throw err
936
}
937
}
938
}
939
Feb 11, 2018
940
dict.get = function(){
Mar 7, 2018
941
var $ = $B.args("get", 3, {self: null, key: null, _default: null},
942
["self", "key", "_default"], arguments, {_default: $N}, null, null)
Feb 11, 2018
944
try{return dict.__getitem__($.self, $.key)}
945
catch(err){
946
if(_b_.isinstance(err, _b_.KeyError)){return $._default}
947
else{throw err}
948
}
949
}
950
951
var dict_items = $B.make_view("dict_items", true)
952
dict_items.$iterator = $B.make_iterator_class("dict_itemiterator")
953
Feb 11, 2018
954
dict.items = function(self){
Mar 23, 2018
955
if(arguments.length > 1){
956
var _len = arguments.length - 1,
957
_msg = "items() takes no arguments (" + _len + " given)"
958
throw _b_.TypeError.$factory(_msg)
959
}
960
var items = to_list(self),
961
set_like = true
962
// Check if all values are hashable
963
for(var i = 0, len = items.length; i < len; i++){
964
try{
965
_b_.hash(items[i][1])
966
}catch(err){
967
set_like = false
968
break
969
}
970
}
971
var values = to_list(self)
972
var it = dict_items.$factory(self, values, set_like)
973
it.dict_version = self.$version
975
}
976
978
var dict_keys = $B.make_view("dict_keys")
979
dict_keys.$iterator = $B.make_iterator_class("dict_keyiterator")
Nov 21, 2015
980
Mar 23, 2018
982
if(arguments.length > 1){
983
var _len = arguments.length - 1,
984
_msg = "keys() takes no arguments (" + _len + " given)"
985
throw _b_.TypeError.$factory(_msg)
Nov 21, 2015
986
}
987
var it = dict_keys.$factory(self, to_list(self, 0), true)
988
it.dict_version = self.$version
Nov 21, 2015
990
}
991
Feb 11, 2018
992
dict.pop = function(){
Nov 21, 2015
993
994
var missing = {},
995
$ = $B.args("pop", 3, {self: null, key: null, _default: null},
996
["self", "key", "_default"], arguments, {_default: missing}, null, null),
997
self = $.self,
998
key = $.key,
999
_default = $._default
Nov 21, 2015
1000
Sep 5, 2014
1001
try{
1002
var res = dict.__getitem__(self, key)
1003
dict.__delitem__(self, key)
Sep 5, 2014
1004
return res
1005
}catch(err){
1006
if(err.__class__ === _b_.KeyError){
1007
if(_default !== missing){return _default}
Sep 5, 2014
1008
throw err
1009
}
1010
throw err
1011
}
1012
}
1013
Feb 11, 2018
1014
dict.popitem = function(self){
1016
var itm = _b_.next(_b_.iter(dict.items(self)))
1017
dict.__delitem__(self, itm[0])
Feb 11, 2018
1018
return _b_.tuple.$factory(itm)
1020
if (err.__class__ == _b_.StopIteration) {
1021
throw _b_.KeyError.$factory("'popitem(): dictionary is empty'")
Sep 5, 2014
1024
}
1025
Feb 11, 2018
1026
dict.setdefault = function(){
Nov 21, 2015
1027
Mar 7, 2018
1028
var $ = $B.args("setdefault", 3, {self: null, key: null, _default: null},
1029
["self", "key", "_default"], arguments, {_default: $N}, null, null),
1030
self = $.self,
1031
key = $.key,
1032
_default = $._default
1033
try{
1034
// Pass 3rd argument to dict.$getitem to avoid using __missing__
1035
// Cf. issue #1598
1036
return dict.$getitem(self, key, true)
1037
}catch(err){
1038
if(err.__class__ !== _b_.KeyError){
1039
throw err
1040
}
1041
if(_default === undefined){_default = $N}
1042
var hash = key.$hash
1043
key.$hash = undefined
1044
dict.$setitem(self, key, _default, hash)
Sep 5, 2014
1045
return _default
1046
}
1047
}
1048
Feb 11, 2018
1049
dict.update = function(self){
Nov 21, 2015
1050
Mar 7, 2018
1051
var $ = $B.args("update", 1, {"self": null}, ["self"], arguments,
1052
{}, "args", "kw"),
1053
self = $.self,
1054
args = $.args,
1055
kw = $.kw
1056
if(args.length > 0){
1057
var o = args[0]
1059
if(o.$jsobj){
1060
o = jsobj2dict(o.$jsobj)
1061
}
1063
}else if(_b_.hasattr(o, "keys")){
1064
var _keys = _b_.list.$factory($B.$call($B.$getattr(o, "keys"))())
1065
for(var i = 0, len = _keys.length; i < len; i++){
1066
var _value = getattr(o, "__getitem__")(_keys[i])
1067
dict.$setitem(self, _keys[i], _value)
1068
}
1069
}else{
1070
var it = _b_.iter(o),
1071
i = 0
1072
while(true){
1073
try{
1074
var item = _b_.next(it)
1075
}catch(err){
1076
if(err.__class__ === _b_.StopIteration){break}
1077
throw err
1078
}
1079
try{
1080
key_value = _b_.list.$factory(item)
1081
}catch(err){
1082
throw _b_.TypeError.$factory("cannot convert dictionary" +
1083
" update sequence element #" + i + " to a sequence")
1084
}
1085
if(key_value.length !== 2){
1086
throw _b_.ValueError.$factory("dictionary update " +
1087
"sequence element #" + i + " has length " +
1088
key_value.length + "; 2 is required")
1089
}
1090
dict.$setitem(self, key_value[0], key_value[1])
1091
i++
Sep 5, 2014
1094
}
Sep 5, 2014
1098
}
1099
1100
var dict_values = $B.make_view("dict_values")
1101
dict_values.$iterator = $B.make_iterator_class("dict_valueiterator")
Nov 21, 2015
1102
Feb 11, 2018
1103
dict.values = function(self){
Mar 23, 2018
1104
if(arguments.length > 1){
1105
var _len = arguments.length - 1,
1106
_msg = "values() takes no arguments (" + _len + " given)"
1107
throw _b_.TypeError.$factory(_msg)
Nov 21, 2015
1108
}
1109
var values = to_list(self, 1)
1110
var it = dict_values.$factory(self, values, false)
1111
it.dict_version = self.$version
Nov 21, 2015
1113
}
1114
1115
dict.$factory = function(){
1116
var res = dict.__new__(dict)
1117
var args = [res]
1118
for(var i = 0, len = arguments.length; i < len ; i++){
1119
args.push(arguments[i])
1120
}
1121
dict.__init__.apply(null, args)
Sep 5, 2014
1122
return res
1123
}
Sep 5, 2014
1125
_b_.dict = dict
Feb 11, 2018
1127
$B.set_func_names(dict, "builtins")
1128
1129
dict.__class_getitem__ = _b_.classmethod.$factory(dict.__class_getitem__)
1130
1131
$B.empty_dict = function(){
1132
return {
1133
__class__: dict,
1134
$numeric_dict : {},
1135
$object_dict : {},
1136
$string_dict : {},
1137
$str_hash: {},
1138
$version: 0,
1139
$order: 0
1143
// This must be done after set_func_names, otherwise dict.fromkeys doesn't
1144
// have the attribute $infos
1145
dict.fromkeys = _b_.classmethod.$factory(dict.fromkeys)
1146
1147
$B.getset_descriptor = $B.make_class("getset_descriptor",
1148
function(klass, attr){
1149
return {
1150
__class__: $B.getset_descriptor,
1151
__doc__: _b_.None,
1152
cls: klass,
1153
attr: attr
1154
}
1155
}
1156
)
1157
1158
$B.getset_descriptor.__repr__ = $B.getset_descriptor.__str__ = function(self){
1159
return `<attribute '${self.attr}' of '${self.cls.$infos.__name__}' objects>`
1160
}
1161
1162
$B.set_func_names($B.getset_descriptor, "builtins")
1163
1164
// Class for attribute __dict__ of classes
1165
var mappingproxy = $B.mappingproxy = $B.make_class("mappingproxy",
Feb 12, 2018
1166
function(obj){
1167
if(_b_.isinstance(obj, dict)){
1168
// obj is a dictionary, with $string_dict table such that
1169
// obj.$string_dict[key] = [value, rank]
1170
// Transform it into an object with attribute $jsobj such that
1171
// res.$jsobj[key] = value
1172
var res = $B.obj_dict(dict.$to_obj(obj))
1173
}else{
1174
var res = $B.obj_dict(obj)
1175
}
Feb 12, 2018
1176
res.__class__ = mappingproxy
1177
return res
1178
}
1179
)
Feb 12, 2018
1181
mappingproxy.__setitem__ = function(){
Mar 7, 2018
1182
throw _b_.TypeError.$factory("'mappingproxy' object does not support " +
1183
"item assignment")
1186
for(var attr in dict){
1187
if(mappingproxy[attr] !== undefined ||
1188
["__class__", "__mro__", "__new__", "__init__", "__delitem__",
1189
"clear", "fromkeys", "pop", "popitem", "setdefault",
1190
"update"].indexOf(attr) > -1){
1191
continue
1192
}
1193
if(typeof dict[attr] == "function"){
1194
mappingproxy[attr] = (function(key){
1195
return function(){
1196
return dict[key].apply(null, arguments)
1197
}
1198
})(attr)
1199
}else{
1200
mappingproxy[attr] = dict[attr]
1201
}
1202
}
1203
Feb 12, 2018
1204
$B.set_func_names(mappingproxy, "builtins")
Mar 7, 2018
1209
if(attr.charAt(0) != "$" && attr !== "__class__"){
1210
if(x[attr] === null){
1211
d.$string_dict[attr] = [_b_.None, d.$order++]
1212
}else if(x[attr] === undefined){
1213
continue
1214
}else if(x[attr].$jsobj === x){
1215
d.$string_dict[attr] = [d, d.$order++]
1217
d.$string_dict[attr] = [$B.$JS2Py(x[attr]), d.$order++]
1219
}
1220
}
1221
return d
1222
}
1224
$B.obj_dict = function(obj, from_js){
1225
var klass = obj.__class__ || $B.get_class(obj)
1226
if(klass !== undefined && klass.$native){
1227
throw _b_.AttributeError.$factory("'" + $B.class_name(obj) +
1228
"' object has no attribute '__dict__'")}
1230
res.$jsobj = obj
1231
res.$from_js = from_js // set to true if
1232
return res
1233
}
1234
Sep 5, 2014
1235
})(__BRYTHON__)