""" A collection of helper utility functions for working with instructor tasks. """ import json import logging from django.utils.translation import ugettext as _ from django.utils.translation import ungettext from bulk_email.models import CourseEmail from lms.djangoapps.instructor_task.views import get_task_completion_info from util.date_utils import get_default_time_display log = logging.getLogger(__name__) def email_error_information(): """ Returns email information marked as None, used in event email cannot be loaded """ expected_info = [ 'created', 'sent_to', 'email', 'number_sent', 'requester', ] return {info: None for info in expected_info} def extract_email_features(email_task): """ From the given task, extract email content information Expects that the given task has the following attributes: * task_input (dict containing email_id) * task_output (optional, dict containing total emails sent) * requester, the user who executed the task With this information, gets the corresponding email object from the bulk emails table, and loads up a dict containing the following: * created, the time the email was sent displayed in default time display * sent_to, the group the email was delivered to * email, dict containing the subject, id, and html_message of an email * number_sent, int number of emails sent * requester, the user who sent the emails If task_input cannot be loaded, then the email cannot be loaded and None is returned for these fields. """ # Load the task input info to get email id try: task_input_information = json.loads(email_task.task_input) except ValueError: log.error("Could not parse task input as valid json; task input: %s", email_task.task_input) return email_error_information() email = CourseEmail.objects.get(id=task_input_information['email_id']) email_feature_dict = { 'created': get_default_time_display(email.created), 'sent_to': [target.long_display() for target in email.targets.all()], 'requester': str(email_task.requester), } features = ['subject', 'html_message', 'id'] email_info = {feature: unicode(getattr(email, feature)) for feature in features} # Pass along email as an object with the information we desire email_feature_dict['email'] = email_info # Translators: number sent refers to the number of emails sent number_sent = _('0 sent') if hasattr(email_task, 'task_output') and email_task.task_output is not None: try: task_output = json.loads(email_task.task_output) except ValueError: log.error("Could not parse task output as valid json; task output: %s", email_task.task_output) else: if 'succeeded' in task_output and task_output['succeeded'] > 0: num_emails = task_output['succeeded'] number_sent = ungettext( "{num_emails} sent", "{num_emails} sent", num_emails ).format(num_emails=num_emails) if 'failed' in task_output and task_output['failed'] > 0: num_emails = task_output['failed'] number_sent += ", " number_sent += ungettext( "{num_emails} failed", "{num_emails} failed", num_emails ).format(num_emails=num_emails) email_feature_dict['number_sent'] = number_sent return email_feature_dict def extract_task_features(task): """ Convert task to dict for json rendering. Expects tasks have the following features: * task_type (str, type of task) * task_input (dict, input(s) to the task) * task_id (str, celery id of the task) * requester (str, username who submitted the task) * task_state (str, state of task eg PROGRESS, COMPLETED) * created (datetime, when the task was completed) * task_output (optional) """ # Pull out information from the task features = ['task_type', 'task_input', 'task_id', 'requester', 'task_state'] task_feature_dict = {feature: str(getattr(task, feature)) for feature in features} # Some information (created, duration, status, task message) require additional formatting task_feature_dict['created'] = task.created.isoformat() # Get duration info, if known duration_sec = 'unknown' if hasattr(task, 'task_output') and task.task_output is not None: try: task_output = json.loads(task.task_output) except ValueError: log.error("Could not parse task output as valid json; task output: %s", task.task_output) else: if 'duration_ms' in task_output: duration_sec = int(task_output['duration_ms'] / 1000.0) task_feature_dict['duration_sec'] = duration_sec # Get progress status message & success information success, task_message = get_task_completion_info(task) status = _("Complete") if success else _("Incomplete") task_feature_dict['status'] = status task_feature_dict['task_message'] = task_message return task_feature_dict