import turbogears as tg import fedora from turbogears import controllers, expose, flash from israwhidebroken.model import Test, Tree, TestResult, hub from turbogears import identity, redirect from cherrypy import request, response from tw.forms import Form, SingleSelectField, HiddenField from tw.api import WidgetsList # from israwhidebroken import json # import logging # log = logging.getLogger("israwhidebroken.controllers") # Simple select widget for submitting test results # TODO: ajaxify class ResultForm(Form): show_errors = True class fields(WidgetsList): result = SingleSelectField(options=['none','pass','fail'], suppress_label=True) testid = HiddenField() treeid = HiddenField() fdict = {'none': None, 'pass': 1, 'fail': 0} def to_int(fstr): '''Returns fstr converted to int, or None if fstr is None''' if fstr in fdict: return fdict[fstr] return fstr and int(float(fstr)) archval = {'i386':'0', 'x86_64':'1', 'ppc':'2', 'ppc64':'3'} def archsort(a,b): return cmp(archval.get(a,a), archval.get(b,b)) class Root(controllers.RootController): # Main index page @expose(template="israwhidebroken.templates.index") def index(self, c=None, *args, **kw): if not c: c = Tree.select().max('compose_id') next = None else: c = to_int(c) next = Tree.select(Tree.q.compose_id > c).min('compose_id') prev = Tree.select(Tree.q.compose_id < c).max('compose_id') treesort = lambda a,b: archsort(a.arch, b.arch) trees = sorted(Tree.selectBy(compose_id=c), treesort) tests = Test.select(Test.q.id <= 14) results = {} for tree in trees: rdict = dict([(t.id, None) for t in tests]) for r in tree.results: rdict[r.testID] = r results[tree.id] = rdict result_form = ResultForm('resultform', action=tg.url('/add_result', kw)) return dict(c=c, prev=prev, next=next, result_form=result_form, in_qa='qa' in identity.current.groups, admin='qa-admin' in identity.current.groups, tests=tests, trees=trees, results=results) # JSON RPC calls @expose(allow_json=True) def get_tests(self): tests = Test.select() return dict(tests=list(tests)) @expose(allow_json=True) def get_trees(self, *args, **kw): tree_results = Tree.selectBy(**kw) return dict(trees=list(tree_results)) @expose(allow_json=True) def get_results(self, *args, **kw): results_results = TestResults.selectBy(**kw) return dict(results=list(results_results)) # JSON calls that require authentication @identity.require(identity.in_group("qa")) @expose(allow_json=True) def add_tree(self, arch, compose_id, tree_time=None, repodata_time=None): # check to see if tree already exists tree_result = Tree.selectBy(arch=arch, compose_id=compose_id, tree_time=tree_time, repodata_time=repodata_time) if tree_result.count(): return dict(exc='ValueError', tg_flash='Tree exists') t = Tree(arch=arch, compose_id=to_int(compose_id), tree_time=to_int(tree_time), repodata_time=to_int(repodata_time)) hub.commit() return dict(tree=t) @identity.require(identity.in_group("qa")) @expose(allow_json=True) def update_tree(self, treeid, arch=None, compose_id=None, tree_time=None, repodata_time=None): tr = list(Tree.selectBy(id=treeid)) if len(tr) == 0: return dict(exc='ValueError', tg_flash='Tree %u not found' % treeid) tree = tr[0] if arch: tree.arch = arch if tree_time: tree.tree_time = to_int(tree_time) if repodata_time: tree.repodata_time = to_int(repodata_time) if compose_id: tree.compose_id = to_int(compose_id) hub.commit() return dict(tree=tree) @identity.require(identity.in_group("qa")) @expose(allow_json=True) def add_result(self, treeid, testid, result, overwrite=False, *args, **kw): if not overwrite: # TODO return an exception if there's already a result here pass tr = TestResult(tree=to_int(treeid), test=to_int(testid), result=to_int(result), userid=identity.current.user.id, bug_id=None) hub.commit() # XXX necessary? if 'json' in fedora.tg.util.request_format(): return dict(id=tr.id) redirect(tg.url("/", kw)) @identity.require(identity.in_group("qa")) @expose(allow_json=True) def delete_result(self, id, *args, **kw): tr = TestResult.get(id) tr.destroySelf() if 'json' in fedora.tg.util.request_format(): return dict(deleted=id) redirect(tg.url("/", kw)) # XXX: delete_tree()? (would require qa-admin) # Identity stuff (login/logout) @expose(template="israwhidebroken.templates.login") @expose(allow_json=True) def login(self, forward_url=None, *args, **kw): if forward_url: if isinstance(forward_url, list): forward_url = forward_url.pop(0) else: del request.params['forward_url'] # If the login was successful... if not identity.current.anonymous and identity.was_login_attempted() \ and not identity.get_identity_errors(): if 'json' == fedora.tg.util.request_format(): return dict(user=identity.current.user) flash("Welcome, %s" % identity.current.user_name) redirect(tg.url(forward_url or '/', kw)) if identity.was_login_attempted(): msg = _("The credentials you supplied were not correct or " "did not grant access to this resource.") elif identity.get_identity_errors(): msg = _("You must provide your credentials before accessing " "this resource.") else: msg = _("Please log in.") if not forward_url: forward_url = request.headers.get("Referer", "/") response.status = 401 return dict(logging_in=True, message=msg, forward_url=forward_url, previous_url=request.path_info, original_parameters=request.params) @expose(allow_json=True) def logout(self): identity.current.logout() if 'json' in fedora.tg.util.request_format(): return dict() redirect("/")