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

Proposed by Colin Watson on 2019-08-11
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 on 2019-08-12
Storm Developers 2019-08-11 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.
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'storm/cache.py'
2--- storm/cache.py 2019-06-05 11:41:07 +0000
3+++ storm/cache.py 2019-08-11 09:53:43 +0000
4@@ -2,6 +2,8 @@
5
6 import itertools
7
8+import six
9+
10
11 class Cache(object):
12 """Prevents recently used objects from being deallocated.
13@@ -142,9 +144,10 @@
14 objects, but no more than twice that number.
15 """
16 self._size = size
17- cache = itertools.islice(itertools.chain(self._new_cache.iteritems(),
18- self._old_cache.iteritems()),
19- 0, size)
20+ cache = itertools.islice(
21+ itertools.chain(six.iteritems(self._new_cache),
22+ six.iteritems(self._old_cache)),
23+ 0, size)
24 self._new_cache = dict(cache)
25 self._old_cache.clear()
26
27
28=== modified file 'storm/cextensions.c'
29--- storm/cextensions.c 2019-06-19 09:34:36 +0000
30+++ storm/cextensions.c 2019-08-11 09:53:43 +0000
31@@ -1931,7 +1931,7 @@
32 PyObject *column, *variable, *tmp;
33 Py_ssize_t i = 0;
34
35- /* for variable in self.variables.itervalues(): */
36+ /* for variable in six.itervalues(self.variables): */
37 while (PyDict_Next(self->variables, &i, &column, &variable)) {
38 /* variable.checkpoint() */
39 CATCH(NULL, tmp = PyObject_CallMethod(variable, "checkpoint", NULL));
40
41=== modified file 'storm/expr.py'
42--- storm/expr.py 2019-06-07 16:36:44 +0000
43+++ storm/expr.py 2019-08-11 09:53:43 +0000
44@@ -740,7 +740,7 @@
45 state.context = EXPR
46 values = insert.values
47 if values is Undef:
48- values = [tuple(insert.map.itervalues())]
49+ values = [tuple(six.itervalues(insert.map))]
50 if isinstance(values, Expr):
51 compiled_values = compile(values, state)
52 else:
53
54=== modified file 'storm/info.py'
55--- storm/info.py 2019-06-05 11:41:07 +0000
56+++ storm/info.py 2019-08-11 09:53:43 +0000
57@@ -22,6 +22,8 @@
58
59 from weakref import ref
60
61+import six
62+
63 from storm.exceptions import ClassInfoError
64 from storm.expr import Column, Desc, TABLE
65 from storm.expr import compile, Table
66@@ -194,7 +196,7 @@
67 self.event.emit("object-deleted")
68
69 def checkpoint(self):
70- for variable in self.variables.itervalues():
71+ for variable in six.itervalues(self.variables):
72 variable.checkpoint()
73
74
75
76=== modified file 'storm/references.py'
77--- storm/references.py 2019-06-05 11:41:07 +0000
78+++ storm/references.py 2019-08-11 09:53:43 +0000
79@@ -22,6 +22,8 @@
80
81 import weakref
82
83+import six
84+
85 from storm.exceptions import (
86 ClassInfoError, FeatureError, NoStoreError, WrongStoreError)
87 from storm.store import Store, get_where_for_args, LostObjectError
88@@ -940,14 +942,14 @@
89
90 def _find_descriptor_class(used_cls, descr):
91 for cls in used_cls.__mro__:
92- for attr, _descr in cls.__dict__.iteritems():
93+ for attr, _descr in six.iteritems(cls.__dict__):
94 if _descr is descr:
95 return cls
96 raise RuntimeError("Reference used in an unknown class")
97
98 def _find_descriptor_obj(used_cls, descr):
99 for cls in used_cls.__mro__:
100- for attr, _descr in cls.__dict__.iteritems():
101+ for attr, _descr in six.iteritems(cls.__dict__):
102 if _descr is descr:
103 return getattr(cls, attr)
104 raise RuntimeError("Reference used in an unknown class")
105
106=== modified file 'storm/sqlobject.py'
107--- storm/sqlobject.py 2019-06-05 11:41:07 +0000
108+++ storm/sqlobject.py 2019-08-11 09:53:43 +0000
109@@ -28,6 +28,8 @@
110 import re
111 import warnings
112
113+import six
114+
115 from storm.properties import (
116 RawStr, Int, Bool, Float, DateTime, Date, TimeDelta)
117 from storm.references import Reference, ReferenceSet
118@@ -164,7 +166,7 @@
119 dict["__storm_table__"] = table_name
120
121 attr_to_prop = {}
122- for attr, prop in dict.items():
123+ for attr, prop in list(six.iteritems(dict)):
124 attr_to_prop[attr] = attr
125 if isinstance(prop, ForeignKey):
126 db_name = prop.kwargs.get("dbName", attr)
127@@ -224,7 +226,7 @@
128 property_registry.add_property(obj, getattr(obj, "id"),
129 "<table %s>" % table_name)
130
131- for fake_name, real_name in attr_to_prop.items():
132+ for fake_name, real_name in list(six.iteritems(attr_to_prop)):
133 prop = getattr(obj, real_name)
134 if fake_name != real_name:
135 property_registry.add_property(obj, prop, fake_name)
136@@ -298,7 +300,7 @@
137 self._init(None)
138
139 def set(self, **kwargs):
140- for attr, value in kwargs.iteritems():
141+ for attr, value in six.iteritems(kwargs):
142 setattr(self, attr, value)
143
144 def destroySelf(self):
145@@ -406,7 +408,7 @@
146
147 def _copy(self, **kwargs):
148 copy = self.__class__(self._cls, **kwargs)
149- for name, value in self.__dict__.iteritems():
150+ for name, value in six.iteritems(self.__dict__):
151 if name[1:] not in kwargs and name != "_finished_result_set":
152 setattr(copy, name, value)
153 return copy
154
155=== modified file 'storm/store.py'
156--- storm/store.py 2019-06-05 11:41:07 +0000
157+++ storm/store.py 2019-08-11 09:53:43 +0000
158@@ -474,7 +474,7 @@
159 self._dirty = flushing
160
161 predecessors = {}
162- for (before_info, after_info), n in self._order.iteritems():
163+ for (before_info, after_info), n in six.iteritems(self._order):
164 if n > 0:
165 before_set = predecessors.get(after_info)
166 if before_set is None:
167@@ -853,7 +853,7 @@
168 del obj_info["primary_vars"]
169
170 def _iter_alive(self):
171- return self._alive.values()
172+ return list(six.itervalues(self._alive))
173
174 def _enable_change_notification(self, obj_info):
175 obj_info.event.emit("start-tracking-changes", self._event)
176@@ -1406,7 +1406,7 @@
177 for column in changes:
178 obj_info.variables[column].set(AutoReload)
179 else:
180- changes = changes.items()
181+ changes = list(six.iteritems(changes))
182 for obj in cached:
183 for column, value in changes:
184 variables = get_obj_info(obj).variables
185
186=== modified file 'storm/tz.py'
187--- storm/tz.py 2019-08-09 13:09:09 +0000
188+++ storm/tz.py 2019-08-11 09:53:43 +0000
189@@ -15,6 +15,8 @@
190 import sys
191 import os
192
193+import six
194+
195 relativedelta = None
196 parser = None
197 rrule = None
198@@ -714,7 +716,7 @@
199
200 def get(self, tzid=None):
201 if tzid is None:
202- keys = self._vtz.keys()
203+ keys = list(six.iterkeys(self._vtz))
204 if len(keys) == 0:
205 raise Exception("no timezones defined")
206 elif len(keys) > 1:
207
208=== modified file 'storm/uri.py'
209--- storm/uri.py 2019-06-07 17:14:33 +0000
210+++ storm/uri.py 2019-08-11 09:53:43 +0000
211@@ -20,6 +20,7 @@
212 #
213 from __future__ import print_function
214
215+import six
216 from six.moves.urllib.parse import quote
217
218 from storm.exceptions import URIError
219@@ -104,7 +105,7 @@
220 append(escape(self.database, "/"))
221 if self.options:
222 options = ["%s=%s" % (escape(key), escape(value))
223- for key, value in sorted(self.options.iteritems())]
224+ for key, value in sorted(six.iteritems(self.options))]
225 append("?")
226 append("&".join(options))
227 return "".join(tokens)
228
229=== modified file 'storm/zope/testing.py'
230--- storm/zope/testing.py 2019-06-05 11:41:07 +0000
231+++ storm/zope/testing.py 2019-08-11 09:53:43 +0000
232@@ -23,6 +23,7 @@
233 import os
234 import shutil
235
236+import six
237 import transaction
238
239 from testresources import TestResourceManager
240@@ -99,8 +100,9 @@
241 # Adapt the old databases format to the new one, for backward
242 # compatibility. This should be eventually dropped.
243 if isinstance(databases, dict):
244- databases = [{"name": name, "uri": uri, "schema": schema}
245- for name, (uri, schema) in databases.iteritems()]
246+ databases = [
247+ {"name": name, "uri": uri, "schema": schema}
248+ for name, (uri, schema) in six.iteritems(databases)]
249
250 # Provide the global IZStorm utility before applying patches, so
251 # patch code can get the ztorm object if needed (e.g. looking up
252
253=== modified file 'storm/zope/zstorm.py'
254--- storm/zope/zstorm.py 2019-06-06 10:14:55 +0000
255+++ storm/zope/zstorm.py 2019-08-11 09:53:43 +0000
256@@ -31,6 +31,7 @@
257
258 from uuid import uuid4
259
260+import six
261 from zope.interface import implementer
262
263 import transaction
264@@ -206,11 +207,11 @@
265
266 def iterstores(self):
267 """Iterate C{name, store} 2-tuples."""
268- # items is explicitly used here, instead of iteritems, to
269- # avoid the problem where a store is deallocated during
270+ # We explicitly copy the list of items before iterating over
271+ # it to avoid the problem where a store is deallocated during
272 # iteration causing RuntimeError: dictionary changed size
273 # during iteration.
274- for store, name in self._name_index.items():
275+ for store, name in list(six.iteritems(self._name_index)):
276 yield name, store
277
278 def get_name(self, store):
279
280=== modified file 'tests/mocker.py'
281--- tests/mocker.py 2019-06-07 17:14:33 +0000
282+++ tests/mocker.py 2019-08-11 09:53:43 +0000
283@@ -13,6 +13,7 @@
284 import os
285 import gc
286
287+import six
288 from six.moves import builtins
289
290
291@@ -1109,13 +1110,13 @@
292 frame = sys._getframe(depth+1)
293 except:
294 return None
295- for name, frame_obj in frame.f_locals.iteritems():
296+ for name, frame_obj in six.iteritems(frame.f_locals):
297 if frame_obj is obj:
298 return name
299 self = frame.f_locals.get("self")
300 if self is not None:
301 try:
302- items = list(self.__dict__.iteritems())
303+ items = list(six.iteritems(self.__dict__))
304 except:
305 pass
306 else:
307@@ -1264,7 +1265,7 @@
308 result = "del %s.%s" % (result, action.args[0])
309 elif action.kind == "call":
310 args = [repr(x) for x in action.args]
311- items = list(action.kwargs.iteritems())
312+ items = list(six.iteritems(action.kwargs))
313 items.sort()
314 for pair in items:
315 args.append("%s=%r" % pair)
316@@ -1384,7 +1385,7 @@
317
318 # Either we have the same number of kwargs, or unknown keywords are
319 # accepted (KWARGS was used), so check just the ones in kwargs1.
320- for key, arg1 in kwargs1.iteritems():
321+ for key, arg1 in six.iteritems(kwargs1):
322 if key not in kwargs2:
323 return False
324 arg2 = kwargs2[key]
325@@ -1914,7 +1915,7 @@
326 for referrer in gc.get_referrers(remove):
327 if (type(referrer) is dict and
328 referrer.get("__mocker_replace__", True)):
329- for key, value in referrer.items():
330+ for key, value in list(six.iteritems(referrer)):
331 if value is remove:
332 referrer[key] = install
333
334@@ -1986,7 +1987,7 @@
335 for kind in self._monitored:
336 attr = self._get_kind_attr(kind)
337 seen = set()
338- for obj in self._monitored[kind].itervalues():
339+ for obj in six.itervalues(self._monitored[kind]):
340 cls = type(obj)
341 if issubclass(cls, type):
342 cls = obj
343@@ -2000,7 +2001,7 @@
344 self.execute)
345
346 def restore(self):
347- for obj, attr, original in self._patched.itervalues():
348+ for obj, attr, original in six.itervalues(self._patched):
349 if original is Undefined:
350 delattr(obj, attr)
351 else:
352
353=== modified file 'tests/store/base.py'
354--- tests/store/base.py 2019-06-07 17:14:33 +0000
355+++ tests/store/base.py 2019-08-11 09:53:43 +0000
356@@ -4946,7 +4946,7 @@
357 foo = self.store.get(DictFoo, 20)
358 foo["a"] = 1
359
360- self.assertEquals(foo.items(), [("a", 1)])
361+ self.assertEquals(list(six.iteritems(foo)), [("a", 1)])
362
363 new_obj = DictFoo()
364 new_obj.id = 40
365
366=== modified file 'tests/zope/testing.py'
367--- tests/zope/testing.py 2019-06-05 11:41:07 +0000
368+++ tests/zope/testing.py 2019-08-11 09:53:43 +0000
369@@ -23,6 +23,8 @@
370 import os
371 import sys
372
373+import six
374+
375 from tests.helper import TestHelper
376 from tests.zope import has_transaction, has_zope_component, has_testresources
377
378@@ -239,7 +241,7 @@
379 real_invalidate = store.invalidate
380
381 def invalidate_proxy():
382- self.assertEqual(0, len(store._alive.values()))
383+ self.assertEqual(0, len(list(six.itervalues(store._alive))))
384 real_invalidate()
385 store.invalidate = invalidate_proxy
386

Subscribers

People subscribed via source and target branches

to status/vote changes: