Merge lp:~agateau/checkbox/keep-tests-ordered2 into lp:checkbox

Proposed by Aurélien Gâteau
Status: Rejected
Rejected by: Daniel Manrique
Proposed branch: lp:~agateau/checkbox/keep-tests-ordered2
Merge into: lp:checkbox
Diff against target: 154 lines (+40/-10) (has conflicts)
5 files modified
checkbox/lib/template.py (+2/-2)
checkbox/lib/template_i18n.py (+6/-1)
checkbox_gtk/gtk_interface.py (+3/-3)
plugins/jobs_info.py (+3/-1)
plugins/suites_prompt.py (+26/-3)
Text conflict in plugins/suites_prompt.py
To merge this branch: bzr merge lp:~agateau/checkbox/keep-tests-ordered2
Reviewer Review Type Date Requested Status
Daniel Manrique (community) Disapprove
Greg Vallande (community) Needs Information
Review via email: mp+100378@code.launchpad.net

Description of the change

This is a second try at getting the keep-tests-ordered feature in. The first attempt got merged-in and rejected later, but I am not sure exactly why. If the changes there introduce some bugs I would be happy to fix them.

To post a comment you must log in.
Revision history for this message
Daniel Manrique (roadmr) wrote :

Hi Aurélien:

Adding the "sortkey" element to a job caused unforeseen and serious consequences, such as being unable to submit results to certification.canonical.com; this is because the job schema has changed and the "receiving end" would need to be updated as well to cope with this.

However, since the "sortkey" is used only for visual sorting, we felt it incorrect to add support on the website, only to strip the key away upon receipt.

My apologies for not giving you a heads-up that the feature had been reverted (checkbox rev 1319); this had to be done in a bit of a hurry because it was blocking all submissions to certification, both by the certification team and OEM/QA. My aim was to reimplement that feature using a different technique but, while I have the basics of a new implementation that doesn't touch the jobs themselves, I haven't had the time to finish it.

I'll mark this as "Needs Fixing" as I notice you're still adding a sortkey to jobs. Let's coordinate so I can show you the progress I have and we can get this feature back in checkbox ASAP (which was my plan from the beginning, apologies again for not having had the time to finish this).

review: Needs Fixing
Revision history for this message
Greg Vallande (gvallande) wrote :

@roadmr: Has there been any movement on this one? Don't forget about this one, please.

review: Needs Information
Revision history for this message
Daniel Manrique (roadmr) wrote :

Hi,

I'm still working on an alternate implementation without using sortkey in the jobs. I'm trying to accomodate the two use cases we have, which are Aurélien's (without using a whitelist) and Certification's (with a whitelist).

Revision history for this message
Daniel Manrique (roadmr) wrote :

Hello,

This has been on hold for a while. Ordering in checkbox is a more complex affair than originally thought; everybody wants a different way of sorting, both visually and at run time, and we don't have a clear way of handling all use cases yet.

In any case, the way it's done in this code is, again, by adding the sortkey attribute to jobs which, as explained above, causes other problems. Based on this and the fact that ordering is still somewhat undefined, I'll have to reject this merge request, as it would be impossible to merge it as is. Thanks for your code and we'll keep trying to get ordering working right.

review: Disapprove

Unmerged revisions

1328. By Aurélien Gâteau

Make the gtk treeview lists tests in the order they are defined in job files

1327. By Aurélien Gâteau

Add a "sortkey" attribute to jobs

