Merge lp:~cjwatson/storm/py3-dict into lp:storm

Proposed by Colin Watson
Status: Merged
Merged at revision: 514
Proposed branch: lp:~cjwatson/storm/py3-dict
Merge into: lp:storm
Diff against target: 385 lines (+49/-31)
14 files modified
storm/cache.py (+6/-3)
storm/cextensions.c (+1/-1)
storm/expr.py (+1/-1)
storm/info.py (+3/-1)
storm/references.py (+4/-2)
storm/sqlobject.py (+6/-4)
storm/store.py (+3/-3)
storm/tz.py (+3/-1)
storm/uri.py (+2/-1)
storm/zope/testing.py (+4/-2)
storm/zope/zstorm.py (+4/-3)
tests/mocker.py (+8/-7)
tests/store/base.py (+1/-1)
tests/zope/testing.py (+3/-1)
To merge this branch: bzr merge lp:~cjwatson/storm/py3-dict
Reviewer Review Type Date Requested Status
Kristian Glass (community) Approve
Storm Developers Pending
Review via email: mp+371160@code.launchpad.net

Commit message

Handle Python 3's changes to dict iteration methods.

Description of the change

In most cases I opted for a somewhat pedantic translation of d.iterfoo() to six.iterfoo(d) and d.foo() to list(six.iterfoo(d)), since there are enough cases where this matters either for performance or to avoid iterating over a dictionary while modifying it that it's simplest to be consistent.

There were a few cases where the Python 2 code was iterating over something like d.items() when it didn't need to do a copy; I left those cases alone, since they'll just become slightly more efficient under Python 3.

