Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes14kdownloads
immutabledict.pyx134 linesDownload Raw Back to cyextension
1# cyextension/immutabledict.pyx
2# Copyright (C) 2005-2024 the SQLAlchemy authors and contributors
3# <see AUTHORS file>
4#
5# This module is part of SQLAlchemy and is released under
6# the MIT License: https://www.opensource.org/licenses/mit-license.php
7from cpython.dict cimport PyDict_New, PyDict_Update, PyDict_Size
8
9
10def _readonly_fn(obj):
11    raise TypeError(
12        "%s object is immutable and/or readonly" % obj.__class__.__name__)
13
14
15def _immutable_fn(obj):
16    raise TypeError(
17        "%s object is immutable" % obj.__class__.__name__)
18
19
20class ReadOnlyContainer:
21
22    __slots__ = ()
23
24    def _readonly(self, *a,**kw):
25        _readonly_fn(self)
26
27    __delitem__ = __setitem__ = __setattr__ = _readonly
28
29
30class ImmutableDictBase(dict):
31    def _immutable(self, *a,**kw):
32        _immutable_fn(self)
33
34    @classmethod
35    def __class_getitem__(cls, key):
36        return cls
37
38    __delitem__ = __setitem__ = __setattr__ = _immutable
39    clear = pop = popitem = setdefault = update = _immutable
40
41
42cdef class immutabledict(dict):
43    def __repr__(self):
44        return f"immutabledict({dict.__repr__(self)})"
45
46    @classmethod
47    def __class_getitem__(cls, key):
48        return cls
49
50    def union(self, *args, **kw):
51        cdef dict to_merge = None
52        cdef immutabledict result
53        cdef Py_ssize_t args_len = len(args)
54        if args_len > 1:
55            raise TypeError(
56                f'union expected at most 1 argument, got {args_len}'
57            )
58        if args_len == 1:
59            attribute = args[0]
60            if isinstance(attribute, dict):
61                to_merge = <dict> attribute
62        if to_merge is None:
63            to_merge = dict(*args, **kw)
64
65        if PyDict_Size(to_merge) == 0:
66            return self
67
68        # new + update is faster than immutabledict(self)
69        result = immutabledict()
70        PyDict_Update(result, self)
71        PyDict_Update(result, to_merge)
72        return result
73
74    def merge_with(self, *other):
75        cdef immutabledict result = None
76        cdef object d
77        cdef bint update = False
78        if not other:
79            return self
80        for d in other:
81            if d:
82                if update == False:
83                    update = True
84                    # new + update is faster than immutabledict(self)
85                    result = immutabledict()
86                    PyDict_Update(result, self)
87                PyDict_Update(
88                    result, <dict>(d if isinstance(d, dict) else dict(d))
89                )
90
91        return self if update == False else result
92
93    def copy(self):
94        return self
95
96    def __reduce__(self):
97        return immutabledict, (dict(self), )
98
99    def __delitem__(self, k):
100        _immutable_fn(self)
101
102    def __setitem__(self, k, v):
103        _immutable_fn(self)
104
105    def __setattr__(self, k, v):
106        _immutable_fn(self)
107
108    def clear(self, *args, **kw):
109        _immutable_fn(self)
110
111    def pop(self, *args, **kw):
112        _immutable_fn(self)
113
114    def popitem(self, *args, **kw):
115        _immutable_fn(self)
116
117    def setdefault(self, *args, **kw):
118        _immutable_fn(self)
119
120    def update(self, *args, **kw):
121        _immutable_fn(self)
122
123    # PEP 584
124    def __ior__(self, other):
125        _immutable_fn(self)
126
127    def __or__(self, other):
128        return immutabledict(dict.__or__(self, other))
129
130    def __ror__(self, other):
131        # NOTE: this is used only in cython 3.x;
132        # version 0.x will call __or__ with args inversed
133        return immutabledict(dict.__ror__(self, other))
134 
codekingpro/portable-devtools · Team Ai