Merge lp:~allenap/launchpad/series-init-failure-explanations-bug-835024 into lp:launchpad

Proposed by Gavin Panella
Status: Merged
Approved by: Gavin Panella
Approved revision: no longer in the source branch.
Merged at revision: 13907
Proposed branch: lp:~allenap/launchpad/series-init-failure-explanations-bug-835024
Merge into: lp:launchpad
Diff against target: 132 lines (+44/-7)
3 files modified
database/schema/security.cfg (+1/-1)
lib/lp/soyuz/model/initializedistroseriesjob.py (+22/-1)
lib/lp/soyuz/tests/test_initializedistroseriesjob.py (+21/-5)
To merge this branch: bzr merge lp:~allenap/launchpad/series-init-failure-explanations-bug-835024
Reviewer Review Type Date Requested Status
Brad Crittenden (community) code Approve
Review via email: mp+74800@code.launchpad.net

Commit message

[r=bac][bug=835024] New error_description property on InitializeDistroSeriesJob.

Description of the change

This adds an error_description property to
InitializeDistroSeriesJob. This property backs onto the job's metadata
so is meant to be persistent. It is populated by the overridden
notifyUserError() method so that the error can be saved even after the
job's transaction is aborted; see BaseJobRunner.runJobHandleError()
for the mechanism.

I've also switched to using the new JSON property from Storm instead
of the _json_data/metadata hackette. This uncovered a bad test -
test__repr__ for InitializeDistroSeriesJob - which I have also fixed.

Pre-implementation discussion with bigjools. There is a follow-up
branch already in progress to make error_description appear in the UI.

To post a comment you must log in.
Revision history for this message
Brad Crittenden (bac) wrote :

Looks good Gavin.

s/slso/also

review: Approve (code)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'database/schema/security.cfg'
2--- database/schema/security.cfg 2011-09-06 19:40:50 +0000
3+++ database/schema/security.cfg 2011-09-09 19:29:35 +0000
4@@ -975,7 +975,7 @@
5 public.component = SELECT
6 public.componentselection = SELECT, INSERT
7 public.distribution = SELECT
8-public.distributionjob = SELECT, INSERT
9+public.distributionjob = SELECT, INSERT, UPDATE
10 public.distributionsourcepackage = SELECT, INSERT
11 public.distroarchseries = SELECT, INSERT
12 public.distroseries = SELECT, UPDATE
13
14=== modified file 'lib/lp/soyuz/model/initializedistroseriesjob.py'
15--- lib/lp/soyuz/model/initializedistroseriesjob.py 2011-08-04 10:37:58 +0000
16+++ lib/lp/soyuz/model/initializedistroseriesjob.py 2011-09-09 19:29:35 +0000
17@@ -7,6 +7,7 @@
18 "InitializeDistroSeriesJob",
19 ]
20
21+import simplejson
22 from zope.interface import (
23 classProvides,
24 implements,
25@@ -31,7 +32,10 @@
26 DistributionJobDerived,
27 )
28 from lp.soyuz.model.packageset import Packageset
29-from lp.soyuz.scripts.initialize_distroseries import InitializeDistroSeries
30+from lp.soyuz.scripts.initialize_distroseries import (
31+ InitializationError,
32+ InitializeDistroSeries,
33+ )
34
35
36 class InitializeDistroSeriesJob(DistributionJobDerived):
37@@ -41,6 +45,8 @@
38 class_job_type = DistributionJobType.INITIALIZE_SERIES
39 classProvides(IInitializeDistroSeriesJobSource)
40
41+ user_error_types = (InitializationError,)
42+
43 @classmethod
44 def create(cls, child, parents, arches=(), packagesets=(),
45 rebuild=False, overlays=(), overlay_pockets=(),
46@@ -179,6 +185,10 @@
47 def rebuild(self):
48 return self.metadata['rebuild']
49
50+ @property
51+ def error_description(self):
52+ return self.metadata.get("error_description")
53+
54 def run(self):
55 """See `IRunnableJob`."""
56 ids = InitializeDistroSeries(
57@@ -188,6 +198,17 @@
58 ids.check()
59 ids.initialize()
60
61+ def notifyUserError(self, error):
62+ """Calls up and slso saves the error text in this job's metadata.
63+
64+ See `BaseRunnableJob`.
65+ """
66+ # This method is called when error is an instance of
67+ # self.user_error_types.
68+ super(InitializeDistroSeriesJob, self).notifyUserError(error)
69+ metadata = dict(self.metadata, error_description=unicode(error))
70+ self.context._json_data = simplejson.dumps(metadata).decode("utf-8")
71+
72 def getOopsVars(self):
73 """See `IRunnableJob`."""
74 vars = super(InitializeDistroSeriesJob, self).getOopsVars()
75
76=== modified file 'lib/lp/soyuz/tests/test_initializedistroseriesjob.py'
77--- lib/lp/soyuz/tests/test_initializedistroseriesjob.py 2011-08-02 16:24:30 +0000
78+++ lib/lp/soyuz/tests/test_initializedistroseriesjob.py 2011-09-09 19:29:35 +0000
79@@ -70,8 +70,8 @@
80 packageset2 = self.factory.makePackageset()
81
82 overlays = (True, False)
83- overlay_pockets = (('Updates',), ('Release',))
84- overlay_components = (("main",), ("universe",))
85+ overlay_pockets = (u'Updates', u'Release')
86+ overlay_components = (u"main", u"universe")
87 arches = (u'i386', u'amd64')
88 packagesets = (packageset1.id, packageset2.id)
89 rebuild = False
90@@ -84,8 +84,8 @@
91 "distribution: {distroseries.distribution.name}, "
92 "distroseries: {distroseries.name}, "
93 "parent[overlay?/pockets/components]: "
94- "{parent1.name}[True/[u'Updates']/[u'main']],"
95- "{parent2.name}[False/[u'Release']/[u'universe']], "
96+ "{parent1.name}[True/Updates/main],"
97+ "{parent2.name}[False/Release/universe], "
98 "architectures: (u'i386', u'amd64'), "
99 "packagesets: [u'{packageset1.name}', u'{packageset2.name}'], "
100 "rebuild: False>".format(
101@@ -99,7 +99,6 @@
102 repr(job)
103 )
104
105-
106 def test_create_with_existing_pending_job(self):
107 parent = self.factory.makeDistroSeries()
108 distroseries = self.factory.makeDistroSeries()
109@@ -197,6 +196,23 @@
110 self.assertIsInstance(job, InitializeDistroSeriesJob)
111 self.assertEqual(job.distroseries, distroseries)
112
113+ def test_error_description_when_no_error(self):
114+ # The InitializeDistroSeriesJob.error_description property returns
115+ # None when no error description is recorded.
116+ parent = self.factory.makeDistroSeries()
117+ distroseries = self.factory.makeDistroSeries()
118+ job = self.job_source.create(distroseries, [parent.id])
119+ self.assertIs(None, removeSecurityProxy(job).error_description)
120+
121+ def test_error_description_set_when_notifying_about_user_errors(self):
122+ # error_description is set by notifyUserError().
123+ parent = self.factory.makeDistroSeries()
124+ distroseries = self.factory.makeDistroSeries()
125+ job = self.job_source.create(distroseries, [parent.id])
126+ message = "This is an example message."
127+ job.notifyUserError(InitializationError(message))
128+ self.assertEqual(message, removeSecurityProxy(job).error_description)
129+
130
131 class InitializeDistroSeriesJobTestsWithPackages(TestCaseWithFactory):
132 """Test case for InitializeDistroSeriesJob."""