Skip to content
Permalink
Newer
Older
100644 1246 lines (1126 sloc) 36.5 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,
175
$match_mapping_pattern: true // for pattern matching (PEP 634)
Sep 5, 2014
176
}
177
178
dict.$to_obj = function(d){
179
// Function applied to dictionary that only have string keys,
180
// return a Javascript objects with the kays mapped to the value,
181
// excluding the insertion rank
182
var res = {}
183
for(var key in d.$string_dict){
184
res[key] = d.$string_dict[key][0]
185
}
186
return res
187
}
188
189
function to_list(d, ix){
190
var items = [],
191
item
193
if(d.$jsobj){
Mar 7, 2018
196
if(attr.charAt(0) != "$"){
197
var val = d.$jsobj[attr]
198
if(val === undefined){val = _b_.NotImplemented}
199
else if(val === null){val = $N}
203
}else if(_b_.isinstance(d, _b_.dict)){
204
for(var k in d.$numeric_dict){
205
items.push([parseFloat(k), d.$numeric_dict[k]])
206
}
208
for(var k in d.$string_dict){
209
items.push([k, d.$string_dict[k]])
210
}
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]]})
225
res = items.map(function(item){return item[ix]})
226
return res
227
}else{
228
items.__class__ = _b_.tuple
229
return items.map(function(item){
230
item.__class__ = _b_.tuple; return item}
231
)
232
}
Feb 9, 2015
234
235
$B.dict_to_list = to_list // used in py_types.js
236
237
var $copy_dict = function(left, right){
239
si = dict.$setitem
240
right.$version = right.$version || 0
241
var right_version = right.$version || 0
242
for(var i = 0, len = _l.length; i < len; i++){
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
Feb 11, 2018
264
dict.__bool__ = function () {
Mar 7, 2018
265
var $ = $B.args("__bool__", 1, {self: null}, ["self"],
266
arguments, {}, null, null)
Feb 11, 2018
267
return dict.__len__($.self) > 0
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
Feb 11, 2018
279
dict.__contains__ = function(){
280
var $ = $B.args("__contains__", 2, {self: null, key: null},
281
["self", "key"], arguments, {}, null, null),
282
self = $.self,
284
if(self.$is_namespace){ // issue 1244
285
key = $B.to_alias(key)
286
}
287
288
if(self.$jsobj){
289
return self.$jsobj[key] !== undefined
290
}
292
switch(typeof key) {
294
return self.$string_dict[key] !== undefined
296
return self.$numeric_dict[key] !== undefined
297
}
298
299
var hash = _b_.hash(key)
300
if(self.$str_hash[hash] !== undefined &&
301
$B.rich_comp("__eq__", key, self.$str_hash[hash])){
302
return true
303
}
304
if(self.$numeric_dict[hash] !== undefined &&
305
$B.rich_comp("__eq__", key, hash)){
306
return true
307
}
308
return rank(self, hash, key) > -1
Sep 5, 2014
309
}
310
Feb 11, 2018
311
dict.__delitem__ = function(){
Nov 21, 2015
312
313
var $ = $B.args("__eq__", 2, {self: null, arg: null},
314
["self", "arg"], arguments, {}, null, null),
315
self = $.self,
Nov 21, 2015
317
318
if(self.$jsobj){
319
if(self.$jsobj[arg] === undefined){throw _b_.KeyError.$factory(arg)}
320
delete self.$jsobj[arg]
323
switch(typeof arg){
324
case "string":
325
if(self.$string_dict[arg] === undefined){
326
throw _b_.KeyError.$factory(_b_.str.$factory(arg))
327
}
328
delete self.$string_dict[arg]
329
delete self.$str_hash[str_hash(arg)]
331
return $N
332
case "number":
333
if(self.$numeric_dict[arg] === undefined){
334
throw _b_.KeyError.$factory(_b_.str.$factory(arg))
336
delete self.$numeric_dict[arg]
340
// go with defaults
341
342
var hash = _b_.hash(arg),
343
ix
345
if((ix = rank(self, hash, arg)) > -1){
346
self.$object_dict[hash].splice(ix, 1)
347
}else{
348
throw _b_.KeyError.$factory(_b_.str.$factory(arg))
Sep 5, 2014
353
}
354
Feb 11, 2018
355
dict.__eq__ = function(){
Mar 7, 2018
356
var $ = $B.args("__eq__", 2, {self: null, other: null},
357
["self", "other"], arguments, {}, null, null),
358
self = $.self,
359
other = $.other
361
if(! _b_.isinstance(other, dict)){return false}
363
if(self.$jsobj){self = jsobj2dict(self.$jsobj)}
364
if(other.$jsobj){other = jsobj2dict(other.$jsobj)}
365
if(dict.__len__(self) != dict.__len__(other)){
366
return false
367
}
369
if(self.$string_dict.length != other.$string_dict.length){
373
for(var k in self.$numeric_dict){
374
if(other.$numeric_dict.hasOwnProperty(k)){
375
if(!$B.rich_comp("__eq__", other.$numeric_dict[k][0],
376
self.$numeric_dict[k][0])){
377
return false
378
}
379
}else if(other.$object_dict.hasOwnProperty(k)){
380
var pairs = other.$object_dict[k],
381
flag = false
382
for(var i = 0, len = pairs.length; i < len; i++){
383
if($B.rich_comp("__eq__", k, pairs[i][0]) &&
384
$B.rich_comp("__eq__", self.$numeric_dict[k],
385
pairs[i][1])){
386
flag = true
387
break
388
}
390
if(! flag){return false}
Nov 21, 2015
393
}
394
}
395
for(var k in self.$string_dict){
396
if(!other.$string_dict.hasOwnProperty(k) ||
397
!$B.rich_comp("__eq__", other.$string_dict[k][0],
398
self.$string_dict[k][0])){
Nov 21, 2015
400
}
401
}
402
for(var hash in self.$object_dict){
403
var pairs = self.$object_dict[hash]
404
// Get all (key, value) pairs in other that have the same hash
405
var other_pairs = []
406
if(other.$numeric_dict[hash] !== undefined){
407
other_pairs.push([hash, other.$numeric_dict[hash]])
408
}
409
if(other.$object_dict[hash] !== undefined){
410
other_pairs = other_pairs.concat(other.$object_dict[hash])
411
}
412
if(other_pairs.length == 0){
413
return false
414
}
415
for(var i = 0, len_i = pairs.length; i < len_i; i++){
416
var flag = false
417
var key = pairs[i][0],
418
value = pairs[i][1][0]
419
for(var j = 0, len_j = other_pairs.length; j < len_j; j++){
420
if($B.rich_comp("__eq__", key, other_pairs[j][0]) &&
421
$B.rich_comp("__eq__", value, other_pairs[j][1][0])){
422
flag = true
423
break
429
}
430
}
431
return true
Sep 5, 2014
432
}
433
Feb 11, 2018
434
dict.__getitem__ = function(){
435
var $ = $B.args("__getitem__", 2, {self: null, arg: null},
436
["self", "arg"], arguments, {}, null, null),
437
self = $.self,
439
return dict.$getitem(self, arg)
440
}
441
442
dict.$getitem = function(self, arg, ignore_missing){
443
// ignore_missing is set in dict.get and dict.setdefault
444
if(self.$jsobj){
445
if(self.$jsobj[arg] === undefined){
446
if(self.$jsobj.hasOwnProperty(arg)){
448
}
449
throw _b_.KeyError.$factory(arg)
450
}
451
return self.$jsobj[arg]
453
454
switch(typeof arg){
455
case "string":
456
var x = self.$string_dict[arg]
457
if(x !== undefined){
458
return x[0]
460
break
461
case "number":
462
if(self.$numeric_dict[arg] !== undefined){
463
return self.$numeric_dict[arg][0]
465
break
466
}
467
468
// since the key is more complex use 'default' method of getting item
469
470
var hash = _b_.hash(arg),
471
_eq = function(other){return $B.rich_comp("__eq__", arg, other)}
472
473
if(typeof arg == "object"){
474
arg.$hash = hash // cache for setdefault
475
}
476
var sk = self.$str_hash[hash]
477
if(sk !== undefined && _eq(sk)){
478
return self.$string_dict[sk][0]
480
if(self.$numeric_dict[hash] !== undefined && _eq(hash)){
481
return self.$numeric_dict[hash][0]
483
if(_b_.isinstance(arg, _b_.str)){
484
// string subclass
485
var res = self.$string_dict[arg.valueOf()]
486
if(res !== undefined){return res[0]}
489
var ix = rank(self, hash, arg)
490
if(ix > -1){
491
return self.$object_dict[hash][ix][1][0]
494
if(! ignore_missing){
495
if(self.__class__ !== dict && ! ignore_missing){
496
try{
497
var missing_method = getattr(self.__class__, "__missing__",
498
_b_.None)
499
}catch(err){
500
console.log(err)
502
}
503
if(missing_method !== _b_.None){
504
return missing_method(self, arg)
505
}
508
throw _b_.KeyError.$factory(arg)
Sep 5, 2014
509
}
510
511
dict.__hash__ = _b_.None
Sep 5, 2014
512
513
function init_from_list(self, args){
514
var i = -1,
515
stop = args.length - 1,
516
si = dict.__setitem__
517
while(i++ < stop){
518
var item = args[i]
519
if(item.length != 2){
520
throw _b_.ValueError.$factory("dictionary " +
521
`update sequence element #${i} has length 1; 2 is required`)
522
}
523
switch(typeof item[0]) {
524
case 'string':
525
self.$string_dict[item[0]] = [item[1], self.$order++]
526
self.$str_hash[str_hash(item[0])] = item[0]
527
self.$version++
528
break
529
case 'number':
530
if(item[0] != 0 && item[0] != 1){
531
self.$numeric_dict[item[0]] = [item[1], self.$order++]
532
self.$version++
533
break
534
}
535
default:
536
si(self, item[0], item[1])
537
break
538
}
539
}
540
}
541
542
dict.__init__ = function(self, first, second){
543
if(first === undefined){
544
return $N
545
}
547
if(first.$nat != 'kw' && $B.get_class(first) === $B.JSObj){
548
for(var key in first){
549
self.$string_dict[key] = [first[key], self.$order++]
550
}
551
return _b_.None
552
}else if(first.$jsobj){
553
self.$jsobj = {}
554
for(var attr in first.$jsobj){
555
self.$jsobj[attr] = first.$jsobj[attr]
558
}else if(Array.isArray(first)){
559
init_from_list(self, first)
560
return $N
Sep 5, 2014
561
}
564
var $ = $B.args("dict", 1, {self:null}, ["self"],
565
arguments, {}, "first", "second")
566
var args = $.first
567
if(args.length > 1){
568
throw _b_.TypeError.$factory("dict expected at most 1 argument" +
569
", got 2")
570
}else if(args.length == 1){
571
args = args[0]
572
if(args.__class__ === dict){
573
['$string_dict', '$str_hash', '$numeric_dict', '$object_dict'].
574
forEach(function(d){
575
for(key in args[d]){self[d][key] = args[d][key]}
576
})
577
}else if(_b_.isinstance(args, dict)){
580
var keys = $B.$getattr(args, "keys", null)
581
if(keys !== null){
582
var gi = $B.$getattr(args, "__getitem__", null)
583
if(gi !== null){
584
// has keys and __getitem__ : it's a mapping, iterate on
585
// keys and values
586
gi = $B.$call(gi)
587
var kiter = _b_.iter($B.$call(keys)())
588
while(true){
589
try{
590
var key = _b_.next(kiter),
591
value = gi(key)
592
dict.__setitem__(self, key, value)
593
}catch(err){
594
if(err.__class__ === _b_.StopIteration){
595
break
596
}
597
throw err
598
}
599
}
600
return $N
601
}
602
}
603
if(! Array.isArray(args)){
604
args = _b_.list.$factory(args)
605
}
606
// Form "dict([[key1, value1], [key2,value2], ...])"
607
init_from_list(self, args)
Sep 5, 2014
608
}
610
var kw = $.second.$string_dict
611
for(var attr in kw){
612
switch(typeof attr){
613
case "string":
614
self.$string_dict[attr] = [kw[attr][0], self.$order++]
615
self.$str_hash[str_hash(attr)] = attr
616
break
617
case "number":
618
self.$numeric_dict[attr] = [kw[attr][0], self.$order++]
621
si(self, attr, kw[attr][0])
Sep 5, 2014
626
}
627
Feb 11, 2018
628
dict.__iter__ = function(self) {
629
return _b_.iter(dict.$$keys(self))
Sep 5, 2014
630
}
631
632
dict.__ior__ = function(self, other){
633
// PEP 584
634
dict.update(self, other)
635
return self
636
}
637
Feb 11, 2018
638
dict.__len__ = function(self) {
641
if(self.$jsobj){
Mar 7, 2018
642
for(var attr in self.$jsobj){if(attr.charAt(0) != "$"){_count++}}
643
return _count
644
}
646
for(var k in self.$numeric_dict){_count++}
647
for(var k in self.$string_dict){_count++}
648
for(var hash in self.$object_dict){
649
_count += self.$object_dict[hash].length
650
}
Sep 5, 2014
654
Mar 7, 2018
655
dict.__ne__ = function(self, other){return ! dict.__eq__(self, other)}
Sep 5, 2014
656
Feb 11, 2018
657
dict.__new__ = function(cls){
658
if(cls === undefined){
Mar 7, 2018
659
throw _b_.TypeError.$factory("int.__new__(): not enough arguments")
661
var instance = {
663
$numeric_dict : {},
664
$object_dict : {},
667
$version: 0,
668
$order: 0
670
if(cls !== dict){
671
instance.__dict__ = $B.empty_dict()
672
}
673
return instance
676
dict.__or__ = function(self, other){
677
// PEP 584
678
if(! _b_.isinstance(other, dict)){
679
return _b_.NotImplemented
680
}
681
var res = dict.copy(self)
682
dict.update(res, other)
683
return res
684
}
685
686
function __newobj__(){
687
// __newobj__ is called with a generator as only argument
688
var $ = $B.args('__newobj__', 0, {}, [], arguments, {}, 'args', null),
689
args = $.args
690
var res = $B.empty_dict()
691
res.__class__ = args[0]
692
return res
693
}
694
695
dict.__reduce_ex__ = function(self, protocol){
696
return $B.fast_tuple([
697
__newobj__,
698
$B.fast_tuple([self.__class__]),
699
_b_.None,
700
_b_.None,
701
dict.items(self)])
702
}
703
Feb 11, 2018
704
dict.__repr__ = function(self){
705
$B.builtins_repr_check(dict, arguments) // in brython_builtins.js
706
if(self.$jsobj){ // wrapper around Javascript object
Feb 11, 2018
707
return dict.__repr__(jsobj2dict(self.$jsobj))
709
if($B.repr.enter(self)){
710
return "{...}"
711
}
712
var res = [],
714
items.forEach(function(item){
715
try{
716
res.push(repr(item[0]) + ": " + repr(item[1]))
717
}catch(err){
718
throw err
719
}
721
$B.repr.leave(self)
Mar 7, 2018
722
return "{" + res.join(", ") + "}"
Sep 5, 2014
723
}
724
725
dict.__ror__ = function(self, other){
726
// PEP 584
727
if(! _b_.isinstance(other, dict)){
728
return _b_.NotImplemented
729
}
730
var res = dict.copy(other)
731
dict.update(res, self)
732
return res
733
}
734
735
dict.__setitem__ = function(self, key, value){
Mar 7, 2018
736
var $ = $B.args("__setitem__", 3, {self: null, key: null, value: null},
737
["self", "key", "value"], arguments, {}, null, null)
738
return dict.$setitem($.self, $.key, $.value)
739
}
Nov 21, 2015
740
741
dict.$setitem = function(self, key, value, $hash){
742
// Set a dictionary item mapping key and value.
743
//
744
// If key is a string, set:
745
// - $string_dict[key] = [value, order] where "order" is an auto-increment
746
// unique id to keep track of insertion order
747
// - $str_hash[hash(key)] to key
748
//
749
// If key is a number, set $numeric_dict[key] = value
750
//
751
// If key is another object, compute its hash value:
752
// - if the hash is a key of $str_hash, and key == $str_hash[hash],
753
// replace $string_dict[$str_hash[hash]] by value
754
// - if the hash is a key of $numeric_dict, and hash == key, replace
755
// $numeric_dict[hash] by value
756
// - if the hash is a key of $object_dict: $object_dict[hash] is a list
757
// of [k, v] pairs. If key is equal to one of the "k", replace the
758
// matching v by value. Otherwise, add [key, value] to the list
759
// - else set $object_dict[hash] = [[key, value]]
760
//
761
// In all cases, increment attribute $version, used to detect dictionary
762
// changes during an iteration.
764
// Parameter $hash is only set if this method is called by setdefault.
765
// In this case the hash of key has already been computed and we
766
// know that the key is not present in the dictionary, so it's no
767
// use computing hash(key) again, nor testing equality of keys
769
if(self.$from_js){
770
// dictionary created by method to_dict of JSObj instances
771
value = $B.pyobj2jsobj(value)
772
}
773
if(self.$jsobj.__class__ === _b_.type){
774
self.$jsobj[key] = value
775
if(key == "__init__" || key == "__new__"){
776
// If class attribute __init__ or __new__ are reset,
777
// the factory function has to change
778
self.$jsobj.$factory = $B.$instance_creator(self.$jsobj)
779
}
780
}else{
781
self.$jsobj[key] = value
785
if(key instanceof String){
786
key = key.valueOf()
787
}
789
switch(typeof key){
790
case "string":
791
if(self.$string_dict === undefined){
792
console.log("pas de string dict", self, key, value)
793
}
794
if(self.$string_dict[key] !== undefined){
795
self.$string_dict[key][0] = value
796
}else{
797
self.$string_dict[key] = [value, self.$order++]
798
self.$str_hash[str_hash(key)] = key
799
self.$version++
800
}
801
return $N
802
case "number":
803
if(self.$numeric_dict[key] !== undefined){
804
// existing key: preserve order
805
self.$numeric_dict[key][0] = value
806
}else{
807
// special case for 0 and 1 if True or False are keys
808
var done = false
809
if((key == 0 || key == 1) &&
810
self.$object_dict[key] !== undefined){
811
for(const item of self.$object_dict[key]){
812
if((key == 0 && item[0] === false) ||
813
(key == 1 && item[0] === true)){
814
// replace value
815
item[1][0] = value
816
done = true
817
}
818
}
819
}
820
if(! done){
821
// new key
822
self.$numeric_dict[key] = [value, self.$order++]
823
}
826
return $N
827
case "boolean":
828
// true replaces 1 and false replaces 0
829
var num = key ? 1 : 0
830
if(self.$numeric_dict[num] !== undefined){
831
var order = self.$numeric_dict[num][1] // preserve order
832
self.$numeric_dict[num] = [value, order]
833
return
834
}
835
if(self.$object_dict[num] !== undefined){
836
self.$object_dict[num].push([key, [value, self.$order++]])
837
}else{
838
self.$object_dict[num] = [[key, [value, self.$order++]]]
839
}
842
// if we got here the key is more complex, use default method
843
844
var hash = $hash === undefined ? _b_.hash(key) : $hash,
845
_eq = function(other){return $B.rich_comp("__eq__", key, other)}
846
847
if(self.$numeric_dict[hash] !== undefined && _eq(hash)){
848
self.$numeric_dict[hash] = [value, self.$numeric_dict[hash][1]]
852
var sk = self.$str_hash[hash]
853
if(sk !== undefined && _eq(sk)){
854
self.$string_dict[sk] = [value, self.$string_dict[sk][1]]
859
// If $setitem is called from setdefault, don't test equality of key
860
// with any object
861
if($hash){
862
if(self.$object_dict[$hash] !== undefined){
863
self.$object_dict[$hash].push([key, [value, self.$order++]])
865
self.$object_dict[$hash] = [[key, [value, self.$order++]]]
866
}
867
self.$version++
868
return $N
869
}
870
var ix = rank(self, hash, key)
871
if(ix > -1){
872
// reset value
873
self.$object_dict[hash][ix][1] = [value,
874
self.$object_dict[hash][ix][1][1]]
875
return $N
876
}else if(self.$object_dict.hasOwnProperty(hash)){
877
self.$object_dict[hash].push([key, [value, self.$order++]])
879
self.$object_dict[hash] = [[key, [value, self.$order++]]]
Sep 5, 2014
883
}
884
885
// add "reflected" methods
Feb 11, 2018
886
$B.make_rmethods(dict)
Sep 5, 2014
887
Feb 11, 2018
888
dict.clear = function(){
Sep 5, 2014
889
// Remove all items from the dictionary.
Mar 7, 2018
890
var $ = $B.args("clear", 1, {self: null}, ["self"], arguments, {},
891
null, null),
892
self = $.self
894
self.$numeric_dict = {}
895
self.$string_dict = {}
896
self.$str_hash = {}
897
self.$object_dict = {}
899
if(self.$jsobj){
900
for(var attr in self.$jsobj){
Mar 7, 2018
901
if(attr.charAt(0) !== "$" && attr !== "__class__"){
902
delete self.$jsobj[attr]
903
}
904
}
905
}
Sep 5, 2014
909
}
910
Feb 11, 2018
911
dict.copy = function(self){
Sep 5, 2014
912
// Return a shallow copy of the dictionary
Mar 7, 2018
913
var $ = $B.args("copy", 1, {self: null},["self"], arguments,{},
914
null, null),
915
self = $.self,
Sep 5, 2014
918
return res
919
}
920
Feb 11, 2018
921
dict.fromkeys = function(){
Nov 21, 2015
922
Mar 7, 2018
923
var $ = $B.args("fromkeys", 3, {cls: null, keys: null, value: null},
924
["cls", "keys", "value"], arguments, {value: _b_.None}, null, null),
925
keys = $.keys,
926
value = $.value
Sep 5, 2014
928
// class method
929
var klass = $.cls,
Sep 5, 2014
933
while(1){
934
try{
935
var key = _b_.next(keys_iter)
936
if(klass === dict){dict.$setitem(res, key, value)}
937
else{$B.$getattr(res, "__setitem__")(key, value)}
Sep 5, 2014
938
}catch(err){
939
if($B.is_exc(err, [_b_.StopIteration])){
Sep 5, 2014
940
return res
941
}
942
throw err
943
}
944
}
945
}
946
Feb 11, 2018
947
dict.get = function(){
Mar 7, 2018
948
var $ = $B.args("get", 3, {self: null, key: null, _default: null},
949
["self", "key", "_default"], arguments, {_default: $N}, null, null)
951
try{
952
// call $getitem with ignore_missign set to true
953
return dict.$getitem($.self, $.key, true)
954
}catch(err){
955
if(_b_.isinstance(err, _b_.KeyError)){return $._default}
956
else{throw err}
957
}
958
}
959
960
var dict_items = $B.make_view("dict_items", true)
961
dict_items.$iterator = $B.make_iterator_class("dict_itemiterator")
962
Feb 11, 2018
963
dict.items = function(self){
Mar 23, 2018
964
if(arguments.length > 1){
965
var _len = arguments.length - 1,
966
_msg = "items() takes no arguments (" + _len + " given)"
967
throw _b_.TypeError.$factory(_msg)
968
}
969
var items = to_list(self),
970
set_like = true
971
// Check if all values are hashable
972
for(var i = 0, len = items.length; i < len; i++){
973
try{
974
_b_.hash(items[i][1])
975
}catch(err){
976
set_like = false
977
break
978
}
979
}
980
var values = to_list(self)
981
var it = dict_items.$factory(self, values, set_like)
982
it.dict_version = self.$version
984
}
985
987
var dict_keys = $B.make_view("dict_keys")
988
dict_keys.$iterator = $B.make_iterator_class("dict_keyiterator")
Nov 21, 2015
989
Mar 23, 2018
991
if(arguments.length > 1){
992
var _len = arguments.length - 1,
993
_msg = "keys() takes no arguments (" + _len + " given)"
994
throw _b_.TypeError.$factory(_msg)
Nov 21, 2015
995
}
996
var it = dict_keys.$factory(self, to_list(self, 0), true)
997
it.dict_version = self.$version
Nov 21, 2015
999
}
1000
Feb 11, 2018
1001
dict.pop = function(){
Nov 21, 2015
1002
1003
var missing = {},
1004
$ = $B.args("pop", 3, {self: null, key: null, _default: null},
1005
["self", "key", "_default"], arguments, {_default: missing}, null, null),
1006
self = $.self,
1007
key = $.key,
1008
_default = $._default
Nov 21, 2015
1009
Sep 5, 2014
1010
try{
1011
var res = dict.__getitem__(self, key)
1012
dict.__delitem__(self, key)
Sep 5, 2014
1013
return res
1014
}catch(err){
1015
if(err.__class__ === _b_.KeyError){
1016
if(_default !== missing){return _default}
Sep 5, 2014
1017
throw err
1018
}
1019
throw err
1020
}
1021
}
1022
Feb 11, 2018
1023
dict.popitem = function(self){
1025
var itm = _b_.next(_b_.iter(dict.items(self)))
1026
dict.__delitem__(self, itm[0])
Feb 11, 2018
1027
return _b_.tuple.$factory(itm)
1029
if (err.__class__ == _b_.StopIteration) {
1030
throw _b_.KeyError.$factory("'popitem(): dictionary is empty'")
Sep 5, 2014
1033
}
1034
Feb 11, 2018
1035
dict.setdefault = function(){
Nov 21, 2015
1036
Mar 7, 2018
1037
var $ = $B.args("setdefault", 3, {self: null, key: null, _default: null},
1038
["self", "key", "_default"], arguments, {_default: $N}, null, null),
1039
self = $.self,
1040
key = $.key,
1041
_default = $._default
1042
try{
1043
// Pass 3rd argument to dict.$getitem to avoid using __missing__
1044
// Cf. issue #1598
1045
return dict.$getitem(self, key, true)
1046
}catch(err){
1047
if(err.__class__ !== _b_.KeyError){
1048
throw err
1049
}
1050
if(_default === undefined){_default = $N}
1051
var hash = key.$hash
1052
key.$hash = undefined
1053
dict.$setitem(self, key, _default, hash)
Sep 5, 2014
1054
return _default
1055
}
1056
}
1057
Feb 11, 2018
1058
dict.update = function(self){
Nov 21, 2015
1059
Mar 7, 2018
1060
var $ = $B.args("update", 1, {"self": null}, ["self"], arguments,
1061
{}, "args", "kw"),
1062
self = $.self,
1063
args = $.args,
1064
kw = $.kw
1065
if(args.length > 0){
1066
var o = args[0]
1068
if(o.$jsobj){
1069
o = jsobj2dict(o.$jsobj)
1070
}
1072
}else if(_b_.hasattr(o, "keys")){
1073
var _keys = _b_.list.$factory($B.$call($B.$getattr(o, "keys"))())
1074
for(var i = 0, len = _keys.length; i < len; i++){
1075
var _value = getattr(o, "__getitem__")(_keys[i])
1076
dict.$setitem(self, _keys[i], _value)
1077
}
1078
}else{
1079
var it = _b_.iter(o),
1080
i = 0
1081
while(true){
1082
try{
1083
var item = _b_.next(it)
1084
}catch(err){
1085
if(err.__class__ === _b_.StopIteration){break}
1086
throw err
1087
}
1088
try{
1089
key_value = _b_.list.$factory(item)
1090
}catch(err){
1091
throw _b_.TypeError.$factory("cannot convert dictionary" +
1092
" update sequence element #" + i + " to a sequence")
1093
}
1094
if(key_value.length !== 2){
1095
throw _b_.ValueError.$factory("dictionary update " +
1096
"sequence element #" + i + " has length " +
1097
key_value.length + "; 2 is required")
1098
}
1099
dict.$setitem(self, key_value[0], key_value[1])
1100
i++
Sep 5, 2014
1103
}
Sep 5, 2014
1107
}
1108
1109
var dict_values = $B.make_view("dict_values")
1110
dict_values.$iterator = $B.make_iterator_class("dict_valueiterator")
Nov 21, 2015
1111
Feb 11, 2018
1112
dict.values = function(self){
Mar 23, 2018
1113
if(arguments.length > 1){
1114
var _len = arguments.length - 1,
1115
_msg = "values() takes no arguments (" + _len + " given)"
1116
throw _b_.TypeError.$factory(_msg)
Nov 21, 2015
1117
}
1118
var values = to_list(self, 1)
1119
var it = dict_values.$factory(self, values, false)
1120
it.dict_version = self.$version
Nov 21, 2015
1122
}
1123
1124
dict.$factory = function(){
1125
var res = dict.__new__(dict)
1126
var args = [res]
1127
for(var i = 0, len = arguments.length; i < len ; i++){
1128
args.push(arguments[i])
1129
}
1130
dict.__init__.apply(null, args)
Sep 5, 2014
1131
return res
1132
}
Sep 5, 2014
1134
_b_.dict = dict
Feb 11, 2018
1136
$B.set_func_names(dict, "builtins")
1137
1138
dict.__class_getitem__ = _b_.classmethod.$factory(dict.__class_getitem__)
1139
1140
$B.empty_dict = function(){
1141
return {
1142
__class__: dict,
1143
$numeric_dict : {},
1144
$object_dict : {},
1145
$string_dict : {},
1146
$str_hash: {},
1147
$version: 0,
1148
$order: 0
1152
// This must be done after set_func_names, otherwise dict.fromkeys doesn't
1153
// have the attribute $infos
1154
dict.fromkeys = _b_.classmethod.$factory(dict.fromkeys)
1155
1156
$B.getset_descriptor = $B.make_class("getset_descriptor",
1157
function(klass, attr){
1158
return {
1159
__class__: $B.getset_descriptor,
1160
__doc__: _b_.None,
1161
cls: klass,
1162
attr: attr
1163
}
1164
}
1165
)
1166
1167
$B.getset_descriptor.__repr__ = $B.getset_descriptor.__str__ = function(self){
1168
return `<attribute '${self.attr}' of '${self.cls.$infos.__name__}' objects>`
1169
}
1170
1171
$B.set_func_names($B.getset_descriptor, "builtins")
1172
1173
// Class for attribute __dict__ of classes
1174
var mappingproxy = $B.mappingproxy = $B.make_class("mappingproxy",
Feb 12, 2018
1175
function(obj){
1176
if(_b_.isinstance(obj, dict)){
1177
// obj is a dictionary, with $string_dict table such that
1178
// obj.$string_dict[key] = [value, rank]
1179
// Transform it into an object with attribute $jsobj such that
1180
// res.$jsobj[key] = value
1181
var res = $B.obj_dict(dict.$to_obj(obj))
1182
}else{
1183
var res = $B.obj_dict(obj)
1184
}
Feb 12, 2018
1185
res.__class__ = mappingproxy
1186
return res
1187
}
1188
)
1190
mappingproxy.$match_mapping_pattern = true // for pattern matching (PEP 634)
1191
Feb 12, 2018
1192
mappingproxy.__setitem__ = function(){
Mar 7, 2018
1193
throw _b_.TypeError.$factory("'mappingproxy' object does not support " +
1194
"item assignment")
1197
for(var attr in dict){
1198
if(mappingproxy[attr] !== undefined ||
1199
["__class__", "__mro__", "__new__", "__init__", "__delitem__",
1200
"clear", "fromkeys", "pop", "popitem", "setdefault",
1201
"update"].indexOf(attr) > -1){
1202
continue
1203
}
1204
if(typeof dict[attr] == "function"){
1205
mappingproxy[attr] = (function(key){
1206
return function(){
1207
return dict[key].apply(null, arguments)
1208
}
1209
})(attr)
1210
}else{
1211
mappingproxy[attr] = dict[attr]
1212
}
1213
}
1214
Feb 12, 2018
1215
$B.set_func_names(mappingproxy, "builtins")
Mar 7, 2018
1220
if(attr.charAt(0) != "$" && attr !== "__class__"){
1221
if(x[attr] === null){
1222
d.$string_dict[attr] = [_b_.None, d.$order++]
1223
}else if(x[attr] === undefined){
1224
continue
1225
}else if(x[attr].$jsobj === x){
1226
d.$string_dict[attr] = [d, d.$order++]
1228
d.$string_dict[attr] = [$B.$JS2Py(x[attr]), d.$order++]
1230
}
1231
}
1232
return d
1233
}
1235
$B.obj_dict = function(obj, from_js){
1236
var klass = obj.__class__ || $B.get_class(obj)
1237
if(klass !== undefined && klass.$native){
1238
throw _b_.AttributeError.$factory("'" + $B.class_name(obj) +
1239
"' object has no attribute '__dict__'")}
1241
res.$jsobj = obj
1242
res.$from_js = from_js // set to true if
1243
return res
1244
}
1245
Sep 5, 2014
1246
})(__BRYTHON__)