Skip to content
Permalink
 
 
Cannot retrieve contributors at this time
;(function($B){
/*
Implementation of Python dictionaries
We can't use Javascript's Map here, because the behaviour is not exactly the
same (eg with keys that are instances of classes with a __hash__ method...)
and because Map is much slower than regular Javascript objects.
A Python dictionary is implemented as a Javascript objects with these
attributes:
. $version: an integer with an initial value of 0, incremented at each
insertion
. $numeric_dict: for keys of type int
. $string_dict and $str_hash: for keys of type str
. $object_dict: for keys of other types
The value associated to a key in $numeric_dict and $string_dict is a pair
[value, rank] where "value" is the value associated with the key and "rank"
is the value of the dict attribute $version when the pair is inserted. This
is required to keep track of the insertion order, mandatory since Python 3.7.
For keys that are not str or int, their hash value is computed. Since several
keys with the same hash can be stored in a dictionary, $object_dict[hash] is a
list of [key, [value, rank]] lists.
*/
var _b_ = $B.builtins
var str_hash = _b_.str.__hash__,
$N = _b_.None
var set_ops = ["eq", "le", "lt", "ge", "gt",
"sub", "rsub", "and", "or", "xor"]
// methods to compare non set-like views
function is_sublist(t1, t2){
// Return true if all elements of t1 are in t2
for(var i = 0, ilen = t1.length; i < ilen; i++){
var x = t1[i],
flag = false
for(var j = 0, jlen = t2.length; j < jlen; j++){
if($B.rich_comp("__eq__", x, t2[j])){
t2.splice(j, 1)
flag = true
break
}
}
if(! flag){
return false
}
}
return true
}
dict_view_op = {
__eq__: function(t1, t2){
return t1.length == t2.length && is_sublist(t1, t2)
},
__ne__: function(t1, t2){
return ! dict_view_op.__eq__(t1, t2)
},
__lt__: function(t1, t2){
return t1.length < t2.length && is_sublist(t1, t2)
},
__gt__: function(t1, t2){
return dict_view_op.__lt__(t2, t1)
},
__le__: function(t1, t2){
return t1.length <= t2.length && is_sublist(t1, t2)
},
__ge__: function(t1, t2){
return dict_view_op.__le__(t2, t1)
},
__and__: function(t1, t2){
var items = []
for(var i = 0, ilen = t1.length; i < ilen; i++){
var x = t1[i]
flag = false
for(var j = 0, jlen = t2.length; j < jlen; j++){
if($B.rich_comp("__eq__", x, t2[j])){
t2.splice(j, 1)
items.push(x)
break
}
}
}
return items
},
__or__: function(t1, t2){
var items = t1
for(var j = 0, jlen = t2.length; j < jlen; j++){
var y = t2[j],
flag = false
for(var i = 0, ilen = t1.length; i < ilen; i++){
if($B.rich_comp("__eq__", y, t1[i])){
t2.splice(j, 1)
flag = true
break
}
}
if(! flag){
items.push(y)
}
}
return items
}
}
$B.make_view = function(name){
var klass = $B.make_class(name, function(d, items, set_like){
return {
__class__: klass,
__dict__: $B.empty_dict(),
counter: -1,
dict: d,
items: items,
len: items.length,
set_like: set_like
}
})
for(var i = 0, len = set_ops.length; i < len; i++){
var op = "__" + set_ops[i] + "__"
klass[op] = (function(op){
return function(self, other){
// compare set of items to other
if(self.set_like){
return _b_.set[op](_b_.set.$factory(self),
_b_.set.$factory(other))
}else{
// Non-set like views can only be compared to
// instances of the same class
if(other.__class__ !== klass){
return false
}
var other_items = _b_.list.$factory(other)
return dict_view_op[op](self.items, other_items)
}
}
})(op)
}
klass.__iter__ = function(self){
var it = klass.$iterator.$factory(self.items)
it.test_change = function(){
return self.dict.$version != self.dict_version
}
return it
}
klass.__len__ = function(self){
return self.len
}
klass.__repr__ = function(self){
return klass.$infos.__name__ + '(' + _b_.repr(self.items) + ')'
}
$B.set_func_names(klass, "builtins")
return klass
}
var dict = {
__class__: _b_.type,
__mro__: [_b_.object],
$infos: {
__module__: "builtins",
__name__: "dict"
},
$is_class: true,
$native: true,
$match_mapping_pattern: true // for pattern matching (PEP 634)
}
dict.$to_obj = function(d){
// Function applied to dictionary that only have string keys,
// return a Javascript objects with the kays mapped to the value,
// excluding the insertion rank
var res = {}
for(var key in d.$string_dict){
res[key] = d.$string_dict[key][0]
}
return res
}
function to_list(d, ix){
var items = [],
item
if(d.$jsobj){
items = []
for(var attr in d.$jsobj){
if((! attr.startsWith("$")) &&
((! d.$exclude) || ! d.$exclude(attr))){
var val = d.$jsobj[attr]
if(val === undefined){val = _b_.NotImplemented}
else if(val === null){val = $N}
items.push([attr, val])
}
}
}else if(_b_.isinstance(d, _b_.dict)){
for(var k in d.$numeric_dict){
items.push([parseFloat(k), d.$numeric_dict[k]])
}
for(var k in d.$string_dict){
items.push([k, d.$string_dict[k]])
}
for(var k in d.$object_dict){
d.$object_dict[k].forEach(function(item){
items.push(item)
})
}
// sort by insertion order
items.sort(function(a, b){
return a[1][1] - b[1][1]
})
items = items.map(function(item){return [item[0], item[1][0]]})
}
if(ix !== undefined){
res = items.map(function(item){return item[ix]})
return res
}else{
items.__class__ = _b_.tuple
return items.map(function(item){
item.__class__ = _b_.tuple; return item}
)
}
}
$B.dict_to_list = to_list // used in py_types.js
var $copy_dict = function(left, right){
var _l = to_list(right),
si = dict.$setitem
right.$version = right.$version || 0
var right_version = right.$version || 0
for(var i = 0, len = _l.length; i < len; i++){
si(left, _l[i][0], _l[i][1])
if(right.$version != right_version){
throw _b_.RuntimeError.$factory("dict mutated during update")
}
}
}
function rank(self, hash, key){
// Search if object key, with hash = hash(key), is in
// self.$object_dict
var pairs = self.$object_dict[hash]
if(pairs !== undefined){
for(var i = 0, len = pairs.length; i < len; i++){
if($B.rich_comp("__eq__", key, pairs[i][0])){
return i
}
}
}
return -1
}
dict.__bool__ = function () {
var $ = $B.args("__bool__", 1, {self: null}, ["self"],
arguments, {}, null, null)
return dict.__len__($.self) > 0
}
dict.__class_getitem__ = function(cls, item){
// PEP 585
// Set as a classmethod at the end of this script, after $B.set_func_names()
if(! Array.isArray(item)){
item = [item]
}
return $B.GenericAlias.$factory(cls, item)
}
dict.__contains__ = function(){
var $ = $B.args("__contains__", 2, {self: null, key: null},
["self", "key"], arguments, {}, null, null),
self = $.self,
key = $.key
if(self.$jsobj){
return self.$jsobj[key] !== undefined
}
switch(typeof key) {
case "string":
return self.$string_dict.hasOwnProperty(key)
case "number":
return self.$numeric_dict[key] !== undefined
}
var hash = _b_.hash(key)
if(self.$str_hash[hash] !== undefined &&
$B.rich_comp("__eq__", key, self.$str_hash[hash])){
return true
}
if(self.$numeric_dict[hash] !== undefined &&
$B.rich_comp("__eq__", key, hash)){
return true
}
return rank(self, hash, key) > -1
}
dict.__delitem__ = function(){
var $ = $B.args("__eq__", 2, {self: null, arg: null},
["self", "arg"], arguments, {}, null, null),
self = $.self,
arg = $.arg
if(self.$jsobj){
if(self.$jsobj[arg] === undefined){throw _b_.KeyError.$factory(arg)}
delete self.$jsobj[arg]
return $N
}
switch(typeof arg){
case "string":
if(self.$string_dict[arg] === undefined){
throw _b_.KeyError.$factory(_b_.str.$factory(arg))
}
delete self.$string_dict[arg]
delete self.$str_hash[str_hash(arg)]
self.$version++
return $N
case "number":
if(self.$numeric_dict[arg] === undefined){
throw _b_.KeyError.$factory(_b_.str.$factory(arg))
}
delete self.$numeric_dict[arg]
self.$version++
return $N
}
// go with defaults
var hash = _b_.hash(arg),
ix
if((ix = rank(self, hash, arg)) > -1){
self.$object_dict[hash].splice(ix, 1)
}else{
throw _b_.KeyError.$factory(_b_.str.$factory(arg))
}
self.$version++
return $N
}
dict.__eq__ = function(){
var $ = $B.args("__eq__", 2, {self: null, other: null},
["self", "other"], arguments, {}, null, null),
self = $.self,
other = $.other
if(! _b_.isinstance(other, dict)){return false}
if(self.$jsobj){self = jsobj2dict(self.$jsobj)}
if(other.$jsobj){other = jsobj2dict(other.$jsobj)}
if(dict.__len__(self) != dict.__len__(other)){
return false
}
if(self.$string_dict.length != other.$string_dict.length){
return false
}
for(var k in self.$numeric_dict){
if(other.$numeric_dict.hasOwnProperty(k)){
if(!$B.rich_comp("__eq__", other.$numeric_dict[k][0],
self.$numeric_dict[k][0])){
return false
}
}else if(other.$object_dict.hasOwnProperty(k)){
var pairs = other.$object_dict[k],
flag = false
for(var i = 0, len = pairs.length; i < len; i++){
if($B.rich_comp("__eq__", k, pairs[i][0]) &&
$B.rich_comp("__eq__", self.$numeric_dict[k],
pairs[i][1])){
flag = true
break
}
}
if(! flag){return false}
}else{
return false
}
}
for(var k in self.$string_dict){
if(!other.$string_dict.hasOwnProperty(k) ||
!$B.rich_comp("__eq__", other.$string_dict[k][0],
self.$string_dict[k][0])){
return false
}
}
for(var hash in self.$object_dict){
var pairs = self.$object_dict[hash]
// Get all (key, value) pairs in other that have the same hash
var other_pairs = []
if(other.$numeric_dict[hash] !== undefined){
other_pairs.push([hash, other.$numeric_dict[hash]])
}
if(other.$object_dict[hash] !== undefined){
other_pairs = other_pairs.concat(other.$object_dict[hash])
}
if(other_pairs.length == 0){
return false
}
for(var i = 0, len_i = pairs.length; i < len_i; i++){
var flag = false
var key = pairs[i][0],
value = pairs[i][1][0]
for(var j = 0, len_j = other_pairs.length; j < len_j; j++){
if($B.rich_comp("__eq__", key, other_pairs[j][0]) &&
$B.rich_comp("__eq__", value, other_pairs[j][1][0])){
flag = true
break
}
}
if(! flag){
return false
}
}
}
return true
}
dict.__getitem__ = function(){
var $ = $B.args("__getitem__", 2, {self: null, arg: null},
["self", "arg"], arguments, {}, null, null),
self = $.self,
arg = $.arg
return dict.$getitem(self, arg)
}
dict.$getitem = function(self, arg, ignore_missing){
// ignore_missing is set in dict.get and dict.setdefault
if(self.$jsobj){
if(self.$exclude && self.$exclude(arg)){
throw _b_.KeyError.$factory(arg)
}
if(self.$jsobj[arg] === undefined){
if(self.$jsobj.hasOwnProperty &&
self.$jsobj.hasOwnProperty(arg)){
return $B.Undefined
}
throw _b_.KeyError.$factory(arg)
}
return self.$jsobj[arg]
}
switch(typeof arg){
case "string":
if(self.$string_dict.hasOwnProperty(arg)){
return self.$string_dict[arg][0]
}
break
case "number":
if(self.$numeric_dict[arg] !== undefined){
return self.$numeric_dict[arg][0]
}
break
}
// since the key is more complex use 'default' method of getting item
var hash = _b_.hash(arg),
_eq = function(other){return $B.rich_comp("__eq__", arg, other)}
if(typeof arg == "object"){
arg.$hash = hash // cache for setdefault
}
var sk = self.$str_hash[hash]
if(sk !== undefined && _eq(sk)){
return self.$string_dict[sk][0]
}
if(self.$numeric_dict[hash] !== undefined && _eq(hash)){
return self.$numeric_dict[hash][0]
}
if(_b_.isinstance(arg, _b_.str)){
// string subclass
if(self.$string_dict.hasOwnProperty(arg.valueOf())){
return self.$string_dict[arg.valueOf()][0]
}
}
var ix = rank(self, hash, arg)
if(ix > -1){
return self.$object_dict[hash][ix][1][0]
}
if(! ignore_missing){
if(self.__class__ !== dict && ! ignore_missing){
try{
var missing_method = $B.$getattr(self.__class__,
"__missing__", _b_.None)
}catch(err){
console.log(err)
}
if(missing_method !== _b_.None){
return missing_method(self, arg)
}
}
}
throw _b_.KeyError.$factory(arg)
}
dict.__hash__ = _b_.None
function init_from_list(self, args){
var i = -1,
stop = args.length - 1,
si = dict.__setitem__
while(i++ < stop){
var item = args[i]
if(item.length != 2){
throw _b_.ValueError.$factory("dictionary " +
`update sequence element #${i} has length 1; 2 is required`)
}
switch(typeof item[0]) {
case 'string':
self.$string_dict[item[0]] = [item[1], self.$order++]
self.$str_hash[str_hash(item[0])] = item[0]
self.$version++
break
case 'number':
if(item[0] != 0 && item[0] != 1){
self.$numeric_dict[item[0]] = [item[1], self.$order++]
self.$version++
break
}
default:
si(self, item[0], item[1])
break
}
}
}
dict.__init__ = function(self, first, second){
if(first === undefined){
return $N
}
if(second === undefined){
if(first.$nat != 'kw' && $B.get_class(first) === $B.JSObj){
for(var key in first){
self.$string_dict[key] = [first[key], self.$order++]
}
return _b_.None
}else if(first.$jsobj){
self.$jsobj = {}
for(var attr in first.$jsobj){
self.$jsobj[attr] = first.$jsobj[attr]
}
return $N
}else if(Array.isArray(first)){
init_from_list(self, first)
return $N
}
}
var $ = $B.args("dict", 1, {self:null}, ["self"],
arguments, {}, "first", "second")
var args = $.first
if(args.length > 1){
throw _b_.TypeError.$factory("dict expected at most 1 argument" +
", got 2")
}else if(args.length == 1){
args = args[0]
if(args.__class__ === dict){
['$string_dict', '$str_hash', '$numeric_dict', '$object_dict'].
forEach(function(d){
for(key in args[d]){self[d][key] = args[d][key]}
})
}else if(_b_.isinstance(args, dict)){
$copy_dict(self, args)
}else{
var keys = $B.$getattr(args, "keys", null)
if(keys !== null){
var gi = $B.$getattr(args, "__getitem__", null)
if(gi !== null){
// has keys and __getitem__ : it's a mapping, iterate on
// keys and values
gi = $B.$call(gi)
var kiter = _b_.iter($B.$call(keys)())
while(true){
try{
var key = _b_.next(kiter),
value = gi(key)
dict.__setitem__(self, key, value)
}catch(err){
if(err.__class__ === _b_.StopIteration){
break
}
throw err
}
}
return $N
}
}
if(! Array.isArray(args)){
args = _b_.list.$factory(args)
}
// Form "dict([[key1, value1], [key2,value2], ...])"
init_from_list(self, args)
}
}
var kw = $.second.$string_dict
for(var attr in kw){
switch(typeof attr){
case "string":
self.$string_dict[attr] = [kw[attr][0], self.$order++]
self.$str_hash[str_hash(attr)] = attr
break
case "number":
self.$numeric_dict[attr] = [kw[attr][0], self.$order++]
break
default:
si(self, attr, kw[attr][0])
break
}
}
return $N
}
dict.__iter__ = function(self){
return _b_.iter(dict.keys(self))
}
dict.__ior__ = function(self, other){
// PEP 584
dict.update(self, other)
return self
}
dict.__len__ = function(self) {
var _count = 0
if(self.$jsobj){
for(var attr in self.$jsobj){
if(attr.charAt(0) != "$" &&
((! self.$exclude) || ! self.$exclude(attr))){
_count++
}
}
return _count
}
for(var k in self.$numeric_dict){_count++}
for(var k in self.$string_dict){_count++}
for(var hash in self.$object_dict){
_count += self.$object_dict[hash].length
}
return _count
}
dict.__ne__ = function(self, other){
return ! dict.__eq__(self, other)
}
dict.__new__ = function(cls){
if(cls === undefined){
throw _b_.TypeError.$factory("int.__new__(): not enough arguments")
}
var instance = {
__class__: cls,
$numeric_dict : {},
$object_dict : {},
$string_dict : {},
$str_hash: {},
$version: 0,
$order: 0
}
if(cls !== dict){
instance.__dict__ = $B.empty_dict()
}
return instance
}
dict.__or__ = function(self, other){
// PEP 584
if(! _b_.isinstance(other, dict)){
return _b_.NotImplemented
}
var res = dict.copy(self)
dict.update(res, other)
return res
}
function __newobj__(){
// __newobj__ is called with a generator as only argument
var $ = $B.args('__newobj__', 0, {}, [], arguments, {}, 'args', null),
args = $.args
var res = $B.empty_dict()
res.__class__ = args[0]
return res
}
dict.__reduce_ex__ = function(self, protocol){
return $B.fast_tuple([
__newobj__,
$B.fast_tuple([self.__class__]),
_b_.None,
_b_.None,
dict.items(self)])
}
dict.__repr__ = function(self){
$B.builtins_repr_check(dict, arguments) // in brython_builtins.js
if(self.$jsobj){ // wrapper around Javascript object
return dict.__repr__(jsobj2dict(self.$jsobj, self.$exclude))
}
if($B.repr.enter(self)){
return "{...}"
}
var res = [],
items = to_list(self)
items.forEach(function(item){
try{
res.push(_b_.repr(item[0]) + ": " + _b_.repr(item[1]))
}catch(err){
throw err
}
})
$B.repr.leave(self)
return "{" + res.join(", ") + "}"
}
dict.__ror__ = function(self, other){
// PEP 584
if(! _b_.isinstance(other, dict)){
return _b_.NotImplemented
}
var res = dict.copy(other)
dict.update(res, self)
return res
}
dict.__setitem__ = function(self, key, value){
var $ = $B.args("__setitem__", 3, {self: null, key: null, value: null},
["self", "key", "value"], arguments, {}, null, null)
return dict.$setitem($.self, $.key, $.value)
}
dict.$setitem = function(self, key, value, $hash){
// Set a dictionary item mapping key and value.
//
// If key is a string, set:
// - $string_dict[key] = [value, order] where "order" is an auto-increment
// unique id to keep track of insertion order
// - $str_hash[hash(key)] to key
//
// If key is a number, set $numeric_dict[key] = value
//
// If key is another object, compute its hash value:
// - if the hash is a key of $str_hash, and key == $str_hash[hash],
// replace $string_dict[$str_hash[hash]] by value
// - if the hash is a key of $numeric_dict, and hash == key, replace
// $numeric_dict[hash] by value
// - if the hash is a key of $object_dict: $object_dict[hash] is a list
// of [k, v] pairs. If key is equal to one of the "k", replace the
// matching v by value. Otherwise, add [key, value] to the list
// - else set $object_dict[hash] = [[key, value]]
//
// In all cases, increment attribute $version, used to detect dictionary
// changes during an iteration.
//
// Parameter $hash is only set if this method is called by setdefault.
// In this case the hash of key has already been computed and we
// know that the key is not present in the dictionary, so it's no
// use computing hash(key) again, nor testing equality of keys
if(self.$jsobj){
if(self.$from_js){
// dictionary created by method to_dict of JSObj instances
value = $B.pyobj2jsobj(value)
}
if(self.$jsobj.__class__ === _b_.type){
self.$jsobj[key] = value
if(key == "__init__" || key == "__new__"){
// If class attribute __init__ or __new__ are reset,
// the factory function has to change
self.$jsobj.$factory = $B.$instance_creator(self.$jsobj)
}
}else{
self.$jsobj[key] = value
}
return $N
}
if(key instanceof String){
key = key.valueOf()
}
switch(typeof key){
case "string":
if(self.$string_dict === undefined){
console.log("pas de string dict", self, key, value)
}
if(self.$string_dict.hasOwnProperty(key)){
self.$string_dict[key][0] = value
}else{
self.$string_dict[key] = [value, self.$order++]
self.$str_hash[str_hash(key)] = key
self.$version++
}
return $N
case "number":
if(self.$numeric_dict[key] !== undefined){
// existing key: preserve order
self.$numeric_dict[key][0] = value
}else{
// special case for 0 and 1 if True or False are keys
var done = false
if((key == 0 || key == 1) &&
self.$object_dict[key] !== undefined){
for(const item of self.$object_dict[key]){
if((key == 0 && item[0] === false) ||
(key == 1 && item[0] === true)){
// replace value
item[1][0] = value
done = true
}
}
}
if(! done){
// new key
self.$numeric_dict[key] = [value, self.$order++]
}
self.$version++
}
return $N
case "boolean":
// true replaces 1 and false replaces 0
var num = key ? 1 : 0
if(self.$numeric_dict[num] !== undefined){
var order = self.$numeric_dict[num][1] // preserve order
self.$numeric_dict[num] = [value, order]
return
}
if(self.$object_dict[num] !== undefined){
self.$object_dict[num].push([key, [value, self.$order++]])
}else{
self.$object_dict[num] = [[key, [value, self.$order++]]]
}
}
// if we got here the key is more complex, use default method
var hash = $hash === undefined ? _b_.hash(key) : $hash,
_eq = function(other){return $B.rich_comp("__eq__", key, other)}
if(self.$numeric_dict[hash] !== undefined && _eq(hash)){
self.$numeric_dict[hash] = [value, self.$numeric_dict[hash][1]]
self.$version++
return $N
}
var sk = self.$str_hash[hash]
if(sk !== undefined && _eq(sk)){
self.$string_dict[sk] = [value, self.$string_dict[sk][1]]
self.$version++
return $N
}
// If $setitem is called from setdefault, don't test equality of key
// with any object
if($hash){
if(self.$object_dict[$hash] !== undefined){
self.$object_dict[$hash].push([key, [value, self.$order++]])
}else{
self.$object_dict[$hash] = [[key, [value, self.$order++]]]
}
self.$version++
return $N
}
var ix = rank(self, hash, key)
if(ix > -1){
// reset value
self.$object_dict[hash][ix][1] = [value,
self.$object_dict[hash][ix][1][1]]
return $N
}else if(self.$object_dict.hasOwnProperty(hash)){
self.$object_dict[hash].push([key, [value, self.$order++]])
}else{
self.$object_dict[hash] = [[key, [value, self.$order++]]]
}
self.$version++
return $N
}
// add "reflected" methods
$B.make_rmethods(dict)
dict.clear = function(){
// Remove all items from the dictionary.
var $ = $B.args("clear", 1, {self: null}, ["self"], arguments, {},
null, null),
self = $.self
self.$numeric_dict = {}
self.$string_dict = {}
self.$str_hash = {}
self.$object_dict = {}
if(self.$jsobj){
for(var attr in self.$jsobj){
if(attr.charAt(0) !== "$" && attr !== "__class__"){
delete self.$jsobj[attr]
}
}
}
self.$version++
self.$order = 0
return $N
}
dict.copy = function(self){
// Return a shallow copy of the dictionary
var $ = $B.args("copy", 1, {self: null},["self"], arguments,{},
null, null),
self = $.self,
res = $B.empty_dict()
$copy_dict(res, self)
return res
}
dict.fromkeys = function(){
var $ = $B.args("fromkeys", 3, {cls: null, keys: null, value: null},
["cls", "keys", "value"], arguments, {value: _b_.None}, null, null),
keys = $.keys,
value = $.value
// class method
var klass = $.cls,
res = $B.$call(klass)(),
keys_iter = $B.$iter(keys)
while(1){
try{
var key = _b_.next(keys_iter)
if(klass === dict){dict.$setitem(res, key, value)}
else{$B.$getattr(res, "__setitem__")(key, value)}
}catch(err){
if($B.is_exc(err, [_b_.StopIteration])){
return res
}
throw err
}
}
}
dict.get = function(){
var $ = $B.args("get", 3, {self: null, key: null, _default: null},
["self", "key", "_default"], arguments, {_default: $N}, null, null)
try{
// call $getitem with ignore_missign set to true
return dict.$getitem($.self, $.key, true)
}catch(err){
if(_b_.isinstance(err, _b_.KeyError)){return $._default}
else{throw err}
}
}
var dict_items = $B.make_view("dict_items", true)
dict_items.$iterator = $B.make_iterator_class("dict_itemiterator")
dict.items = function(self){
var $ = $B.args('items', 1, {self: null}, ['self'], arguments,
{}, null, null)
var items = to_list(self),
set_like = true
// Check if all values are hashable
for(var i = 0, len = items.length; i < len; i++){
try{
_b_.hash(items[i][1])
}catch(err){
set_like = false
break
}
}
var values = to_list(self)
var it = dict_items.$factory(self, values, set_like)
it.dict_version = self.$version
return it
}
var dict_keys = $B.make_view("dict_keys")
dict_keys.$iterator = $B.make_iterator_class("dict_keyiterator")
dict.keys = function(self){
var $ = $B.args('keys', 1, {self: null}, ['self'], arguments,
{}, null, null)
var it = dict_keys.$factory(self, to_list(self, 0), true)
it.dict_version = self.$version
return it
}
dict.pop = function(){
var missing = {},
$ = $B.args("pop", 3, {self: null, key: null, _default: null},
["self", "key", "_default"], arguments, {_default: missing}, null, null),
self = $.self,
key = $.key,
_default = $._default
try{
var res = dict.__getitem__(self, key)
dict.__delitem__(self, key)
return res
}catch(err){
if(err.__class__ === _b_.KeyError){
if(_default !== missing){return _default}
throw err
}
throw err
}
}
dict.popitem = function(self){
try{
var itm = _b_.next(_b_.iter(dict.items(self)))
dict.__delitem__(self, itm[0])
return _b_.tuple.$factory(itm)
}catch(err) {
if (err.__class__ == _b_.StopIteration) {
throw _b_.KeyError.$factory("'popitem(): dictionary is empty'")
}
}
}
dict.setdefault = function(){
var $ = $B.args("setdefault", 3, {self: null, key: null, _default: null},
["self", "key", "_default"], arguments, {_default: $N}, null, null),
self = $.self,
key = $.key,
_default = $._default
try{
// Pass 3rd argument to dict.$getitem to avoid using __missing__
// Cf. issue #1598
return dict.$getitem(self, key, true)
}catch(err){
if(err.__class__ !== _b_.KeyError){
throw err
}
if(_default === undefined){_default = $N}
var hash = key.$hash
key.$hash = undefined
dict.$setitem(self, key, _default, hash)
return _default
}
}
dict.update = function(self){
var $ = $B.args("update", 1, {"self": null}, ["self"], arguments,
{}, "args", "kw"),
self = $.self,
args = $.args,
kw = $.kw
if(args.length > 0){
var o = args[0]
if(_b_.isinstance(o, dict)){
if(o.$jsobj){
o = jsobj2dict(o.$jsobj)
}
$copy_dict(self, o)
}else if(_b_.hasattr(o, "keys")){
var _keys = _b_.list.$factory($B.$call($B.$getattr(o, "keys"))())
for(var i = 0, len = _keys.length; i < len; i++){
var _value = $B.$getattr(o, "__getitem__")(_keys[i])
dict.$setitem(self, _keys[i], _value)
}
}else{
var it = _b_.iter(o),
i = 0
while(true){
try{
var item = _b_.next(it)
}catch(err){
if(err.__class__ === _b_.StopIteration){break}
throw err
}
try{
key_value = _b_.list.$factory(item)
}catch(err){
throw _b_.TypeError.$factory("cannot convert dictionary" +
" update sequence element #" + i + " to a sequence")
}
if(key_value.length !== 2){
throw _b_.ValueError.$factory("dictionary update " +
"sequence element #" + i + " has length " +
key_value.length + "; 2 is required")
}
dict.$setitem(self, key_value[0], key_value[1])
i++
}
}
}
$copy_dict(self, kw)
self.$version++
return $N
}
var dict_values = $B.make_view("dict_values")
dict_values.$iterator = $B.make_iterator_class("dict_valueiterator")
dict.values = function(self){
var $ = $B.args('values', 1, {self: null}, ['self'], arguments,
{}, null, null)
var values = to_list(self, 1)
var it = dict_values.$factory(self, values, false)
it.dict_version = self.$version
return it
}
dict.$factory = function(){
var res = dict.__new__(dict)
var args = [res]
for(var i = 0, len = arguments.length; i < len ; i++){
args.push(arguments[i])
}
dict.__init__.apply(null, args)
return res
}
_b_.dict = dict
$B.set_func_names(dict, "builtins")
dict.__class_getitem__ = _b_.classmethod.$factory(dict.__class_getitem__)
$B.empty_dict = function(){
return {
__class__: dict,
$numeric_dict : {},
$object_dict : {},
$string_dict : {},
$str_hash: {},
$version: 0,
$order: 0
}
}
// This must be done after set_func_names, otherwise dict.fromkeys doesn't
// have the attribute $infos
dict.fromkeys = _b_.classmethod.$factory(dict.fromkeys)
$B.getset_descriptor = $B.make_class("getset_descriptor",
function(klass, attr){
return {
__class__: $B.getset_descriptor,
__doc__: _b_.None,
cls: klass,
attr: attr
}
}
)
$B.getset_descriptor.__repr__ = $B.getset_descriptor.__str__ = function(self){
return `<attribute '${self.attr}' of '${self.cls.$infos.__name__}' objects>`
}
$B.set_func_names($B.getset_descriptor, "builtins")
// Class for attribute __dict__ of classes
var mappingproxy = $B.mappingproxy = $B.make_class("mappingproxy",
function(obj){
if(_b_.isinstance(obj, dict)){
// obj is a dictionary, with $string_dict table such that
// obj.$string_dict[key] = [value, rank]
// Transform it into an object with attribute $jsobj such that
// res.$jsobj[key] = value
var res = $B.obj_dict(dict.$to_obj(obj))
}else{
var res = $B.obj_dict(obj)
}
res.__class__ = mappingproxy
return res
}
)
mappingproxy.$match_mapping_pattern = true // for pattern matching (PEP 634)
mappingproxy.__repr__ = function(){
return '<mappingproxy object>'
}
mappingproxy.__setitem__ = function(){
throw _b_.TypeError.$factory("'mappingproxy' object does not support " +
"item assignment")
}
for(var attr in dict){
if(mappingproxy[attr] !== undefined ||
["__class__", "__mro__", "__new__", "__init__", "__delitem__",
"clear", "fromkeys", "pop", "popitem", "setdefault",
"update"].indexOf(attr) > -1){
continue
}
if(typeof dict[attr] == "function"){
mappingproxy[attr] = (function(key){
return function(){
return dict[key].apply(null, arguments)
}
})(attr)
}else{
mappingproxy[attr] = dict[attr]
}
}
$B.set_func_names(mappingproxy, "builtins")
function jsobj2dict(x, exclude){
exclude = exclude || function(){return false}
var d = $B.empty_dict()
for(var attr in x){
if(attr.charAt(0) != "$" && ! exclude(attr)){
if(x[attr] === null){
d.$string_dict[attr] = [_b_.None, d.$order++]
}else if(x[attr] === undefined){
continue
}else if(x[attr].$jsobj === x){
d.$string_dict[attr] = [d, d.$order++]
}else{
d.$string_dict[attr] = [$B.$JS2Py(x[attr]), d.$order++]
}
}
}
return d
}
$B.obj_dict = function(obj, exclude){
var klass = obj.__class__ || $B.get_class(obj)
if(klass !== undefined && klass.$native){
throw $B.attr_error("__dict__", obj)
}
var res = $B.empty_dict()
res.$jsobj = obj
res.$exclude = exclude || function(){return false}
return res
}
// Wrapper around a JS object to handle it as a Python dictionary.
// Some keys of the original object can be ignored by passing
// the filtering function exclude().
// Supports adding new keys.
var jsobj_as_pydict = $B.jsobj_as_pydict = $B.make_class('jsobj_as_pydict',
function(jsobj, exclude){
return {
__class__: jsobj_as_pydict,
obj: jsobj,
exclude: exclude ? exclude : function(){return false},
new_keys: []
}
}
)
jsobj_as_pydict.__contains__ = function(self, key){
if(self.new_keys.indexOf(key) > -1){
return true
}
return ! (self.exclude(key) || self.obj[key] === undefined)
}
jsobj_as_pydict.__delitem__ = function(self, key){
jsobj_as_pydict.__getitem__(self, key) // raises KeyError if not present
delete self.obj[key]
var ix = self.new_keys.indexOf(key)
if(ix > -1){
self.new_keys.splice(ix, 1)
}
}
jsobj_as_pydict.__eq__ = function(self, other){
if(other.__class__ !== jsobj_as_pydict){
return _b_.NotImplemented
}
// create true Python dicts with the items in self and other
var self1 = $B.empty_dict()
other1 = $B.empty_dict()
dict.__init__(self1, jsobj_as_pydict.items(self))
dict.__init__(other1, jsobj_as_pydict.items(other))
// Compare true Python dicts
return dict.__eq__(self1, other1)
}
jsobj_as_pydict.__getitem__ = function(self, key){
if(jsobj_as_pydict.__contains__(self, key)){
return self.obj[key]
}
throw _b_.KeyError.$factory(key)
}
jsobj_as_pydict.__iter__ = function(self){
return _b_.iter(jsobj_as_pydict.keys(self))
}
jsobj_as_pydict.__len__ = function(self){
var len = 0
for(var key in self.obj){
if(! self.exclude(key)){
len++
}
}
return len + self.new_keys.length
}
jsobj_as_pydict.__repr__ = function(self){
if($B.repr.enter(self)){
return "{...}"
}
var res = [],
items = _b_.list.$factory(jsobj_as_pydict.items(self))
for(var item of items){
res.push(_b_.repr(item[0]) + ": " + _b_.repr(item[1]))
}
$B.repr.leave(self)
return "{" + res.join(", ") + "}"
}
jsobj_as_pydict.__setitem__ = function(self, key, value){
if(self.exclude(key) && self.new_keys.indexOf(key) == -1){
self.new_keys.push(key)
}
self.obj[key] = value
}
jsobj_as_pydict.get = function(self, key, _default){
_default = _default === undefined ? _b_.None : _default
if(self.exclude(key) || self.obj[key] === undefined){
return _default
}
return self.obj[key]
}
jsobj_as_pydict.items = function(self){
var items = []
for(var key in self.obj){
if(self.exclude(key) && self.new_keys.indexOf(key) == -1){
continue
}
items.push($B.fast_tuple([key, self.obj[key]]))
}
var set_like = true
// Check if all values are hashable
for(var item of items){
try{
_b_.hash(item[1])
}catch(err){
set_like = false
break
}
}
var it = dict_items.$factory(self, items, set_like)
it.dict_version = self.$version
return it
}
jsobj_as_pydict.keys = function(self){
var lst = []
for(var key in self.obj){
if(self.exclude(key) && self.new_keys.indexOf(key) == -1){
continue
}
lst.push(key)
}
var it = dict_keys.$factory(self, lst, true)
it.dict_version = self.$version
return it
}
jsobj_as_pydict.values = function(self){
var values = []
for(var key in self.obj){
if(self.exclude(key) && self.new_keys.indexOf(key) == -1){
continue
}
values.push(self.obj[key])
}
var it = dict_values.$factory(self, values, false)
it.dict_version = self.$version
return it
}
$B.set_func_names(jsobj_as_pydict, 'builtins')
})(__BRYTHON__)