def view_assignment(assignment_id): simple_archive_form = SimpleArchiveForm() # Convert the assignment in the URL into an ObjectId try: id = ObjectId(assignment_id) except InvalidId: logger.info("Invalid Assignment ID requested.") abort(404) # Retrieve the assignment try: assignment = Assignment.objects.get(id=id) except Assignment.DoesNotExist: logger.info("Non-extant ID requested.") abort(404) assignment.apply_personal_deadlines(current_user) # Get all of the submissions for this assignment submissions = list(Submission.objects(user=current_user.id, assignment=id).order_by("-most_recent", "-timestamp")) # Get student submissions if being viewed as teacher student_submissions = [] students = [] if current_user.account_type in ["teacher", "teaching_assistant"]: students = list(User.objects(classes=assignment.for_class, account_type="student").order_by("-email")) student_submissions = list( Submission.objects(user__in=[i.email for i in students], assignment=assignment_id, most_recent=True) ) test_results = list(TestResult.objects(id__in=[i.test_results for i in submissions if i.test_results])) # Match test results to submissions for i in submissions: for j in test_results: if i.test_results == j.id: i.test_results_obj = j # Current time to be compared to submission test_request_timestamp now = datetime.datetime.now() # Flag to set refresh trigger if user is waiting on test results wait_and_refresh = False # Add the pretty version of each submissions timestamp for i in submissions: i.timestamp_pretty = pretty_time(i.timestamp) i.status = "Submitted" # If the user submitted a test request and there aren't any results if i.test_request_timestamp and not i.test_results: timedelta = now - i.test_request_timestamp i.show_resubmit = timedelta > config["STUDENT_RETRY_INTERVAL"] if not i.show_resubmit: i.status = "Waiting for test results..." else: i.status = "Test request timed out" elif i.test_results and i.test_results_obj.failed: i.status = "Tests Failed" i.show_resubmit = True elif i.test_results and not i.test_results_obj.failed: i.status = "Tests Completed" wait_and_refresh = any(i.status == "Waiting for test results..." for i in submissions) return render_template( "assignment.html", now=datetime.datetime.today(), create_time_element=create_time_element, assignment=assignment, submissions=submissions, simple_archive_form=simple_archive_form, wait_and_refresh=wait_and_refresh, new_submissions=[v for k, v in get_flashed_messages(with_categories=True) if k == "new_submission"], view_as_teacher=(current_user.account_type in ["teacher", "teaching_assistant"]), students=students, student_submissions=student_submissions, enumerate=enumerate, )
def view_assignment(assignment_id): simple_archive_form = SimpleArchiveForm() # Convert the assignment in the URL into an ObjectId try: id = ObjectId(assignment_id) except InvalidId: logger.info("Invalid Assignment ID requested.") abort(404) # Retrieve the assignment try: assignment = Assignment.objects.get(id=id) except Assignment.DoesNotExist: logger.info("Non-extant ID requested.") abort(404) assignment.apply_personal_deadlines(current_user) # Get all of the submissions for this assignment submissions = list( Submission.objects(user=current_user.id, assignment=id).order_by("-most_recent", "-timestamp")) # Get student submissions if being viewed as teacher student_submissions = [] students = [] if current_user.account_type in ["teacher", "teaching_assistant"]: students = list( User.objects(classes=assignment.for_class, account_type="student").order_by("-email")) student_submissions = list( Submission.objects(user__in=[i.email for i in students], assignment=assignment_id, most_recent=True)) test_results = list( TestResult.objects( id__in=[i.test_results for i in submissions if i.test_results])) # Match test results to submissions for i in submissions: for j in test_results: if i.test_results == j.id: i.test_results_obj = j # Current time to be compared to submission test_request_timestamp now = datetime.datetime.now() # Flag to set refresh trigger if user is waiting on test results wait_and_refresh = False # Add the pretty version of each submissions timestamp for i in submissions: i.timestamp_pretty = pretty_time(i.timestamp) i.status = "Submitted" # If the user submitted a test request and there aren't any results if (i.test_request_timestamp and not i.test_results): timedelta = now - i.test_request_timestamp i.show_resubmit = (timedelta > config["STUDENT_RETRY_INTERVAL"]) if not i.show_resubmit: i.status = "Waiting for test results..." else: i.status = "Test request timed out" elif (i.test_results and i.test_results_obj.failed): i.status = "Tests Failed" i.show_resubmit = True elif (i.test_results and not i.test_results_obj.failed): i.status = "Tests Completed" wait_and_refresh = \ any(i.status == "Waiting for test results..." for i in submissions) return render_template( "assignment.html", now=datetime.datetime.today(), create_time_element=create_time_element, assignment=assignment, submissions=submissions, simple_archive_form=simple_archive_form, wait_and_refresh=wait_and_refresh, new_submissions=[ v for k, v in get_flashed_messages(with_categories=True) if k == "new_submission" ], view_as_teacher=(current_user.account_type in ["teacher", "teaching_assistant"]), students=students, student_submissions=student_submissions, enumerate=enumerate)
def main(): flock = FlockManager( match_found, config["BLEET_TIMEOUT"], config["SERVICE_TIMEOUT"] ) logger.info("Shepherd starting.") while True: # Wait until either the public or sheep socket has messages waiting zmq.select([public, sheep], [], [], timeout = 5) # Will grab all of the outstanding messages from the outside and place them # in the request queue while public.getsockopt(zmq.EVENTS) & zmq.POLLIN != 0: request = public.recv_json() logger.debug("Raw test request: %s", str(request)) request = TestRequest.from_dict(request) try: submission = \ Submission.objects.get(id = ObjectId(request.submission_id)) except Submission.DoesNotExist as e: logger.warning( "Received test request for non-existant submission [%s].", str(request.submission_id) ) continue except bson.errors.InvalidId as e: logger.warning("Received malformed test request. %s", str(e)) continue try: assignment = Assignment.objects.get(id = submission.assignment) except Assignment.DoesNotExist as e: logger.error( "Received test request for a submission [%s] referencing " "an invalid assignment [%s].", str(submission.id), str(submission.assignment) ) continue if not assignment.test_harness: logger.warning( "Received test request for a submission [%s] referencing " "an assignment [%s] that does not have a test harness " "associated with it.", str(submission.id), str(submission.assignment) ) continue try: test_harness = \ TestHarness.objects.get(id = assignment.test_harness) except TestHarness.DoesNotExit as e: logger.error( "Received test request for a submission [%s] referencing " "an assignment [%s] that references a non-existant test " "harness [%s].", str(submission.id), str(submission.assignment), str(assignment.test_harness) ) continue # Gather all the necessary information from the test request # received from the outside. processed_request = InternalTestRequest( submission.id, test_harness.config.get("galah/timeout", config["BLEET_TIMEOUT"].seconds), test_harness.config.get("galah/environment", {}) ) logger.info("Received test request.") flock.received_request(processed_request) # Will grab all of the outstanding messages from the sheep and process them while sheep.getsockopt(zmq.EVENTS) & zmq.POLLIN != 0: try: sheep_identity, sheep_message = router_recv_json(sheep) sheep_message = FlockMessage.from_dict(sheep_message) logger.debug( "Received message from sheep: %s", str(sheep_message) ) except ValueError as e: logger.error("Could not decode sheep's message: %s", str(e)) logger.debug( "Exception thrown while decoding sheep's message...", exc_info = sys.exc_info() ) continue if sheep_message.type == "distress": logger.warn("Received distress message. Sending bloot.") router_send_json( sheep, sheep_identity, FlockMessage("bloot", "").to_dict() ) elif sheep_message.type == "bleet": logger.debug( "Sheep [%s] bleeted. Sending bloot.", repr(sheep_identity) ) result = flock.sheep_bleeted(sheep_identity) # Under certain circumstances we want to completely ignore a # bleet (see FlockManager.sheep_bleeted() for more details) if result is FlockManager.IGNORE: logger.debug("Ignoring bleet.") continue if not result: router_send_json( sheep, sheep_identity, FlockMessage("identify", "").to_dict() ) logger.info( "Unrecognized sheep [%s] connected, identify sent.", repr(sheep_identity) ) continue router_send_json( sheep, sheep_identity, FlockMessage("bloot", "").to_dict() ) elif sheep_message.type == "environment": if not flock.manage_sheep(sheep_identity, sheep_message.body): logger.warn( "Received environment from an already-recognized sheep." ) elif sheep_message.type == "result": logger.info("Received test result from sheep.") logger.debug( "Received test result from sheep: %s", str(sheep_message.body) ) try: submission_id = ObjectId(sheep_message.body["id"]) submission = Submission.objects.get(id = submission_id) test_result = TestResult.from_dict(sheep_message.body) try: test_result.save() except InvalidDocument: logger.warn( "Test result is too large for the database.", exc_info = True ) test_result = TestResult(failed = True) test_result.save() submission.test_results = test_result.id submission.save() except (InvalidId, Submission.DoesNotExist) as e: logger.warn( "Could not retrieve submission [%s] for test result " "received from sheep [%s].", str(submission_id), repr(sheep_identity) ) continue router_send_json( sheep, sheep_identity, FlockMessage( "bloot", sheep_message.body["id"] ).to_dict() ) if not flock.sheep_finished(sheep_identity): logger.info( "Got result from sheep [%s] who was not processing " "a test request.", repr(sheep_identity) ) # Let the flock manager get rid of any dead or killed sheep. lost_sheep, killed_sheep = flock.cleanup() if lost_sheep: logger.warn( "%d sheep lost due to bleet timeout: %s", len(lost_sheep), str([repr(i) for i in lost_sheep]) ) if killed_sheep: logger.warn( "%d sheep lost due to request timeout: %s", len(killed_sheep), str([repr(i) for i in killed_sheep]) )