File: classdict.py

package info (click to toggle)
pypy3 7.0.0%2Bdfsg-3
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 111,848 kB
  • sloc: python: 1,291,746; ansic: 74,281; asm: 5,187; cpp: 3,017; sh: 2,533; makefile: 544; xml: 243; lisp: 45; csh: 21; awk: 4
file content (112 lines) | stat: -rw-r--r-- 4,075 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
from rpython.rlib import rerased
from rpython.rlib.objectmodel import iteritems_with_hash

from pypy.interpreter.error import OperationError, oefmt
from pypy.objspace.std.dictmultiobject import (
    DictStrategy, create_iterator_classes)
from pypy.objspace.std.typeobject import unwrap_cell


class ClassDictStrategy(DictStrategy):
    """Exposes a W_TypeObject.dict_w at app-level.

    Uses getdictvalue() and setdictvalue() to access items.
    """
    erase, unerase = rerased.new_erasing_pair("dictproxy")
    erase = staticmethod(erase)
    unerase = staticmethod(unerase)

    def getitem(self, w_dict, w_key):
        space = self.space
        w_lookup_type = space.type(w_key)
        if space.issubtype_w(w_lookup_type, space.w_text):
            return self.getitem_str(w_dict, space.text_w(w_key))
        else:
            return None

    def getitem_str(self, w_dict, key):
        return self.unerase(w_dict.dstorage).getdictvalue(self.space, key)

    def setitem(self, w_dict, w_key, w_value):
        space = self.space
        if space.is_w(space.type(w_key), space.w_text):
            self.setitem_str(w_dict, self.space.text_w(w_key), w_value)
        else:
            raise oefmt(space.w_TypeError,
                        "cannot add non-string keys to dict of a type")

    def setitem_str(self, w_dict, key, w_value):
        w_type = self.unerase(w_dict.dstorage)
        try:
            w_type.setdictvalue(self.space, key, w_value)
        except OperationError as e:
            if not e.match(self.space, self.space.w_TypeError):
                raise
            if not w_type.is_cpytype():
                raise
            # Allow cpyext to write to type->tp_dict even in the case
            # of a builtin type.
            # Like CPython, we assume that this is only done early
            # after the type is created, and we don't invalidate any
            # cache.  User code shoud call PyType_Modified().
            w_type.dict_w[key] = w_value

    def setdefault(self, w_dict, w_key, w_default):
        w_result = self.getitem(w_dict, w_key)
        if w_result is not None:
            return w_result
        self.setitem(w_dict, w_key, w_default)
        return w_default

    def delitem(self, w_dict, w_key):
        space = self.space
        w_key_type = space.type(w_key)
        if space.is_w(w_key_type, space.w_text):
            key = self.space.text_w(w_key)
            if not self.unerase(w_dict.dstorage).deldictvalue(space, key):
                raise KeyError
        else:
            raise KeyError

    def length(self, w_dict):
        return len(self.unerase(w_dict.dstorage).dict_w)

    def w_keys(self, w_dict):
        space = self.space
        return space.newlist_text(self.unerase(w_dict.dstorage).dict_w.keys())

    def values(self, w_dict):
        return [unwrap_cell(self.space, w_value) for w_value in
                self.unerase(w_dict.dstorage).dict_w.itervalues()]

    def items(self, w_dict):
        space = self.space
        return [space.newtuple([space.newtext(key), unwrap_cell(self.space, w_value)])
                    for (key, w_value) in self.unerase(w_dict.dstorage).dict_w.iteritems()]

    def clear(self, w_dict):
        space = self.space
        w_type = self.unerase(w_dict.dstorage)
        if not w_type.is_heaptype():
            raise oefmt(space.w_TypeError,
                        "can't clear dictionary of type '%N'", w_type)
        w_type.dict_w.clear()
        w_type.mutated(None)

    def getiterkeys(self, w_dict):
        return self.unerase(w_dict.dstorage).dict_w.iterkeys()

    def getitervalues(self, w_dict):
        return self.unerase(w_dict.dstorage).dict_w.itervalues()

    def getiteritems_with_hash(self, w_dict):
        return iteritems_with_hash(self.unerase(w_dict.dstorage).dict_w)

    def wrapkey(space, key):
        # keys are utf-8 encoded identifiers from type's dict_w
        return space.newtext(key)

    def wrapvalue(space, value):
        return unwrap_cell(space, value)

create_iterator_classes(ClassDictStrategy)