def recent_responses(guts, username): """Show a list of recent responses""" skip = int(guts.parameters.get("skip", 0)) user = get_object_or_404(User, username=username) if guts.user.is_superuser or guts.user == user: recent_responses = Response.objects.filter( user=User.objects.get(username=username), task__result__id__isnull=False).order_by("-task__result__end_time")[skip:skip+50] responses = [] for response in recent_responses: res = {'response': response} res['project_type'] = response.task.project.type ptype = get_project_type(response.task.project) res['task_summary'] = ptype.cast(response.task).summary() res['response_summary'] = ptype.cast(response).summary() res['result_summary'] = ptype.cast(response.task.result).summary() if res["response_summary"] is not None and res["result_summary"] is not None: res['match'] = (res['response_summary'] == res['result_summary']) responses.append(res) template = get_template("recent_responses.html") skips = {} skips['current'] = "%s - %s" % (skip+1, skip+len(responses)) if skip >= 50: skips['forward'] = (skip - 50) or "0" if len (responses) == 50: skips['backward'] = skip + 50 return TemplateResponse(template, {'responses': responses, 'skips': skips, 'username': user.username} ) else: return ForbiddenResponse("Only the user %s, or an administrator, may see this page." % username)
def task_adhoc_review(get, guts): if get: response_id = guts.parameters['response'] response = Response.objects.get(pk=response_id) reviews = Review.objects.filter(response=response) if reviews.count() == 1: review = reviews[0] else: review = Review(response=response, comment="") task = response.task result = task.result # Tagger or merger can both view, as well as super-user if ((response.user != guts.user) and not (guts.user.is_superuser) and (result.user != guts.user)): return ForbiddenResponse( "You are not authorized to see this review.") project_type = get_project_type(task.project) task = project_type.cast(task) try: template = get_template(review.review_template) except NotImplementedError: template = task.template() template_data = task.template_data(review=review) return TemplateResponse(template, template_data) else: return ViewResponse('main:next-review')
def task_review(get, guts, review_id): """Present an interface to request the user to review a given task.""" review = get_object_or_404(Review, pk=review_id) response = review.response ## NOTE: an earlier version of this code would throw a Review.DoesNotExist exception ## if the Review object with the right id and user had complete=True. I don't see ## the harm in re-reviewing so I am not checking for that here. if (response.user != guts.user) and not (guts.user.is_superuser or get): return ForbiddenResponse("You are not authorized to see this review.") if get: task = response.task project_type = get_project_type(task.project) task = project_type.cast(task) try: template = get_template(review.review_template) except NotImplementedError: template = task.template() template_data = task.template_data(review=review) return TemplateResponse(template, template_data) else: review.complete = True review.full_clean() review.save() return ViewResponse('main:next-review')
def task_review(get, guts, review_id): """Present an interface to request the user to review a given task.""" review = get_object_or_404(Review, pk=review_id) response = review.response ## NOTE: an earlier version of this code would throw a Review.DoesNotExist exception ## if the Review object with the right id and user had complete=True. I don't see ## the harm in re-reviewing so I am not checking for that here. if (response.user != guts.user) and not (guts.user.is_superuser or get): return ForbiddenResponse("You are not authorized to see this review.") if get: task = response.task project_type = get_project_type(task.project) task = project_type.cast(task) try: template = get_template(review.review_template) except NotImplementedError: template = task.template() template_data = task.template_data(review=review) return TemplateResponse(template, template_data) else: review.complete = True review.full_clean() review.save() return ViewResponse(next_review)
def contextlet(result): ptype = get_project_type(result.task.project) return {"result": result, "result_summary": ptype.cast(result).summary(), "project_type": result.task.project.type, "responses": [{"response": response, "response_summary": ptype.cast(response).summary(), "match": ptype.cast(result).summary() == \ ptype.cast(response).summary()} for response in result.task.response_set.all()]}
def project_export(guts, project): """Take in a request and project_id, and export a full set of data using the project's export_task method. # TODO: Testing Should return a zipfile. Inside the zipfile is one or more files for each Task; the filenames should be like task-id-ExportString, where exportString is a string returned from the export_task function. """ ptype = get_project_type(project) project = ptype.cast(project) completed_tasks = Task.objects.filter(completed=True, project=project) data = [] buffer = StringIO() zip = zipfile.ZipFile(buffer, "w", zipfile.ZIP_DEFLATED) def put(pathname, data): if isinstance(data, six.text_type): data = data.encode("utf-8") info = zipfile.ZipInfo(pathname) info.external_attr = settings.CLICKWORK_EXPORT_FILE_PERMISSIONS << 16 zip.writestr(info, data) ## a project type can put an export method on its task and/or its project subclass try: data = project.export() for key, val in data.items(): put("project-%s" % key, val) except NotImplementedError: pass try: for task in completed_tasks: task = ptype.cast(task) task_data = task.export() if type(task_data) == dict: for key, val in task_data.items(): put("task-%s-%s" % (task.id, key), val) else: put("task-%s" % taskid, task_data) except NotImplementedError: pass zip.close() if len(zip.infolist()) == 0: return ErrorResponse( "Empty export", "Project %s could not be exported; the export file is empty." % django.utils.html.escape(repr(project)), ) buffer.seek(0) guts.log_info("Exporting project %s to the client" % project.id) return AttachmentResponse("project-%s.zip" % project.id, "application/zip", buffer.read())
def project_export(guts, project): """Take in a request and project_id, and export a full set of data using the project's export_task method. # TODO: Testing Should return a zipfile. Inside the zipfile is one or more files for each Task; the filenames should be like task-id-ExportString, where exportString is a string returned from the export_task function. """ ptype = get_project_type(project) project = ptype.cast(project) completed_tasks = Task.objects.filter(completed=True, project=project) data = [] buffer = StringIO() zip = zipfile.ZipFile(buffer, "w", zipfile.ZIP_DEFLATED) def put(pathname, data): if isinstance(data, unicode): data = data.encode("utf-8") info = zipfile.ZipInfo(pathname) info.external_attr = settings.CLICKWORK_EXPORT_FILE_PERMISSIONS << 16L zip.writestr(info, data) ## a project type can put an export method on its task and/or its project subclass try: data = project.export() for key, val in data.items(): put("project-%s" % key, val) except NotImplementedError: pass try: for task in completed_tasks: task = ptype.cast(task) task_data = task.export() if type(task_data) == dict: for key, val in task_data.items(): put("task-%s-%s" % (task.id, key), val) else: put("task-%s" % taskid, task_data) except NotImplementedError: pass zip.close() if len(zip.infolist()) == 0: return ErrorResponse("Empty export", "Project %s could not be exported; the export file is empty." % \ django.utils.html.escape(repr(project))) buffer.seek(0) guts.log_info("Exporting project %s to the client" % project.id) return AttachmentResponse("project-%s.zip" % project.id, "application/zip", buffer.read())
def project_agreement(guts, project): ptype = get_project_type(project) if not hasattr(ptype, 'test_agreement'): return DefaultResponse("Project doesn't support testing agreement.") same_counts = {} tasks = project.task_set.filter(completed=True).all() for t in tasks: responses = t.response_set.all() same = ptype.test_agreement(responses) same_counts[same] = same_counts.setdefault(same, 0) + 1 template = get_template('project/agreement.html') print same_counts ## TODO: is this leftover debugging code? return TemplateResponse(template, {'counts': same_counts, 'task_count': tasks.count()})
def contextlet(result): ptype = get_project_type(result.task.project) return { "result": result, "result_summary": ptype.cast(result).summary(), "project_type": result.task.project.type, "responses": [ { "response": response, "response_summary": ptype.cast(response).summary(), "match": ptype.cast(result).summary() == ptype.cast(response).summary(), } for response in result.task.response_set.all() ], }
def unmerge(get, guts, task_id): """Given a task that has already been merged, undo the merge, give the user a WIP for re-merging it, and redirect to the page for handling that WIP. This operation may not be supported for all project types, and may only be executed by a superuser.""" if guts.user.is_superuser: if not get: task = get_object_or_404(Task, pk=task_id) project_type = get_project_type(task.project) task = project_type.cast(task) task.handle_unmerge() wip = WorkInProgress(user=guts.user, task=task) wip.full_clean() wip.save() return ViewResponse('main:view-task', task_id) else: return ForbiddenResponse("Only superusers may perform this operation.")
def unmerge(get, guts, task_id): """Given a task that has already been merged, undo the merge, give the user a WIP for re-merging it, and redirect to the page for handling that WIP. This operation may not be supported for all project types, and may only be executed by a superuser.""" if guts.user.is_superuser: if not get: task = get_object_or_404(Task, pk=task_id) project_type = get_project_type(task.project) task = project_type.cast(task) task.handle_unmerge() wip = WorkInProgress(user=guts.user, task=task) wip.full_clean() wip.save() return ViewResponse(task_view, task_id) else: return ForbiddenResponse("Only superusers may perform this operation.")
def project_agreement(guts, project): ptype = get_project_type(project) if not hasattr(ptype, 'test_agreement'): return DefaultResponse("Project doesn't support testing agreement.") same_counts = {} tasks = project.task_set.filter(completed=True).all() for t in tasks: responses = t.response_set.all() same = ptype.test_agreement(responses) same_counts[same] = same_counts.setdefault(same, 0) + 1 template = get_template('project/agreement.html') print(same_counts) ## TODO: is this leftover debugging code? return TemplateResponse(template, { 'counts': same_counts, 'task_count': tasks.count() })
def project_upload(get, guts, project): """Take an upload, and queue it for running through the task processor. # TODO: Testing # TODO: Return something better than the current Upload complete response. (template) # TODO: fix allowing user to select project form a dropdown (project is in the URL). # TODO: only allow certain users to upload projects """ ptype = get_project_type(project) project = ptype.cast(project) if get: template = get_template("project/upload_form.html") return TemplateResponse(template, {"form": UploadForm()}) else: action = guts.parameters["action"] if action == "Upload": pu = ProjectUpload(project=project) item = UploadForm(guts.parameters, guts.files, instance=pu) if item.is_valid(): item.save() if not hasattr(settings, "PROCESS_INLINE") or settings.PROCESS_INLINE: project.handle_input(pu) if project.auto_review: project.add_auto_reviews() pu.complete = True pu.save() message = ( "Upload complete to project %s, tasks processed" % project.id) else: message = "Upload complete, queued as %s" % pu.id guts.log_info(message) return DefaultResponse(message) else: ## re-present the page with input errors marked template = get_template("project/upload_form.html") return TemplateResponse(template, {"form": item}) elif action == "Empty": ## NOTE: if subclasses have customized the delete() method, ## this bulk-delete will not call it. Task.objects.filter(project=project).delete() return ViewResponse('main:view-project', project.id) else: return ErrorResponse("Bad form", "Action parameter %s not understood" % action)
def project_upload(get, guts, project): """Take an upload, and queue it for running through the task processor. # TODO: Testing # TODO: Return something better than the current Upload complete response. (template) # TODO: fix allowing user to select project form a dropdown (project is in the URL). # TODO: only allow certain users to upload projects """ ptype = get_project_type(project) project = ptype.cast(project) if get: template = get_template("project/upload_form.html") return TemplateResponse(template, {"form": UploadForm()}) else: action = guts.parameters["action"] if action == "Upload": pu = ProjectUpload(project=project) item = UploadForm(guts.parameters, guts.files, instance=pu) if item.is_valid(): item.save() if not hasattr(settings, "PROCESS_INLINE") or settings.PROCESS_INLINE: project.handle_input(pu) if project.auto_review: project.add_auto_reviews() pu.complete = True pu.save() message = "Upload complete to project %s, tasks processed" % project.id else: message = "Upload complete, queued as %s" % pu.id guts.log_info(message) return DefaultResponse(message) else: ## re-present the page with input errors marked template = get_template("project/upload_form.html") return TemplateResponse(template, {"form": item}) elif action == "Empty": ## NOTE: if subclasses have customized the delete() method, ## this bulk-delete will not call it. Task.objects.filter(project=project).delete() return ViewResponse(one_project, project.id) else: return ErrorResponse("Bad form", "Action parameter %s not understood" % action)
def recent_responses(guts, username): """Show a list of recent responses""" skip = int(guts.parameters.get("skip", 0)) user = get_object_or_404(User, username=username) if guts.user.is_superuser or guts.user == user: recent_responses = Response.objects.filter( user=user, task__result__id__isnull=False ).order_by("-task__result__end_time")[skip : skip + 50] responses = [] for response in recent_responses: res = {'response': response} res['project_type'] = response.task.project.type ptype = get_project_type(response.task.project) res['task_summary'] = ptype.cast(response.task).summary() res['response_summary'] = ptype.cast(response).summary() res['result_summary'] = ptype.cast(response.task.result).summary() if ( res["response_summary"] is not None and res["result_summary"] is not None ): res['match'] = res['response_summary'] == res['result_summary'] responses.append(res) template = get_template("recent_responses.html") skips = {} skips['current'] = "%s - %s" % (skip + 1, skip + len(responses)) if skip >= 50: skips['forward'] = (skip - 50) or "0" if len(responses) == 50: skips['backward'] = skip + 50 return TemplateResponse( template, {'responses': responses, 'skips': skips, 'username': user.username}, ) else: return ForbiddenResponse( "Only the user %s, or an administrator, may see this page." % username )
def task_adhoc_review(get, guts): if get: response_id = guts.parameters['response'] response = Response.objects.get(pk=response_id) reviews = Review.objects.filter(response=response) if reviews.count() == 1: review = reviews[0] else: review = Review(response=response, comment="") task = response.task result = task.result # Tagger or merger can both view, as well as super-user if (response.user != guts.user) and not (guts.user.is_superuser) and (result.user != guts.user): return ForbiddenResponse("You are not authorized to see this review.") project_type = get_project_type(task.project) task = project_type.cast(task) try: template = get_template(review.review_template) except NotImplementedError: template = task.template() template_data = task.template_data(review=review) return TemplateResponse(template, template_data) else: return ViewResponse(next_review)