To post a comment you must log in.
Revision history for this message
Kristian Glass (doismellburning) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'storm/cache.py'
--- storm/cache.py 2019-06-05 11:41:07 +0000
+++ storm/cache.py 2019-08-11 09:53:43 +0000
@@ -2,6 +2,8 @@
22
3import itertools3import itertools
44
5import six
6
57
6class Cache(object):8class Cache(object):
7 """Prevents recently used objects from being deallocated.9 """Prevents recently used objects from being deallocated.
@@ -142,9 +144,10 @@
142 objects, but no more than twice that number.144 objects, but no more than twice that number.
143 """145 """
144 self._size = size146 self._size = size
145 cache = itertools.islice(itertools.chain(self._new_cache.iteritems(),147 cache = itertools.islice(
146 self._old_cache.iteritems()),148 itertools.chain(six.iteritems(self._new_cache),
147 0, size)149 six.iteritems(self._old_cache)),
150 0, size)
148 self._new_cache = dict(cache)151 self._new_cache = dict(cache)
149 self._old_cache.clear()152 self._old_cache.clear()
150153
151154
=== modified file 'storm/cextensions.c'
--- storm/cextensions.c 2019-06-19 09:34:36 +0000
+++ storm/cextensions.c 2019-08-11 09:53:43 +0000
@@ -1931,7 +1931,7 @@
1931 PyObject *column, *variable, *tmp;1931 PyObject *column, *variable, *tmp;
1932 Py_ssize_t i = 0;1932 Py_ssize_t i = 0;
19331933
1934 /* for variable in self.variables.itervalues(): */1934 /* for variable in six.itervalues(self.variables): */
1935 while (PyDict_Next(self->variables, &i, &column, &variable)) {1935 while (PyDict_Next(self->variables, &i, &column, &variable)) {
1936 /* variable.checkpoint() */1936 /* variable.checkpoint() */
1937 CATCH(NULL, tmp = PyObject_CallMethod(variable, "checkpoint", NULL));1937 CATCH(NULL, tmp = PyObject_CallMethod(variable, "checkpoint", NULL));
19381938
=== modified file 'storm/expr.py'
--- storm/expr.py 2019-06-07 16:36:44 +0000
+++ storm/expr.py 2019-08-11 09:53:43 +0000
@@ -740,7 +740,7 @@
740 state.context = EXPR740 state.context = EXPR
741 values = insert.values741 values = insert.values
742 if values is Undef:742 if values is Undef:
743 values = [tuple(insert.map.itervalues())]743 values = [tuple(six.itervalues(insert.map))]
744 if isinstance(values, Expr):744 if isinstance(values, Expr):
745 compiled_values = compile(values, state)745 compiled_values = compile(values, state)
746 else:746 else:
747747
=== modified file 'storm/info.py'
--- storm/info.py 2019-06-05 11:41:07 +0000
+++ storm/info.py 2019-08-11 09:53:43 +0000
@@ -22,6 +22,8 @@
2222
23from weakref import ref23from weakref import ref
2424
25import six
26
25from storm.exceptions import ClassInfoError27from storm.exceptions import ClassInfoError
26from storm.expr import Column, Desc, TABLE28from storm.expr import Column, Desc, TABLE
27from storm.expr import compile, Table29from storm.expr import compile, Table
@@ -194,7 +196,7 @@
194 self.event.emit("object-deleted")196 self.event.emit("object-deleted")
195197
196 def checkpoint(self):198 def checkpoint(self):
197 for variable in self.variables.itervalues():199 for variable in six.itervalues(self.variables):
198 variable.checkpoint()200 variable.checkpoint()
199201
200202
201203
=== modified file 'storm/references.py'
--- storm/references.py 2019-06-05 11:41:07 +0000
+++ storm/references.py 2019-08-11 09:53:43 +0000
@@ -22,6 +22,8 @@
2222
23import weakref23import weakref
2424
25import six
26
25from storm.exceptions import (27from storm.exceptions import (
26 ClassInfoError, FeatureError, NoStoreError, WrongStoreError)28 ClassInfoError, FeatureError, NoStoreError, WrongStoreError)
27from storm.store import Store, get_where_for_args, LostObjectError29from storm.store import Store, get_where_for_args, LostObjectError
@@ -940,14 +942,14 @@
940942
941def _find_descriptor_class(used_cls, descr):943def _find_descriptor_class(used_cls, descr):
942 for cls in used_cls.__mro__:944 for cls in used_cls.__mro__:
943 for attr, _descr in cls.__dict__.iteritems():945 for attr, _descr in six.iteritems(cls.__dict__):
944 if _descr is descr:946 if _descr is descr:
945 return cls947 return cls
946 raise RuntimeError("Reference used in an unknown class")948 raise RuntimeError("Reference used in an unknown class")
947949
948def _find_descriptor_obj(used_cls, descr):950def _find_descriptor_obj(used_cls, descr):
949 for cls in used_cls.__mro__:951 for cls in used_cls.__mro__:
950 for attr, _descr in cls.__dict__.iteritems():952 for attr, _descr in six.iteritems(cls.__dict__):
951 if _descr is descr:953 if _descr is descr:
952 return getattr(cls, attr)954 return getattr(cls, attr)
953 raise RuntimeError("Reference used in an unknown class")955 raise RuntimeError("Reference used in an unknown class")
954956
=== modified file 'storm/sqlobject.py'
--- storm/sqlobject.py 2019-06-05 11:41:07 +0000
+++ storm/sqlobject.py 2019-08-11 09:53:43 +0000
@@ -28,6 +28,8 @@
28import re28import re
29import warnings29import warnings
3030
31import six
32
31from storm.properties import (33from storm.properties import (
32 RawStr, Int, Bool, Float, DateTime, Date, TimeDelta)34 RawStr, Int, Bool, Float, DateTime, Date, TimeDelta)
33from storm.references import Reference, ReferenceSet35from storm.references import Reference, ReferenceSet
@@ -164,7 +166,7 @@
164 dict["__storm_table__"] = table_name166 dict["__storm_table__"] = table_name
165167
166 attr_to_prop = {}168 attr_to_prop = {}
167 for attr, prop in dict.items():169 for attr, prop in list(six.iteritems(dict)):
168 attr_to_prop[attr] = attr170 attr_to_prop[attr] = attr
169 if isinstance(prop, ForeignKey):171 if isinstance(prop, ForeignKey):
170 db_name = prop.kwargs.get("dbName", attr)172 db_name = prop.kwargs.get("dbName", attr)
@@ -224,7 +226,7 @@
224 property_registry.add_property(obj, getattr(obj, "id"),226 property_registry.add_property(obj, getattr(obj, "id"),
225 "<table %s>" % table_name)227 "<table %s>" % table_name)
226228
227 for fake_name, real_name in attr_to_prop.items():229 for fake_name, real_name in list(six.iteritems(attr_to_prop)):
228 prop = getattr(obj, real_name)230 prop = getattr(obj, real_name)
229 if fake_name != real_name:231 if fake_name != real_name:
230 property_registry.add_property(obj, prop, fake_name)232 property_registry.add_property(obj, prop, fake_name)
@@ -298,7 +300,7 @@
298 self._init(None)300 self._init(None)
299301
300 def set(self, **kwargs):302 def set(self, **kwargs):
301 for attr, value in kwargs.iteritems():303 for attr, value in six.iteritems(kwargs):
302 setattr(self, attr, value)304 setattr(self, attr, value)
303305
304 def destroySelf(self):306 def destroySelf(self):
@@ -406,7 +408,7 @@
406408
407 def _copy(self, **kwargs):409 def _copy(self, **kwargs):
408 copy = self.__class__(self._cls, **kwargs)410 copy = self.__class__(self._cls, **kwargs)
409 for name, value in self.__dict__.iteritems():411 for name, value in six.iteritems(self.__dict__):
410 if name[1:] not in kwargs and name != "_finished_result_set":412 if name[1:] not in kwargs and name != "_finished_result_set":
411 setattr(copy, name, value)413 setattr(copy, name, value)
412 return copy414 return copy
413415
=== modified file 'storm/store.py'
--- storm/store.py 2019-06-05 11:41:07 +0000
+++ storm/store.py 2019-08-11 09:53:43 +0000
@@ -474,7 +474,7 @@
474 self._dirty = flushing474 self._dirty = flushing
475475
476 predecessors = {}476 predecessors = {}
477 for (before_info, after_info), n in self._order.iteritems():477 for (before_info, after_info), n in six.iteritems(self._order):
478 if n > 0:478 if n > 0:
479 before_set = predecessors.get(after_info)479 before_set = predecessors.get(after_info)
480 if before_set is None:480 if before_set is None:
@@ -853,7 +853,7 @@
853 del obj_info["primary_vars"]853 del obj_info["primary_vars"]
854854
855 def _iter_alive(self):855 def _iter_alive(self):
856 return self._alive.values()856 return list(six.itervalues(self._alive))
857857
858 def _enable_change_notification(self, obj_info):858 def _enable_change_notification(self, obj_info):
859 obj_info.event.emit("start-tracking-changes", self._event)859 obj_info.event.emit("start-tracking-changes", self._event)
@@ -1406,7 +1406,7 @@
1406 for column in changes:1406 for column in changes:
1407 obj_info.variables[column].set(AutoReload)1407 obj_info.variables[column].set(AutoReload)
1408 else:1408 else:
1409 changes = changes.items()1409 changes = list(six.iteritems(changes))
1410 for obj in cached:1410 for obj in cached:
1411 for column, value in changes:1411 for column, value in changes:
1412 variables = get_obj_info(obj).variables1412 variables = get_obj_info(obj).variables
14131413
=== modified file 'storm/tz.py'
--- storm/tz.py 2019-08-09 13:09:09 +0000
+++ storm/tz.py 2019-08-11 09:53:43 +0000
@@ -15,6 +15,8 @@
15import sys15import sys
16import os16import os
1717
18import six
19
18relativedelta = None20relativedelta = None
19parser = None21parser = None
20rrule = None22rrule = None
@@ -714,7 +716,7 @@
714716
715 def get(self, tzid=None):717 def get(self, tzid=None):
716 if tzid is None:718 if tzid is None:
717 keys = self._vtz.keys()719 keys = list(six.iterkeys(self._vtz))
718 if len(keys) == 0:720 if len(keys) == 0:
719 raise Exception("no timezones defined")721 raise Exception("no timezones defined")
720 elif len(keys) > 1:722 elif len(keys) > 1:
721723
=== modified file 'storm/uri.py'
--- storm/uri.py 2019-06-07 17:14:33 +0000
+++ storm/uri.py 2019-08-11 09:53:43 +0000
@@ -20,6 +20,7 @@
20#20#
21from __future__ import print_function21from __future__ import print_function
2222
23import six
23from six.moves.urllib.parse import quote24from six.moves.urllib.parse import quote
2425
25from storm.exceptions import URIError26from storm.exceptions import URIError
@@ -104,7 +105,7 @@
104 append(escape(self.database, "/"))105 append(escape(self.database, "/"))
105 if self.options:106 if self.options:
106 options = ["%s=%s" % (escape(key), escape(value))107 options = ["%s=%s" % (escape(key), escape(value))
107 for key, value in sorted(self.options.iteritems())]108 for key, value in sorted(six.iteritems(self.options))]
108 append("?")109 append("?")
109 append("&".join(options))110 append("&".join(options))
110 return "".join(tokens)111 return "".join(tokens)
111112
=== modified file 'storm/zope/testing.py'
--- storm/zope/testing.py 2019-06-05 11:41:07 +0000
+++ storm/zope/testing.py 2019-08-11 09:53:43 +0000
@@ -23,6 +23,7 @@
23import os23import os
24import shutil24import shutil
2525
26import six
26import transaction27import transaction
2728
28from testresources import TestResourceManager29from testresources import TestResourceManager
@@ -99,8 +100,9 @@
99 # Adapt the old databases format to the new one, for backward100 # Adapt the old databases format to the new one, for backward
100 # compatibility. This should be eventually dropped.101 # compatibility. This should be eventually dropped.
101 if isinstance(databases, dict):102 if isinstance(databases, dict):
102 databases = [{"name": name, "uri": uri, "schema": schema}103 databases = [
103 for name, (uri, schema) in databases.iteritems()]104 {"name": name, "uri": uri, "schema": schema}
105 for name, (uri, schema) in six.iteritems(databases)]
104106
105 # Provide the global IZStorm utility before applying patches, so107 # Provide the global IZStorm utility before applying patches, so
106 # patch code can get the ztorm object if needed (e.g. looking up108 # patch code can get the ztorm object if needed (e.g. looking up
107109
=== modified file 'storm/zope/zstorm.py'
--- storm/zope/zstorm.py 2019-06-06 10:14:55 +0000
+++ storm/zope/zstorm.py 2019-08-11 09:53:43 +0000
@@ -31,6 +31,7 @@
3131
32from uuid import uuid432from uuid import uuid4
3333
34import six
34from zope.interface import implementer35from zope.interface import implementer
3536
36import transaction37import transaction
@@ -206,11 +207,11 @@
206207
207 def iterstores(self):208 def iterstores(self):
208 """Iterate C{name, store} 2-tuples."""209 """Iterate C{name, store} 2-tuples."""
209 # items is explicitly used here, instead of iteritems, to210 # We explicitly copy the list of items before iterating over
210 # avoid the problem where a store is deallocated during211 # it to avoid the problem where a store is deallocated during
211 # iteration causing RuntimeError: dictionary changed size212 # iteration causing RuntimeError: dictionary changed size
212 # during iteration.213 # during iteration.
213 for store, name in self._name_index.items():214 for store, name in list(six.iteritems(self._name_index)):
214 yield name, store215 yield name, store
215216
216 def get_name(self, store):217 def get_name(self, store):
217218
=== modified file 'tests/mocker.py'
--- tests/mocker.py 2019-06-07 17:14:33 +0000
+++ tests/mocker.py 2019-08-11 09:53:43 +0000
@@ -13,6 +13,7 @@
13import os13import os
14import gc14import gc
1515
16import six
16from six.moves import builtins17from six.moves import builtins
1718
1819
@@ -1109,13 +1110,13 @@
1109 frame = sys._getframe(depth+1)1110 frame = sys._getframe(depth+1)
1110 except:1111 except:
1111 return None1112 return None
1112 for name, frame_obj in frame.f_locals.iteritems():1113 for name, frame_obj in six.iteritems(frame.f_locals):
1113 if frame_obj is obj:1114 if frame_obj is obj:
1114 return name1115 return name
1115 self = frame.f_locals.get("self")1116 self = frame.f_locals.get("self")
1116 if self is not None:1117 if self is not None:
1117 try:1118 try:
1118 items = list(self.__dict__.iteritems())1119 items = list(six.iteritems(self.__dict__))
1119 except:1120 except:
1120 pass1121 pass
1121 else:1122 else:
@@ -1264,7 +1265,7 @@
1264 result = "del %s.%s" % (result, action.args[0])1265 result = "del %s.%s" % (result, action.args[0])
1265 elif action.kind == "call":1266 elif action.kind == "call":
1266 args = [repr(x) for x in action.args]1267 args = [repr(x) for x in action.args]
1267 items = list(action.kwargs.iteritems())1268 items = list(six.iteritems(action.kwargs))
1268 items.sort()1269 items.sort()
1269 for pair in items:1270 for pair in items:
1270 args.append("%s=%r" % pair)1271 args.append("%s=%r" % pair)
@@ -1384,7 +1385,7 @@
13841385
1385 # Either we have the same number of kwargs, or unknown keywords are1386 # Either we have the same number of kwargs, or unknown keywords are
1386 # accepted (KWARGS was used), so check just the ones in kwargs1.1387 # accepted (KWARGS was used), so check just the ones in kwargs1.
1387 for key, arg1 in kwargs1.iteritems():1388 for key, arg1 in six.iteritems(kwargs1):
1388 if key not in kwargs2:1389 if key not in kwargs2:
1389 return False1390 return False
1390 arg2 = kwargs2[key]1391 arg2 = kwargs2[key]
@@ -1914,7 +1915,7 @@
1914 for referrer in gc.get_referrers(remove):1915 for referrer in gc.get_referrers(remove):
1915 if (type(referrer) is dict and1916 if (type(referrer) is dict and
1916 referrer.get("__mocker_replace__", True)):1917 referrer.get("__mocker_replace__", True)):
1917 for key, value in referrer.items():1918 for key, value in list(six.iteritems(referrer)):
1918 if value is remove:1919 if value is remove:
1919 referrer[key] = install1920 referrer[key] = install
19201921
@@ -1986,7 +1987,7 @@
1986 for kind in self._monitored:1987 for kind in self._monitored:
1987 attr = self._get_kind_attr(kind)1988 attr = self._get_kind_attr(kind)
1988 seen = set()1989 seen = set()
1989 for obj in self._monitored[kind].itervalues():1990 for obj in six.itervalues(self._monitored[kind]):
1990 cls = type(obj)1991 cls = type(obj)
1991 if issubclass(cls, type):1992 if issubclass(cls, type):
1992 cls = obj1993 cls = obj
@@ -2000,7 +2001,7 @@
2000 self.execute)2001 self.execute)
20012002
2002 def restore(self):2003 def restore(self):
2003 for obj, attr, original in self._patched.itervalues():2004 for obj, attr, original in six.itervalues(self._patched):
2004 if original is Undefined:2005 if original is Undefined:
2005 delattr(obj, attr)2006 delattr(obj, attr)
2006 else:2007 else:
20072008
=== modified file 'tests/store/base.py'
--- tests/store/base.py 2019-06-07 17:14:33 +0000
+++ tests/store/base.py 2019-08-11 09:53:43 +0000
@@ -4946,7 +4946,7 @@
4946 foo = self.store.get(DictFoo, 20)4946 foo = self.store.get(DictFoo, 20)
4947 foo["a"] = 14947 foo["a"] = 1
49484948
4949 self.assertEquals(foo.items(), [("a", 1)])4949 self.assertEquals(list(six.iteritems(foo)), [("a", 1)])
49504950
4951 new_obj = DictFoo()4951 new_obj = DictFoo()
4952 new_obj.id = 404952 new_obj.id = 40
49534953
=== modified file 'tests/zope/testing.py'
--- tests/zope/testing.py 2019-06-05 11:41:07 +0000
+++ tests/zope/testing.py 2019-08-11 09:53:43 +0000
@@ -23,6 +23,8 @@
23import os23import os
24import sys24import sys
2525
26import six
27
26from tests.helper import TestHelper28from tests.helper import TestHelper
27from tests.zope import has_transaction, has_zope_component, has_testresources29from tests.zope import has_transaction, has_zope_component, has_testresources
2830
@@ -239,7 +241,7 @@
239 real_invalidate = store.invalidate241 real_invalidate = store.invalidate
240242
241 def invalidate_proxy():243 def invalidate_proxy():
242 self.assertEqual(0, len(store._alive.values()))244 self.assertEqual(0, len(list(six.itervalues(store._alive))))
243 real_invalidate()245 real_invalidate()
244 store.invalidate = invalidate_proxy246 store.invalidate = invalidate_proxy
245247

Subscribers

People subscribed via source and target branches

to status/vote changes: