Merge lp:~lifeless/testresources/bug-271619 into lp:~testresources-developers/testresources/trunk

Proposed by Robert Collins
Status: Merged
Merged at revision: not available
Proposed branch: lp:~lifeless/testresources/bug-271619
Merge into: lp:~testresources-developers/testresources/trunk
Diff against target: None lines
To merge this branch: bzr merge lp:~lifeless/testresources/bug-271619
Reviewer Review Type Date Requested Status
Jonathan Lange Approve
James Henstridge Pending
testresources developers Pending
Review via email: mp+7610@code.launchpad.net
To post a comment you must log in.
Revision history for this message
Jonathan Lange (jml) wrote :

I think this patch is fundamentally correct and adds a useful feature.

However, I think the docstring for `reset` should be changed so that the first line says something like, "Return a clean version of 'old_resource'". That is, it should describe what the method does.

The docstring should also provide some hints as to *why* one might want to override the method. One way to do this would be to follow-up the "By default" sentence with "If there is a faster way of resetting the resource than cleaning it and remaking it, you probably want to override this method to do that." Or something along those lines.

Thanks for the patch & for dealing with this long-dormant bug.

jml

review: Approve
Revision history for this message
Robert Collins (lifeless) wrote :

Some views on code only show the first line, and as an intentionally overridable method I think its important to keep that in there. However - "Overridable method to return a clean version of old_resource." should meet your points too.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'NEWS'
2--- NEWS 2009-06-17 10:23:42 +0000
3+++ NEWS 2009-06-18 10:36:00 +0000
4@@ -19,6 +19,11 @@
5
6 * Expanded TODO. (Jonathan Lange)
7
8+ * Resources can now be reset by overriding TestResource.reset, which for
9+ some resources is significantly cheaper. If checking for dirtiness is
10+ expensive, isDirty can also be overridden.
11+ (James Henstridge, Robert Collins)
12+
13 * Started keeping a NEWS file! (Jonathan Lange)
14
15 BUG FIXES:
16
17=== modified file 'lib/testresources/__init__.py'
18--- lib/testresources/__init__.py 2009-06-17 10:23:42 +0000
19+++ lib/testresources/__init__.py 2009-06-18 10:36:00 +0000
20@@ -203,7 +203,7 @@
21 self._currentResource = None
22 self.resources = list(getattr(self.__class__, "resources", []))
23
24- def clean_all(self, resource):
25+ def _clean_all(self, resource):
26 """Clean the dependencies from resource, and then resource itself."""
27 self.clean(resource)
28 for name, manager in self.resources:
29@@ -233,7 +233,7 @@
30 """
31 self._uses -= 1
32 if self._uses == 0:
33- self.clean_all(resource)
34+ self._clean_all(resource)
35 self._setResource(None)
36
37 def getResource(self):
38@@ -245,9 +245,9 @@
39 that it is no longer needed.
40 """
41 if self._uses == 0:
42- self._setResource(self.make_all())
43+ self._setResource(self._make_all())
44 elif self.isDirty():
45- self._resetResource(self._currentResource)
46+ self._setResource(self.reset(self._currentResource))
47 self._uses += 1
48 return self._currentResource
49
50@@ -269,7 +269,7 @@
51 finally:
52 mgr.finishedWith(res)
53
54- def make_all(self):
55+ def _make_all(self):
56 """Make the dependencies of this resource and this resource."""
57 dependency_resources = {}
58 for name, resource in self.resources:
59@@ -305,9 +305,23 @@
60 result.append(self)
61 return result
62
63- def _resetResource(self, old_resource):
64- self.clean_all(old_resource)
65- self._setResource(self.make_all())
66+ def reset(self, old_resource):
67+ """Override this to reset resources.
68+
69+ By default, the resource will be cleaned then remade if it had
70+ previously been `dirtied`.
71+
72+ This function needs to take the dependent resource stack into
73+ consideration as _make_all and _clean_all do.
74+
75+ :return: The new resource.
76+ """
77+ if self._dirty:
78+ self._clean_all(old_resource)
79+ resource = self._make_all()
80+ else:
81+ resource = old_resource
82+ return resource
83
84 def _setResource(self, new_resource):
85 """Set the current resource to a new value."""
86
87=== modified file 'lib/testresources/tests/test_test_resource.py'
88--- lib/testresources/tests/test_test_resource.py 2009-06-17 10:23:42 +0000
89+++ lib/testresources/tests/test_test_resource.py 2009-06-18 10:36:00 +0000
90@@ -57,6 +57,19 @@
91 return MockResourceInstance("Boo!")
92
93
94+class MockResettableResource(MockResource):
95+ """Mock resource that logs the number of reset calls too."""
96+
97+ def __init__(self):
98+ MockResource.__init__(self)
99+ self.resets = 0
100+
101+ def reset(self, resource):
102+ self.resets += 1
103+ resource._name += "!"
104+ return resource
105+
106+
107 class TestTestResource(testtools.TestCase):
108
109 def testUnimplementedGetResource(self):
110@@ -183,6 +196,33 @@
111 resource_manager.getResource()
112 self.assertEqual(1, resource_manager.makes)
113
114+ def testGetResourceResetsUsedResource(self):
115+ resource_manager = MockResettableResource()
116+ resource_manager.getResource()
117+ resource = resource_manager.getResource()
118+ self.assertEqual(1, resource_manager.makes)
119+ resource_manager.dirtied(resource)
120+ resource_manager.getResource()
121+ self.assertEqual(1, resource_manager.makes)
122+ self.assertEqual(1, resource_manager.resets)
123+ resource_manager.finishedWith(resource)
124+
125+ def testUsedResourceResetBetweenUses(self):
126+ resource_manager = MockResettableResource()
127+ # take two refs; like happens with OptimisingTestSuite.
128+ resource_manager.getResource()
129+ resource = resource_manager.getResource()
130+ resource_manager.dirtied(resource)
131+ resource_manager.finishedWith(resource)
132+ # Get again, but its been dirtied.
133+ resource = resource_manager.getResource()
134+ resource_manager.finishedWith(resource)
135+ resource_manager.finishedWith(resource)
136+ # The resource is made once, reset once and cleaned once.
137+ self.assertEqual(1, resource_manager.makes)
138+ self.assertEqual(1, resource_manager.resets)
139+ self.assertEqual(1, resource_manager.cleans)
140+
141 def testFinishedWithDecrementsUses(self):
142 resource_manager = MockResource()
143 resource = resource_manager.getResource()
144@@ -237,6 +277,8 @@
145 resource_manager.finishedWith(resource)
146 self.assertIs(resource, resource_manager._currentResource)
147
148+ # The default implementation of reset() performs a make/clean if
149+ # the dirty flag is set.
150 def testDirtiedSetsDirty(self):
151 resource_manager = MockResource()
152 resource = resource_manager.getResource()
153@@ -257,15 +299,23 @@
154 resource_manager.finishedWith(resource1)
155 self.assertEqual(2, resource_manager.cleans)
156
157- def testDirtyingResourceTriggersRemake(self):
158+ def testDefaultResetMethodPreservesCleanResource(self):
159+ resource_manager = MockResource()
160+ resource = resource_manager.getResource()
161+ self.assertEqual(1, resource_manager.makes)
162+ self.assertEqual(False, resource_manager._dirty)
163+ resource_manager.reset(resource)
164+ self.assertEqual(1, resource_manager.makes)
165+ self.assertEqual(0, resource_manager.cleans)
166+
167+ def testDefaultResetMethodRecreatesDirtyResource(self):
168 resource_manager = MockResource()
169 resource = resource_manager.getResource()
170 self.assertEqual(1, resource_manager.makes)
171 resource_manager.dirtied(resource)
172- resource_manager.getResource()
173+ resource_manager.reset(resource)
174+ self.assertEqual(2, resource_manager.makes)
175 self.assertEqual(1, resource_manager.cleans)
176- self.assertEqual(2, resource_manager.makes)
177- self.assertEqual(False, resource_manager._dirty)
178
179 def testDirtyingWhenUnused(self):
180 resource_manager = MockResource()

Subscribers

People subscribed via source and target branches