Will be used by the UI to present jobs in the order they appear in the job
definition file.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'checkbox/lib/template.py'
--- checkbox/lib/template.py 2012-03-15 14:46:06 +0000
+++ checkbox/lib/template.py 2012-04-02 10:14:18 +0000
@@ -70,11 +70,11 @@
7070
71 def load_file(self, file, filename="<stream>"):71 def load_file(self, file, filename="<stream>"):
72 elements = []72 elements = []
73 for string in self._reader(file):73 for index, string in enumerate(self._reader(file)):
74 if not string:74 if not string:
75 break75 break
7676
77 element = {}77 element = {"sortkey": index}
7878
79 def _save(field, value, extended):79 def _save(field, value, extended):
80 extended = extended.rstrip("\n")80 extended = extended.rstrip("\n")
8181
=== modified file 'checkbox/lib/template_i18n.py'
--- checkbox/lib/template_i18n.py 2012-03-14 21:11:06 +0000
+++ checkbox/lib/template_i18n.py 2012-04-02 10:14:18 +0000
@@ -18,6 +18,7 @@
18#18#
19import re19import re
20import locale20import locale
21import types
2122
22from os import environ23from os import environ
23from gettext import gettext as _24from gettext import gettext as _
@@ -116,7 +117,11 @@
116 continue117 continue
117118
118 if key in element:119 if key in element:
119 filter[key] = self._filter_field(element[key])120 value = element[key]
121 if type(value) in types.StringTypes:
122 filter[key] = self._filter_field(value)
123 else:
124 filter[key] = value
120 continue125 continue
121 else:126 else:
122 field = "_%s" % key127 field = "_%s" % key
123128
=== modified file 'checkbox_gtk/gtk_interface.py'
--- checkbox_gtk/gtk_interface.py 2012-03-14 21:11:06 +0000
+++ checkbox_gtk/gtk_interface.py 2012-04-02 10:14:18 +0000
@@ -409,9 +409,9 @@
409409
410 def set_options(options, default, parent=None):410 def set_options(options, default, parent=None):
411 if isinstance(options, dict):411 if isinstance(options, dict):
412 keys = sorted(options.keys())412 items = options.items()
413 values = [options[k] for k in keys]413 items.sort(key=lambda x: x[0].sortkey)
414 for text, child in zip(keys, values):414 for text, child in items:
415 active = text in default415 active = text in default
416 iter = treestore.append(parent, [text, active])416 iter = treestore.append(parent, [text, active])
417 set_options(child, default.get(text, {}), iter)417 set_options(child, default.get(text, {}), iter)
418418
=== modified file 'plugins/jobs_info.py'
--- plugins/jobs_info.py 2012-03-21 12:33:48 +0000
+++ plugins/jobs_info.py 2012-04-02 10:14:18 +0000
@@ -46,7 +46,9 @@
46 "resources": List(String(), required=False),46 "resources": List(String(), required=False),
47 "timeout": Int(required=False),47 "timeout": Int(required=False),
48 "user": String(required=False),48 "user": String(required=False),
49 "data": String(required=False)})49 "data": String(required=False),
50 "sortkey": Int(required=False, value=0),
51 })
5052
5153
52class JobsInfo(Plugin):54class JobsInfo(Plugin):
5355
=== modified file 'plugins/suites_prompt.py'
--- plugins/suites_prompt.py 2012-03-20 22:31:41 +0000
+++ plugins/suites_prompt.py 2012-04-02 10:14:18 +0000
@@ -29,6 +29,20 @@
2929
30from gettext import gettext as _30from gettext import gettext as _
3131
32class OptionString(str):
33 """
34 This class is used as a key in the dict passed to the interface to define
35 options. It works like a string for all interfaces, but provide a "sortkey"
36 attribute so that interface can opt-in to list tests according to the order
37 defined by this key.
38 "sortkey" is initialized from the "sortkey" job attribute.
39 """
40 def __init__(self, *args, **kwargs):
41 super(OptionString, self).__init__(*args, **kwargs)
42 self.sortkey = 0
43
44 def __repr__(self):
45 return "<text: %s, sortkey: %d>" % (self, self.sortkey)
3246
33class SuitesPrompt(Plugin):47class SuitesPrompt(Plugin):
3448
@@ -42,8 +56,9 @@
42 def register(self, manager):56 def register(self, manager):
43 super(SuitesPrompt, self).register(manager)57 super(SuitesPrompt, self).register(manager)
4458
59 self._jobs = {}
45 self._depends = {}60 self._depends = {}
46 self._jobs = {}61 self._visible_names = {}
47 self._statuses = {}62 self._statuses = {}
48 self._persist = None63 self._persist = None
49 self._recover = False 64 self._recover = False
@@ -77,13 +92,14 @@
77 self.store = store92 self.store = store
7893
79 def report_job(self, job):94 def report_job(self, job):
95 self._jobs[job["name"]] = job
80 if job.get("type") == "suite":96 if job.get("type") == "suite":
81 attribute = "description"97 attribute = "description"
82 else:98 else:
83 attribute = "name"99 attribute = "name"
84100
85 if attribute in job:101 if attribute in job:
86 self._jobs[job["name"]] = job[attribute]102 self._visible_names[job["name"]] = job[attribute]
87 if "suite" in job:103 if "suite" in job:
88 self._depends[job["name"]] = [job["suite"]]104 self._depends[job["name"]] = [job["suite"]]
89 if job.get("type") == "test":105 if job.get("type") == "test":
@@ -92,7 +108,7 @@
92 def prompt_gather(self, interface):108 def prompt_gather(self, interface):
93 # Resolve dependencies109 # Resolve dependencies
94 resolver = Resolver()110 resolver = Resolver()
95 for key in self._jobs.iterkeys():111 for key in self._visible_names.iterkeys():
96 depends = self._depends.get(key, [])112 depends = self._depends.get(key, [])
97 resolver.add(key, *depends)113 resolver.add(key, *depends)
98114
@@ -109,11 +125,18 @@
109 suboptions = options125 suboptions = options
110 dependencies = resolver.get_dependencies(job)126 dependencies = resolver.get_dependencies(job)
111 for dependency in dependencies:127 for dependency in dependencies:
128<<<<<<< TREE
112 if dependency in tests:129 if dependency in tests:
113 value = tests[dependency]["status"]130 value = tests[dependency]["status"]
114 else:131 else:
115 value = self._statuses.get(dependency, {})132 value = self._statuses.get(dependency, {})
116 suboptions = suboptions.setdefault(self._jobs[dependency], value)133 suboptions = suboptions.setdefault(self._jobs[dependency], value)
134=======
135 value = self._statuses.get(dependency, {})
136 option = OptionString(self._visible_names[dependency])
137 option.sortkey = self._jobs[dependency]["sortkey"]
138 suboptions = suboptions.setdefault(option, value)
139>>>>>>> MERGE-SOURCE
117140
118 # Build defaults141 # Build defaults
119 defaults = self.persist.get("default")142 defaults = self.persist.get("default")

Subscribers

People subscribed via source and target branches