Skip to content
Permalink
Newer
Older
100644 1239 lines (1118 sloc) 36.4 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(){
Nov 21, 2015
280
281
var $ = $B.args("__contains__", 2, {self: null, key: null},
282
["self", "key"], arguments, {}, null, null),
283
self = $.self,
285
if(self.$is_namespace){key = $B.to_alias(key)} // issue 1244
286
287
if(self.$jsobj){
288
return self.$jsobj[key] !== undefined
289
}
291
switch(typeof key) {
293
return self.$string_dict[key] !== undefined
295
return self.$numeric_dict[key] !== undefined
296
}
297
298
var hash = _b_.hash(key)
299
if(self.$str_hash[hash] !== undefined &&
300
$B.rich_comp("__eq__", key, self.$str_hash[hash])){return true}
301
if(self.$numeric_dict[hash] !== undefined &&
302
$B.rich_comp("__eq__", key, hash)){return true}
303
return rank(self, hash, key) > -1
Sep 5, 2014
304
}
305
Feb 11, 2018
306
dict.__delitem__ = function(){
Nov 21, 2015
307
308
var $ = $B.args("__eq__", 2, {self: null, arg: null},
309
["self", "arg"], arguments, {}, null, null),
310
self = $.self,
Nov 21, 2015
312
313
if(self.$jsobj){
314
if(self.$jsobj[arg] === undefined){throw _b_.KeyError.$factory(arg)}
315
delete self.$jsobj[arg]
318
switch(typeof arg){
319
case "string":
320
if(self.$string_dict[arg] === undefined){
321
throw _b_.KeyError.$factory(_b_.str.$factory(arg))
322
}
323
delete self.$string_dict[arg]
324
delete self.$str_hash[str_hash(arg)]
326
return $N
327
case "number":
328
if(self.$numeric_dict[arg] === undefined){
329
throw _b_.KeyError.$factory(_b_.str.$factory(arg))
331
delete self.$numeric_dict[arg]
335
// go with defaults
336
337
var hash = _b_.hash(arg),
338
ix
340
if((ix = rank(self, hash, arg)) > -1){
341
self.$object_dict[hash].splice(ix, 1)
342
}else{
343
throw _b_.KeyError.$factory(_b_.str.$factory(arg))
Sep 5, 2014
348
}
349
Feb 11, 2018
350
dict.__eq__ = function(){
Mar 7, 2018
351
var $ = $B.args("__eq__", 2, {self: null, other: null},
352
["self", "other"], arguments, {}, null, null),
353
self = $.self,
354
other = $.other
356
if(! _b_.isinstance(other, dict)){return false}
358
if(self.$jsobj){self = jsobj2dict(self.$jsobj)}
359
if(other.$jsobj){other = jsobj2dict(other.$jsobj)}
360
if(dict.__len__(self) != dict.__len__(other)){
361
return false
362
}
364
if(self.$string_dict.length != other.$string_dict.length){
368
for(var k in self.$numeric_dict){
369
if(other.$numeric_dict.hasOwnProperty(k)){
370
if(!$B.rich_comp("__eq__", other.$numeric_dict[k][0],
371
self.$numeric_dict[k][0])){
372
return false
373
}
374
}else if(other.$object_dict.hasOwnProperty(k)){
375
var pairs = other.$object_dict[k],
376
flag = false
377
for(var i = 0, len = pairs.length; i < len; i++){
378
if($B.rich_comp("__eq__", k, pairs[i][0]) &&
379
$B.rich_comp("__eq__", self.$numeric_dict[k],
380
pairs[i][1])){
381
flag = true
382
break
383
}
385
if(! flag){return false}
Nov 21, 2015
388
}
389
}
390
for(var k in self.$string_dict){
391
if(!other.$string_dict.hasOwnProperty(k) ||
392
!$B.rich_comp("__eq__", other.$string_dict[k][0],
393
self.$string_dict[k][0])){
Nov 21, 2015
395
}
396
}
397
for(var hash in self.$object_dict){
398
var pairs = self.$object_dict[hash]
399
// Get all (key, value) pairs in other that have the same hash
400
var other_pairs = []
401
if(other.$numeric_dict[hash] !== undefined){
402
other_pairs.push([hash, other.$numeric_dict[hash]])
403
}
404
if(other.$object_dict[hash] !== undefined){
405
other_pairs = other_pairs.concat(other.$object_dict[hash])
406
}
407
if(other_pairs.length == 0){
408
return false
409
}
410
for(var i = 0, len_i = pairs.length; i < len_i; i++){
411
var flag = false
412
var key = pairs[i][0],
413
value = pairs[i][1][0]
414
for(var j = 0, len_j = other_pairs.length; j < len_j; j++){
415
if($B.rich_comp("__eq__", key, other_pairs[j][0]) &&
416
$B.rich_comp("__eq__", value, other_pairs[j][1][0])){
417
flag = true
418
break
424
}
425
}
426
return true
Sep 5, 2014
427
}
428
Feb 11, 2018
429
dict.__getitem__ = function(){
430
var $ = $B.args("__getitem__", 2, {self: null, arg: null},
431
["self", "arg"], arguments, {}, null, null),
432
self = $.self,
434
return dict.$getitem(self, arg)
435
}
436
437
$B.string_count = 0
438
$B.num_count = 0
439
dict.$getitem = function(self, arg, ignore_missing){
440
// ignore_missing is only set in dict.setdefault
441
if(self.$jsobj){
442
if(self.$jsobj[arg] === undefined){
443
if(self.$jsobj.hasOwnProperty(arg)){
445
}
446
throw _b_.KeyError.$factory(arg)
447
}
448
return self.$jsobj[arg]
450
451
switch(typeof arg){
452
case "string":
453
var x = self.$string_dict[arg]
454
if(x !== undefined){
455
$B.string_count++
456
return x[0]
458
break
459
case "number":
460
if(self.$numeric_dict[arg] !== undefined){
462
return self.$numeric_dict[arg][0]
464
break
465
}
466
467
// since the key is more complex use 'default' method of getting item
468
469
var hash = _b_.hash(arg),
470
_eq = function(other){return $B.rich_comp("__eq__", arg, other)}
471
472
if(typeof arg == "object"){
473
arg.$hash = hash // cache for setdefault
474
}
475
var sk = self.$str_hash[hash]
476
if(sk !== undefined && _eq(sk)){
477
return self.$string_dict[sk][0]
479
if(self.$numeric_dict[hash] !== undefined && _eq(hash)){
480
return self.$numeric_dict[hash][0]
482
if(_b_.isinstance(arg, _b_.str)){
483
// string subclass
484
var res = self.$string_dict[arg.valueOf()]
485
if(res !== undefined){return res[0]}
488
var ix = rank(self, hash, arg)
489
if(ix > -1){
490
return self.$object_dict[hash][ix][1][0]
493
if(! ignore_missing){
494
if(self.__class__ !== dict && ! ignore_missing){
495
try{
496
var missing_method = getattr(self.__class__, "__missing__",
497
_b_.None)
498
}catch(err){
499
console.log(err)
501
}
502
if(missing_method !== _b_.None){
503
return missing_method(self, arg)
504
}
507
throw _b_.KeyError.$factory(arg)
Sep 5, 2014
508
}
509
510
dict.__hash__ = _b_.None
Sep 5, 2014
511
512
function init_from_list(self, args){
513
var i = -1,
514
stop = args.length - 1,
515
si = dict.__setitem__
516
while(i++ < stop){
517
var item = args[i]
518
if(item.length != 2){
519
throw _b_.ValueError.$factory("dictionary " +
520
`update sequence element #${i} has length 1; 2 is required`)
521
}
522
switch(typeof item[0]) {
523
case 'string':
524
self.$string_dict[item[0]] = [item[1], self.$order++]
525
self.$str_hash[str_hash(item[0])] = item[0]
526
self.$version++
527
break
528
case 'number':
529
if(item[0] != 0 && item[0] != 1){
530
self.$numeric_dict[item[0]] = [item[1], self.$order++]
531
self.$version++
532
break
533
}
534
default:
535
si(self, item[0], item[1])
536
break
537
}
538
}
539
}
540
541
dict.__init__ = function(self, first, second){
543
if(first === undefined){return $N}
544
if(second === undefined){
545
if(first.$nat != 'kw' && $B.get_class(first) === $B.JSObj){
546
for(var key in first){
547
self.$string_dict[key] = [first[key], self.$order++]
548
}
549
return _b_.None
550
}else if(first.$jsobj){
551
self.$jsobj = {}
552
for(var attr in first.$jsobj){
553
self.$jsobj[attr] = first.$jsobj[attr]
556
}else if(Array.isArray(first)){
557
init_from_list(self, first)
558
return $N
Sep 5, 2014
559
}
562
$ = $ || $B.args("dict", 1, {self:null}, ["self"],
563
arguments, {}, "first", "second")
564
var args = $.first
565
if(args.length > 1){
566
throw _b_.TypeError.$factory("dict expected at most 1 argument" +
567
", got 2")
568
}else if(args.length == 1){
569
args = args[0]
570
if(args.__class__ === dict){
571
['$string_dict', '$str_hash', '$numeric_dict', '$object_dict'].
572
forEach(function(d){
573
for(key in args[d]){self[d][key] = args[d][key]}
574
})
575
}else if(_b_.isinstance(args, dict)){
578
var keys = $B.$getattr(args, "keys", null)
579
if(keys !== null){
580
var gi = $B.$getattr(args, "__getitem__", null)
581
if(gi !== null){
582
// has keys and __getitem__ : it's a mapping, iterate on
583
// keys and values
584
gi = $B.$call(gi)
585
var kiter = _b_.iter($B.$call(keys)())
586
while(true){
587
try{
588
var key = _b_.next(kiter),
589
value = gi(key)
590
dict.__setitem__(self, key, value)
591
}catch(err){
592
if(err.__class__ === _b_.StopIteration){
593
break
594
}
595
throw err
596
}
597
}
598
return $N
599
}
600
}
601
if(! Array.isArray(args)){
602
args = _b_.list.$factory(args)
603
}
604
// Form "dict([[key1, value1], [key2,value2], ...])"
605
init_from_list(self, args)
Sep 5, 2014
606
}
608
var kw = $.second.$string_dict
609
for(var attr in kw){
610
switch(typeof attr){
611
case "string":
612
self.$string_dict[attr] = [kw[attr][0], self.$order++]
613
self.$str_hash[str_hash(attr)] = attr
614
break
615
case "number":
616
self.$numeric_dict[attr] = [kw[attr][0], self.$order++]
619
si(self, attr, kw[attr][0])
Sep 5, 2014
624
}
625
Feb 11, 2018
626
dict.__iter__ = function(self) {
627
return _b_.iter(dict.$$keys(self))
Sep 5, 2014
628
}
629
630
dict.__ior__ = function(self, other){
631
// PEP 584
632
dict.update(self, other)
633
return self
634
}
635
Feb 11, 2018
636
dict.__len__ = function(self) {
639
if(self.$jsobj){
Mar 7, 2018
640
for(var attr in self.$jsobj){if(attr.charAt(0) != "$"){_count++}}
641
return _count
642
}
644
for(var k in self.$numeric_dict){_count++}
645
for(var k in self.$string_dict){_count++}
646
for(var hash in self.$object_dict){
647
_count += self.$object_dict[hash].length
648
}
Sep 5, 2014
652
Mar 7, 2018
653
dict.__ne__ = function(self, other){return ! dict.__eq__(self, other)}
Sep 5, 2014
654
Feb 11, 2018
655
dict.__new__ = function(cls){
656
if(cls === undefined){
Mar 7, 2018
657
throw _b_.TypeError.$factory("int.__new__(): not enough arguments")
659
var instance = {
661
$numeric_dict : {},
662
$object_dict : {},
665
$version: 0,
666
$order: 0
668
if(cls !== dict){
669
instance.__dict__ = $B.empty_dict()
670
}
671
return instance
674
dict.__or__ = function(self, other){
675
// PEP 584
676
if(! _b_.isinstance(other, dict)){
677
return _b_.NotImplemented
678
}
679
var res = dict.copy(self)
680
dict.update(res, other)
681
return res
682
}
683
684
function __newobj__(){
685
// __newobj__ is called with a generator as only argument
686
var $ = $B.args('__newobj__', 0, {}, [], arguments, {}, 'args', null),
687
args = $.args
688
var res = $B.empty_dict()
689
res.__class__ = args[0]
690
return res
691
}
692
693
dict.__reduce_ex__ = function(self, protocol){
694
return $B.fast_tuple([
695
__newobj__,
696
$B.fast_tuple([self.__class__]),
697
_b_.None,
698
_b_.None,
699
dict.items(self)])
700
}
701
Feb 11, 2018
702
dict.__repr__ = function(self){
703
$B.builtins_repr_check(dict, arguments) // in brython_builtins.js
704
if(self.$jsobj){ // wrapper around Javascript object
Feb 11, 2018
705
return dict.__repr__(jsobj2dict(self.$jsobj))
707
if($B.repr.enter(self)){
708
return "{...}"
709
}
710
var res = [],
712
items.forEach(function(item){
713
try{
714
res.push(repr(item[0]) + ": " + repr(item[1]))
715
}catch(err){
716
throw err
717
}
719
$B.repr.leave(self)
Mar 7, 2018
720
return "{" + res.join(", ") + "}"
Sep 5, 2014
721
}
722
723
dict.__ror__ = function(self, other){
724
// PEP 584
725
if(! _b_.isinstance(other, dict)){
726
return _b_.NotImplemented
727
}
728
var res = dict.copy(other)
729
dict.update(res, self)
730
return res
731
}
732
733
dict.__setitem__ = function(self, key, value){
Mar 7, 2018
734
var $ = $B.args("__setitem__", 3, {self: null, key: null, value: null},
735
["self", "key", "value"], arguments, {}, null, null)
736
return dict.$setitem($.self, $.key, $.value)
737
}
Nov 21, 2015
738
739
dict.$setitem = function(self, key, value, $hash){
740
// Set a dictionary item mapping key and value.
741
//
742
// If key is a string, set:
743
// - $string_dict[key] = [value, order] where "order" is an auto-increment
744
// unique id to keep track of insertion order
745
// - $str_hash[hash(key)] to key
746
//
747
// If key is a number, set $numeric_dict[key] = value
748
//
749
// If key is another object, compute its hash value:
750
// - if the hash is a key of $str_hash, and key == $str_hash[hash],
751
// replace $string_dict[$str_hash[hash]] by value
752
// - if the hash is a key of $numeric_dict, and hash == key, replace
753
// $numeric_dict[hash] by value
754
// - if the hash is a key of $object_dict: $object_dict[hash] is a list
755
// of [k, v] pairs. If key is equal to one of the "k", replace the
756
// matching v by value. Otherwise, add [key, value] to the list
757
// - else set $object_dict[hash] = [[key, value]]
758
//
759
// In all cases, increment attribute $version, used to detect dictionary
760
// changes during an iteration.
762
// Parameter $hash is only set if this method is called by setdefault.
763
// In this case the hash of key has already been computed and we
764
// know that the key is not present in the dictionary, so it's no
765
// use computing hash(key) again, nor testing equality of keys
767
if(self.$from_js){
768
// dictionary created by method to_dict of JSObj instances
769
value = $B.pyobj2jsobj(value)
770
}
771
if(self.$jsobj.__class__ === _b_.type){
772
self.$jsobj[key] = value
773
if(key == "__init__" || key == "__new__"){
774
// If class attribute __init__ or __new__ are reset,
775
// the factory function has to change
776
self.$jsobj.$factory = $B.$instance_creator(self.$jsobj)
777
}
778
}else{
779
self.$jsobj[key] = value
784
switch(typeof key){
785
case "string":
786
if(self.$string_dict === undefined){
787
console.log("pas de string dict", self, key, value)
788
}
789
if(self.$string_dict[key] !== undefined){
790
self.$string_dict[key][0] = value
791
}else{
792
self.$string_dict[key] = [value, self.$order++]
793
self.$str_hash[str_hash(key)] = key
794
self.$version++
795
}
796
return $N
797
case "number":
798
if(self.$numeric_dict[key] !== undefined){
799
// existing key: preserve order
800
self.$numeric_dict[key][0] = value
801
}else{
802
// special case for 0 and 1 if True or False are keys
803
var done = false
804
if((key == 0 || key == 1) &&
805
self.$object_dict[key] !== undefined){
806
for(const item of self.$object_dict[key]){
807
if((key == 0 && item[0] === false) ||
808
(key == 1 && item[0] === true)){
809
// replace value
810
item[1][0] = value
811
done = true
812
}
813
}
814
}
815
if(! done){
816
// new key
817
self.$numeric_dict[key] = [value, self.$order++]
818
}
821
return $N
822
case "boolean":
823
// true replaces 1 and false replaces 0
824
var num = key ? 1 : 0
825
if(self.$numeric_dict[num] !== undefined){
826
var order = self.$numeric_dict[num][1] // preserve order
827
self.$numeric_dict[num] = [value, order]
828
return
829
}
830
if(self.$object_dict[num] !== undefined){
831
self.$object_dict[num].push([key, [value, self.$order++]])
832
}else{
833
self.$object_dict[num] = [[key, [value, self.$order++]]]
834
}
837
// if we got here the key is more complex, use default method
838
839
var hash = $hash === undefined ? _b_.hash(key) : $hash,
840
_eq = function(other){return $B.rich_comp("__eq__", key, other)}
841
842
if(self.$numeric_dict[hash] !== undefined && _eq(hash)){
843
self.$numeric_dict[hash] = [value, self.$numeric_dict[hash][1]]
847
var sk = self.$str_hash[hash]
848
if(sk !== undefined && _eq(sk)){
849
self.$string_dict[sk] = [value, self.$string_dict[sk][1]]
854
// If $setitem is called from setdefault, don't test equality of key
855
// with any object
856
if($hash){
857
if(self.$object_dict[$hash] !== undefined){
858
self.$object_dict[$hash].push([key, [value, self.$order++]])
860
self.$object_dict[$hash] = [[key, [value, self.$order++]]]
861
}
862
self.$version++
863
return $N
864
}
865
var ix = rank(self, hash, key)
866
if(ix > -1){
867
// reset value
868
self.$object_dict[hash][ix][1] = [value,
869
self.$object_dict[hash][ix][1][1]]
870
return $N
871
}else if(self.$object_dict.hasOwnProperty(hash)){
872
self.$object_dict[hash].push([key, [value, self.$order++]])
874
self.$object_dict[hash] = [[key, [value, self.$order++]]]
Sep 5, 2014
878
}
879
880
// add "reflected" methods
Feb 11, 2018
881
$B.make_rmethods(dict)
Sep 5, 2014
882
Feb 11, 2018
883
dict.clear = function(){
Sep 5, 2014
884
// Remove all items from the dictionary.
Mar 7, 2018
885
var $ = $B.args("clear", 1, {self: null}, ["self"], arguments, {},
886
null, null),
887
self = $.self
889
self.$numeric_dict = {}
890
self.$string_dict = {}
891
self.$str_hash = {}
892
self.$object_dict = {}
894
if(self.$jsobj){
895
for(var attr in self.$jsobj){
Mar 7, 2018
896
if(attr.charAt(0) !== "$" && attr !== "__class__"){
897
delete self.$jsobj[attr]
898
}
899
}
900
}
Sep 5, 2014
904
}
905
Feb 11, 2018
906
dict.copy = function(self){
Sep 5, 2014
907
// Return a shallow copy of the dictionary
Mar 7, 2018
908
var $ = $B.args("copy", 1, {self: null},["self"], arguments,{},
909
null, null),
910
self = $.self,
Sep 5, 2014
913
return res
914
}
915
Feb 11, 2018
916
dict.fromkeys = function(){
Nov 21, 2015
917
Mar 7, 2018
918
var $ = $B.args("fromkeys", 3, {cls: null, keys: null, value: null},
919
["cls", "keys", "value"], arguments, {value: _b_.None}, null, null),
920
keys = $.keys,
921
value = $.value
Sep 5, 2014
923
// class method
924
var klass = $.cls,
Sep 5, 2014
928
while(1){
929
try{
930
var key = _b_.next(keys_iter)
931
if(klass === dict){dict.$setitem(res, key, value)}
932
else{$B.$getattr(res, "__setitem__")(key, value)}
Sep 5, 2014
933
}catch(err){
934
if($B.is_exc(err, [_b_.StopIteration])){
Sep 5, 2014
935
return res
936
}
937
throw err
938
}
939
}
940
}
941
Feb 11, 2018
942
dict.get = function(){
Mar 7, 2018
943
var $ = $B.args("get", 3, {self: null, key: null, _default: null},
944
["self", "key", "_default"], arguments, {_default: $N}, null, null)
Feb 11, 2018
946
try{return dict.__getitem__($.self, $.key)}
947
catch(err){
948
if(_b_.isinstance(err, _b_.KeyError)){return $._default}
949
else{throw err}
950
}
951
}
952
953
var dict_items = $B.make_view("dict_items", true)
954
dict_items.$iterator = $B.make_iterator_class("dict_itemiterator")
955
Feb 11, 2018
956
dict.items = function(self){
Mar 23, 2018
957
if(arguments.length > 1){
958
var _len = arguments.length - 1,
959
_msg = "items() takes no arguments (" + _len + " given)"
960
throw _b_.TypeError.$factory(_msg)
961
}
962
var items = to_list(self),
963
set_like = true
964
// Check if all values are hashable
965
for(var i = 0, len = items.length; i < len; i++){
966
try{
967
_b_.hash(items[i][1])
968
}catch(err){
969
set_like = false
970
break
971
}
972
}
973
var values = to_list(self)
974
var it = dict_items.$factory(self, values, set_like)
975
it.dict_version = self.$version
977
}
978
980
var dict_keys = $B.make_view("dict_keys")
981
dict_keys.$iterator = $B.make_iterator_class("dict_keyiterator")
Nov 21, 2015
982
Mar 23, 2018
984
if(arguments.length > 1){
985
var _len = arguments.length - 1,
986
_msg = "keys() takes no arguments (" + _len + " given)"
987
throw _b_.TypeError.$factory(_msg)
Nov 21, 2015
988
}
989
var it = dict_keys.$factory(self, to_list(self, 0), true)
990
it.dict_version = self.$version
Nov 21, 2015
992
}
993
Feb 11, 2018
994
dict.pop = function(){
Nov 21, 2015
995
996
var missing = {},
997
$ = $B.args("pop", 3, {self: null, key: null, _default: null},
998
["self", "key", "_default"], arguments, {_default: missing}, null, null),
999
self = $.self,
1000
key = $.key,
1001
_default = $._default
Nov 21, 2015
1002
Sep 5, 2014
1003
try{
1004
var res = dict.__getitem__(self, key)
1005
dict.__delitem__(self, key)
Sep 5, 2014
1006
return res
1007
}catch(err){
1008
if(err.__class__ === _b_.KeyError){
1009
if(_default !== missing){return _default}
Sep 5, 2014
1010
throw err
1011
}
1012
throw err
1013
}
1014
}
1015
Feb 11, 2018
1016
dict.popitem = function(self){
1018
var itm = _b_.next(_b_.iter(dict.items(self)))
1019
dict.__delitem__(self, itm[0])
Feb 11, 2018
1020
return _b_.tuple.$factory(itm)
1022
if (err.__class__ == _b_.StopIteration) {
1023
throw _b_.KeyError.$factory("'popitem(): dictionary is empty'")
Sep 5, 2014
1026
}
1027
Feb 11, 2018
1028
dict.setdefault = function(){
Nov 21, 2015
1029
Mar 7, 2018
1030
var $ = $B.args("setdefault", 3, {self: null, key: null, _default: null},
1031
["self", "key", "_default"], arguments, {_default: $N}, null, null),
1032
self = $.self,
1033
key = $.key,
1034
_default = $._default
1035
try{
1036
// Pass 3rd argument to dict.$getitem to avoid using __missing__
1037
// Cf. issue #1598
1038
return dict.$getitem(self, key, true)
1039
}catch(err){
1040
if(err.__class__ !== _b_.KeyError){
1041
throw err
1042
}
1043
if(_default === undefined){_default = $N}
1044
var hash = key.$hash
1045
key.$hash = undefined
1046
dict.$setitem(self, key, _default, hash)
Sep 5, 2014
1047
return _default
1048
}
1049
}
1050
Feb 11, 2018
1051
dict.update = function(self){
Nov 21, 2015
1052
Mar 7, 2018
1053
var $ = $B.args("update", 1, {"self": null}, ["self"], arguments,
1054
{}, "args", "kw"),
1055
self = $.self,
1056
args = $.args,
1057
kw = $.kw
1058
if(args.length > 0){
1059
var o = args[0]
1061
if(o.$jsobj){
1062
o = jsobj2dict(o.$jsobj)
1063
}
1065
}else if(_b_.hasattr(o, "keys")){
1066
var _keys = _b_.list.$factory($B.$call($B.$getattr(o, "keys"))())
1067
for(var i = 0, len = _keys.length; i < len; i++){
1068
var _value = getattr(o, "__getitem__")(_keys[i])
1069
dict.$setitem(self, _keys[i], _value)
1070
}
1071
}else{
1072
var it = _b_.iter(o),
1073
i = 0
1074
while(true){
1075
try{
1076
var item = _b_.next(it)
1077
}catch(err){
1078
if(err.__class__ === _b_.StopIteration){break}
1079
throw err
1080
}
1081
try{
1082
key_value = _b_.list.$factory(item)
1083
}catch(err){
1084
throw _b_.TypeError.$factory("cannot convert dictionary" +
1085
" update sequence element #" + i + " to a sequence")
1086
}
1087
if(key_value.length !== 2){
1088
throw _b_.ValueError.$factory("dictionary update " +
1089
"sequence element #" + i + " has length " +
1090
key_value.length + "; 2 is required")
1091
}
1092
dict.$setitem(self, key_value[0], key_value[1])
1093
i++
Sep 5, 2014
1096
}
Sep 5, 2014
1100
}
1101
1102
var dict_values = $B.make_view("dict_values")
1103
dict_values.$iterator = $B.make_iterator_class("dict_valueiterator")
Nov 21, 2015
1104
Feb 11, 2018
1105
dict.values = function(self){
Mar 23, 2018
1106
if(arguments.length > 1){
1107
var _len = arguments.length - 1,
1108
_msg = "values() takes no arguments (" + _len + " given)"
1109
throw _b_.TypeError.$factory(_msg)
Nov 21, 2015
1110
}
1111
var values = to_list(self, 1)
1112
var it = dict_values.$factory(self, values, false)
1113
it.dict_version = self.$version
Nov 21, 2015
1115
}
1116
1117
dict.$factory = function(){
1118
var res = dict.__new__(dict)
1119
var args = [res]
1120
for(var i = 0, len = arguments.length; i < len ; i++){
1121
args.push(arguments[i])
1122
}
1123
dict.__init__.apply(null, args)
Sep 5, 2014
1124
return res
1125
}
Sep 5, 2014
1127
_b_.dict = dict
Feb 11, 2018
1129
$B.set_func_names(dict, "builtins")
1130
1131
dict.__class_getitem__ = _b_.classmethod.$factory(dict.__class_getitem__)
1132
1133
$B.empty_dict = function(){
1134
return {
1135
__class__: dict,
1136
$numeric_dict : {},
1137
$object_dict : {},
1138
$string_dict : {},
1139
$str_hash: {},
1140
$version: 0,
1141
$order: 0
1145
// This must be done after set_func_names, otherwise dict.fromkeys doesn't
1146
// have the attribute $infos
1147
dict.fromkeys = _b_.classmethod.$factory(dict.fromkeys)
1148
1149
$B.getset_descriptor = $B.make_class("getset_descriptor",
1150
function(klass, attr){
1151
return {
1152
__class__: $B.getset_descriptor,
1153
__doc__: _b_.None,
1154
cls: klass,
1155
attr: attr
1156
}
1157
}
1158
)
1159
1160
$B.getset_descriptor.__repr__ = $B.getset_descriptor.__str__ = function(self){
1161
return `<attribute '${self.attr}' of '${self.cls.$infos.__name__}' objects>`
1162
}
1163
1164
$B.set_func_names($B.getset_descriptor, "builtins")
1165
1166
// Class for attribute __dict__ of classes
1167
var mappingproxy = $B.mappingproxy = $B.make_class("mappingproxy",
Feb 12, 2018
1168
function(obj){
1169
if(_b_.isinstance(obj, dict)){
1170
// obj is a dictionary, with $string_dict table such that
1171
// obj.$string_dict[key] = [value, rank]
1172
// Transform it into an object with attribute $jsobj such that
1173
// res.$jsobj[key] = value
1174
var res = $B.obj_dict(dict.$to_obj(obj))
1175
}else{
1176
var res = $B.obj_dict(obj)
1177
}
Feb 12, 2018
1178
res.__class__ = mappingproxy
1179
return res
1180
}
1181
)
1183
mappingproxy.$match_mapping_pattern = true // for pattern matching (PEP 634)
1184
Feb 12, 2018
1185
mappingproxy.__setitem__ = function(){
Mar 7, 2018
1186
throw _b_.TypeError.$factory("'mappingproxy' object does not support " +
1187
"item assignment")
1190
for(var attr in dict){
1191
if(mappingproxy[attr] !== undefined ||
1192
["__class__", "__mro__", "__new__", "__init__", "__delitem__",
1193
"clear", "fromkeys", "pop", "popitem", "setdefault",
1194
"update"].indexOf(attr) > -1){
1195
continue
1196
}
1197
if(typeof dict[attr] == "function"){
1198
mappingproxy[attr] = (function(key){
1199
return function(){
1200
return dict[key].apply(null, arguments)
1201
}
1202
})(attr)
1203
}else{
1204
mappingproxy[attr] = dict[attr]
1205
}
1206
}
1207
Feb 12, 2018
1208
$B.set_func_names(mappingproxy, "builtins")
Mar 7, 2018
1213
if(attr.charAt(0) != "$" && attr !== "__class__"){
1214
if(x[attr] === null){
1215
d.$string_dict[attr] = [_b_.None, d.$order++]
1216
}else if(x[attr] === undefined){
1217
continue
1218
}else if(x[attr].$jsobj === x){
1219
d.$string_dict[attr] = [d, d.$order++]
1221
d.$string_dict[attr] = [$B.$JS2Py(x[attr]), d.$order++]
1223
}
1224
}
1225
return d
1226
}
1228
$B.obj_dict = function(obj, from_js){
1229
var klass = obj.__class__ || $B.get_class(obj)
1230
if(klass !== undefined && klass.$native){
1231
throw _b_.AttributeError.$factory("'" + $B.class_name(obj) +
1232
"' object has no attribute '__dict__'")}
1234
res.$jsobj = obj
1235
res.$from_js = from_js // set to true if
1236
return res
1237
}
1238
Sep 5, 2014
1239
})(__BRYTHON__)