summaryrefslogtreecommitdiff
path: root/lib/sqlalchemy/util/_collections.py
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2020-05-22 00:06:06 -0400
committerMike Bayer <mike_mp@zzzcomputing.com>2020-05-23 00:05:13 -0400
commitfcbd03e48af50e301e0dcbade75765a4d3e4999f (patch)
tree8a30c4b9811bb217430c6bafea040753729c80ae /lib/sqlalchemy/util/_collections.py
parentd45657a2f5b880dc22dda2d1eb1687af5234a470 (diff)
downloadsqlalchemy-fcbd03e48af50e301e0dcbade75765a4d3e4999f.tar.gz
Add immutabledict C code
Start trying to convert fundamental objects to C as we now rely on a fairly small core of things, and 1.4 is having problems with complexity added being slower than the performance gains we are trying to build in. immutabledict here does seem to bench as twice as fast as the Python one, see below. However, it does not appear to be used prominently enough to make any dent in the performance tests. at the very least it may provide us some more lift-and-copy code for more C extensions. import timeit from sqlalchemy.util._collections import not_immutabledict, immutabledict def run(dict_cls): for i in range(1000000): d1 = dict_cls({"x": 5, "y": 4}) d2 = d1.union({"x": 17, "new key": "some other value"}, None) assert list(d2) == ["x", "y", "new key"] print( timeit.timeit( "run(d)", "from __main__ import run, not_immutabledict as d", number=1 ) ) print( timeit.timeit( "run(d)", "from __main__ import run, immutabledict as d", number=1 ) ) output: python: 1.8799766399897635 C code: 0.8880784640205093 Change-Id: I29e7104dc21dcc7cdf895bf274003af2e219bf6d
Diffstat (limited to 'lib/sqlalchemy/util/_collections.py')
-rw-r--r--lib/sqlalchemy/util/_collections.py83
1 files changed, 68 insertions, 15 deletions
diff --git a/lib/sqlalchemy/util/_collections.py b/lib/sqlalchemy/util/_collections.py
index 0990acb83..065935c48 100644
--- a/lib/sqlalchemy/util/_collections.py
+++ b/lib/sqlalchemy/util/_collections.py
@@ -31,7 +31,67 @@ class ImmutableContainer(object):
__delitem__ = __setitem__ = __setattr__ = _immutable
-class immutabledict(ImmutableContainer, dict):
+def _immutabledict_py_fallback():
+ class immutabledict(ImmutableContainer, dict):
+
+ clear = (
+ pop
+ ) = popitem = setdefault = update = ImmutableContainer._immutable
+
+ def __new__(cls, *args):
+ new = dict.__new__(cls)
+ dict.__init__(new, *args)
+ return new
+
+ def __init__(self, *args):
+ pass
+
+ def __reduce__(self):
+ return _immutabledict_reconstructor, (dict(self),)
+
+ def union(self, d):
+ if not d:
+ return self
+
+ new = dict.__new__(self.__class__)
+ dict.__init__(new, self)
+ dict.update(new, d)
+ return new
+
+ def merge_with(self, *dicts):
+ new = None
+ for d in dicts:
+ if d:
+ if new is None:
+ new = dict.__new__(self.__class__)
+ dict.__init__(new, self)
+ dict.update(new, d)
+ if new is None:
+ return self
+
+ return new
+
+ def __repr__(self):
+ return "immutabledict(%s)" % dict.__repr__(self)
+
+ return immutabledict
+
+
+try:
+ from sqlalchemy.cimmutabledict import immutabledict
+
+ collections_abc.Mapping.register(immutabledict)
+
+except ImportError:
+ immutabledict = _immutabledict_py_fallback()
+
+ def _immutabledict_reconstructor(*arg):
+ """do the pickle dance"""
+ return immutabledict(*arg)
+
+
+class FacadeDict(ImmutableContainer, dict):
+ """A dictionary that is not publicly mutable."""
clear = pop = popitem = setdefault = update = ImmutableContainer._immutable
@@ -44,24 +104,17 @@ class immutabledict(ImmutableContainer, dict):
pass
def __reduce__(self):
- return immutabledict, (dict(self),)
+ return FacadeDict, (dict(self),)
- def union(self, d):
- new = dict.__new__(self.__class__)
- dict.__init__(new, self)
- dict.update(new, d)
- return new
+ def _insert_item(self, key, value):
+ """insert an item into the dictionary directly.
- def merge_with(self, *dicts):
- new = dict.__new__(self.__class__)
- dict.__init__(new, self)
- for d in dicts:
- if d:
- dict.update(new, d)
- return new
+
+ """
+ dict.__setitem__(self, key, value)
def __repr__(self):
- return "immutabledict(%s)" % dict.__repr__(self)
+ return "FacadeDict(%s)" % dict.__repr__(self)
class Properties(object):