Ran pyupgrade on lms/djangoapps
Ran pyupgrade on lms/djangoapps/instructor_analytics Ran pyugprade on lms/djangoapps/instructor_task Ran pyupgrade on lms/djangoapps/learner_dashboard
This commit is contained in:
@@ -7,12 +7,14 @@ from time import time
|
||||
|
||||
from django.contrib.auth import get_user_model
|
||||
from django.db.models import Q
|
||||
from xmodule.modulestore.django import modulestore
|
||||
|
||||
from common.djangoapps.student.models import CourseEnrollment
|
||||
from lms.djangoapps.certificates.api import generate_user_certificates
|
||||
from lms.djangoapps.certificates.models import CertificateStatuses, GeneratedCertificate
|
||||
from xmodule.modulestore.django import modulestore
|
||||
|
||||
from .runner import TaskProgress
|
||||
|
||||
User = get_user_model()
|
||||
|
||||
|
||||
|
||||
@@ -10,15 +10,17 @@ from time import time
|
||||
from django.conf import settings # lint-amnesty, pylint: disable=unused-import
|
||||
from django.utils.translation import ugettext as _ # lint-amnesty, pylint: disable=unused-import
|
||||
from pytz import UTC
|
||||
from six import StringIO # lint-amnesty, pylint: disable=unused-import
|
||||
|
||||
from common.djangoapps.edxmako.shortcuts import render_to_string # lint-amnesty, pylint: disable=unused-import
|
||||
from common.djangoapps.student.models import ( # lint-amnesty, pylint: disable=unused-import
|
||||
CourseAccessRole,
|
||||
CourseEnrollment
|
||||
)
|
||||
from common.djangoapps.util.file import course_filename_prefix_generator # lint-amnesty, pylint: disable=unused-import
|
||||
from lms.djangoapps.courseware.courses import get_course_by_id # lint-amnesty, pylint: disable=unused-import
|
||||
from lms.djangoapps.instructor_analytics.basic import enrolled_students_features, list_may_enroll
|
||||
from lms.djangoapps.instructor_analytics.csvs import format_dictlist
|
||||
from lms.djangoapps.instructor_task.models import ReportStore # lint-amnesty, pylint: disable=unused-import
|
||||
from common.djangoapps.student.models import CourseAccessRole, CourseEnrollment # lint-amnesty, pylint: disable=unused-import
|
||||
from common.djangoapps.util.file import course_filename_prefix_generator # lint-amnesty, pylint: disable=unused-import
|
||||
|
||||
from .runner import TaskProgress
|
||||
from .utils import tracker_emit, upload_csv_to_report_store # lint-amnesty, pylint: disable=unused-import
|
||||
|
||||
@@ -3,37 +3,35 @@ Functionality for generating grade reports.
|
||||
"""
|
||||
|
||||
import logging
|
||||
import re
|
||||
from collections import OrderedDict, defaultdict
|
||||
from datetime import datetime
|
||||
from itertools import chain
|
||||
from time import time
|
||||
|
||||
import re
|
||||
import six
|
||||
from lms.djangoapps.course_blocks.api import get_course_blocks
|
||||
from django.conf import settings # lint-amnesty, pylint: disable=wrong-import-order
|
||||
from django.contrib.auth import get_user_model # lint-amnesty, pylint: disable=wrong-import-order
|
||||
from lazy import lazy # lint-amnesty, pylint: disable=wrong-import-order
|
||||
from opaque_keys.edx.keys import UsageKey # lint-amnesty, pylint: disable=wrong-import-order
|
||||
from pytz import UTC # lint-amnesty, pylint: disable=wrong-import-order
|
||||
from six import text_type # lint-amnesty, pylint: disable=wrong-import-order
|
||||
from six.moves import zip, zip_longest # lint-amnesty, pylint: disable=wrong-import-order
|
||||
from django.conf import settings
|
||||
from django.contrib.auth import get_user_model
|
||||
from lazy import lazy
|
||||
from opaque_keys.edx.keys import UsageKey
|
||||
from pytz import UTC
|
||||
from six.moves import zip_longest
|
||||
|
||||
from common.djangoapps.course_modes.models import CourseMode
|
||||
from common.djangoapps.student.models import CourseEnrollment
|
||||
from common.djangoapps.student.roles import BulkRoleCache
|
||||
from lms.djangoapps.certificates.models import CertificateWhitelist, GeneratedCertificate, certificate_info_for_user
|
||||
from lms.djangoapps.course_blocks.api import get_course_blocks
|
||||
from lms.djangoapps.courseware.courses import get_course_by_id
|
||||
from lms.djangoapps.courseware.user_state_client import DjangoXBlockUserStateClient
|
||||
from lms.djangoapps.grades.api import (
|
||||
CourseGradeFactory,
|
||||
context as grades_context,
|
||||
prefetch_course_and_subsection_grades,
|
||||
)
|
||||
from lms.djangoapps.grades.api import CourseGradeFactory
|
||||
from lms.djangoapps.grades.api import context as grades_context
|
||||
from lms.djangoapps.grades.api import prefetch_course_and_subsection_grades
|
||||
from lms.djangoapps.instructor_analytics.basic import list_problem_responses
|
||||
from lms.djangoapps.instructor_analytics.csvs import format_dictlist
|
||||
from lms.djangoapps.instructor_task.config.waffle import (
|
||||
course_grade_report_verified_only,
|
||||
optimize_get_learners_switch_enabled,
|
||||
problem_grade_report_verified_only,
|
||||
problem_grade_report_verified_only
|
||||
)
|
||||
from lms.djangoapps.teams.models import CourseTeamMembership
|
||||
from lms.djangoapps.verify_student.services import IDVerificationService
|
||||
@@ -41,11 +39,10 @@ from openedx.core.djangoapps.content.block_structure.api import get_course_in_ca
|
||||
from openedx.core.djangoapps.course_groups.cohorts import bulk_cache_cohorts, get_cohort, is_course_cohorted
|
||||
from openedx.core.djangoapps.user_api.course_tag.api import BulkCourseTags
|
||||
from openedx.core.lib.cache_utils import get_cache
|
||||
from common.djangoapps.student.models import CourseEnrollment
|
||||
from common.djangoapps.student.roles import BulkRoleCache
|
||||
from xmodule.modulestore.django import modulestore
|
||||
from xmodule.partitions.partitions_service import PartitionService
|
||||
from xmodule.split_test_module import get_split_user_partitions
|
||||
|
||||
from .runner import TaskProgress
|
||||
from .utils import upload_csv_to_report_store
|
||||
|
||||
@@ -71,7 +68,7 @@ def _flatten(iterable):
|
||||
return list(chain.from_iterable(iterable))
|
||||
|
||||
|
||||
class GradeReportBase(object):
|
||||
class GradeReportBase:
|
||||
"""
|
||||
Base class for grade reports (ProblemGradeReport and CourseGradeReport).
|
||||
"""
|
||||
@@ -91,14 +88,14 @@ class GradeReportBase(object):
|
||||
Updates the status on the celery task to the given message.
|
||||
Also logs the update.
|
||||
"""
|
||||
fmt = u'Task: {task_id}, InstructorTask ID: {entry_id}, Course: {course_id}, Input: {task_input}'
|
||||
fmt = 'Task: {task_id}, InstructorTask ID: {entry_id}, Course: {course_id}, Input: {task_input}'
|
||||
task_info_string = fmt.format(
|
||||
task_id=context.task_id,
|
||||
entry_id=context.entry_id,
|
||||
course_id=context.course_id,
|
||||
task_input=context.task_input
|
||||
)
|
||||
TASK_LOG.info(u'%s, Task type: %s, %s, %s', task_info_string, context.action_name,
|
||||
TASK_LOG.info('%s, Task type: %s, %s, %s', task_info_string, context.action_name,
|
||||
message, context.task_progress.state)
|
||||
|
||||
def _handle_empty_generator(self, generator, default):
|
||||
@@ -119,8 +116,7 @@ class GradeReportBase(object):
|
||||
else:
|
||||
TASK_LOG.info('GradeReport: Generator is not empty')
|
||||
yield first_iteration_output
|
||||
for element in generator:
|
||||
yield element
|
||||
yield from generator
|
||||
|
||||
def _batch_users(self, context):
|
||||
"""
|
||||
@@ -200,7 +196,7 @@ class GradeReportBase(object):
|
||||
context.update_status(message)
|
||||
|
||||
|
||||
class _CourseGradeReportContext(object):
|
||||
class _CourseGradeReportContext:
|
||||
"""
|
||||
Internal class that provides a common context to use for a single grade
|
||||
report. When a report is parallelized across multiple processes,
|
||||
@@ -210,10 +206,10 @@ class _CourseGradeReportContext(object):
|
||||
|
||||
def __init__(self, _xmodule_instance_args, _entry_id, course_id, _task_input, action_name):
|
||||
self.task_info_string = (
|
||||
u'Task: {task_id}, '
|
||||
u'InstructorTask ID: {entry_id}, '
|
||||
u'Course: {course_id}, '
|
||||
u'Input: {task_input}'
|
||||
'Task: {task_id}, '
|
||||
'InstructorTask ID: {entry_id}, '
|
||||
'Course: {course_id}, '
|
||||
'Input: {task_input}'
|
||||
).format(
|
||||
task_id=_xmodule_instance_args.get('task_id') if _xmodule_instance_args is not None else None,
|
||||
entry_id=_entry_id,
|
||||
@@ -253,24 +249,24 @@ class _CourseGradeReportContext(object):
|
||||
"""
|
||||
grading_cxt = grades_context.grading_context(self.course, self.course_structure)
|
||||
graded_assignments_map = OrderedDict()
|
||||
for assignment_type_name, subsection_infos in six.iteritems(grading_cxt['all_graded_subsections_by_type']):
|
||||
for assignment_type_name, subsection_infos in grading_cxt['all_graded_subsections_by_type'].items():
|
||||
graded_subsections_map = OrderedDict()
|
||||
for subsection_index, subsection_info in enumerate(subsection_infos, start=1):
|
||||
subsection = subsection_info['subsection_block']
|
||||
header_name = u"{assignment_type} {subsection_index}: {subsection_name}".format(
|
||||
header_name = "{assignment_type} {subsection_index}: {subsection_name}".format(
|
||||
assignment_type=assignment_type_name,
|
||||
subsection_index=subsection_index,
|
||||
subsection_name=subsection.display_name,
|
||||
)
|
||||
graded_subsections_map[subsection.location] = header_name
|
||||
|
||||
average_header = u"{assignment_type}".format(assignment_type=assignment_type_name)
|
||||
average_header = f"{assignment_type_name}"
|
||||
|
||||
# Use separate subsection and average columns only if
|
||||
# there's more than one subsection.
|
||||
separate_subsection_avg_headers = len(subsection_infos) > 1
|
||||
if separate_subsection_avg_headers:
|
||||
average_header += u" (Avg)"
|
||||
average_header += " (Avg)"
|
||||
|
||||
graded_assignments_map[assignment_type_name] = {
|
||||
'subsection_headers': graded_subsections_map,
|
||||
@@ -285,11 +281,11 @@ class _CourseGradeReportContext(object):
|
||||
Updates the status on the celery task to the given message.
|
||||
Also logs the update.
|
||||
"""
|
||||
TASK_LOG.info(u'%s, Task type: %s, %s', self.task_info_string, self.action_name, message)
|
||||
TASK_LOG.info('%s, Task type: %s, %s', self.task_info_string, self.action_name, message)
|
||||
return self.task_progress.update_task_state(extra_meta={'step': message})
|
||||
|
||||
|
||||
class _ProblemGradeReportContext(object):
|
||||
class _ProblemGradeReportContext:
|
||||
"""
|
||||
Internal class that provides a common context to use for a single problem
|
||||
grade report. When a report is parallelized across multiple processes,
|
||||
@@ -331,7 +327,7 @@ class _ProblemGradeReportContext(object):
|
||||
"""
|
||||
scorable_blocks_map = OrderedDict()
|
||||
grading_context = grades_context.grading_context_for_course(self.course)
|
||||
for assignment_type_name, subsection_infos in six.iteritems(grading_context['all_graded_subsections_by_type']):
|
||||
for assignment_type_name, subsection_infos in grading_context['all_graded_subsections_by_type'].items():
|
||||
for subsection_index, subsection_info in enumerate(subsection_infos, start=1):
|
||||
for scorable_block in subsection_info['scored_descendants']:
|
||||
header_name = (
|
||||
@@ -360,7 +356,7 @@ class _ProblemGradeReportContext(object):
|
||||
return self.task_progress.update_task_state(extra_meta={'step': message})
|
||||
|
||||
|
||||
class _CertificateBulkContext(object):
|
||||
class _CertificateBulkContext:
|
||||
def __init__(self, context, users):
|
||||
certificate_whitelist = CertificateWhitelist.objects.filter(course_id=context.course_id, whitelist=True)
|
||||
self.whitelisted_user_ids = [entry.user_id for entry in certificate_whitelist]
|
||||
@@ -371,7 +367,7 @@ class _CertificateBulkContext(object):
|
||||
}
|
||||
|
||||
|
||||
class _TeamBulkContext(object): # lint-amnesty, pylint: disable=missing-class-docstring
|
||||
class _TeamBulkContext: # lint-amnesty, pylint: disable=missing-class-docstring
|
||||
def __init__(self, context, users):
|
||||
self.enabled = context.teams_enabled
|
||||
if self.enabled:
|
||||
@@ -384,13 +380,13 @@ class _TeamBulkContext(object): # lint-amnesty, pylint: disable=missing-class-d
|
||||
self.teams_by_user = {}
|
||||
|
||||
|
||||
class _EnrollmentBulkContext(object):
|
||||
class _EnrollmentBulkContext:
|
||||
def __init__(self, context, users):
|
||||
CourseEnrollment.bulk_fetch_enrollment_states(users, context.course_id)
|
||||
self.verified_users = set(IDVerificationService.get_verified_user_ids(users))
|
||||
|
||||
|
||||
class _CourseGradeBulkContext(object): # lint-amnesty, pylint: disable=missing-class-docstring
|
||||
class _CourseGradeBulkContext: # lint-amnesty, pylint: disable=missing-class-docstring
|
||||
def __init__(self, context, users):
|
||||
self.certs = _CertificateBulkContext(context, users)
|
||||
self.teams = _TeamBulkContext(context, users)
|
||||
@@ -401,7 +397,7 @@ class _CourseGradeBulkContext(object): # lint-amnesty, pylint: disable=missing-
|
||||
BulkCourseTags.prefetch(context.course_id, users)
|
||||
|
||||
|
||||
class CourseGradeReport(object):
|
||||
class CourseGradeReport:
|
||||
"""
|
||||
Class to encapsulate functionality related to generating Grade Reports.
|
||||
"""
|
||||
@@ -421,18 +417,18 @@ class CourseGradeReport(object):
|
||||
"""
|
||||
Internal method for generating a grade report for the given context.
|
||||
"""
|
||||
context.update_status(u'Starting grades')
|
||||
context.update_status('Starting grades')
|
||||
success_headers = self._success_headers(context)
|
||||
error_headers = self._error_headers()
|
||||
batched_rows = self._batched_rows(context)
|
||||
|
||||
context.update_status(u'Compiling grades')
|
||||
context.update_status('Compiling grades')
|
||||
success_rows, error_rows = self._compile(context, batched_rows)
|
||||
|
||||
context.update_status(u'Uploading grades')
|
||||
context.update_status('Uploading grades')
|
||||
self._upload(context, success_headers, success_rows, error_headers, error_rows)
|
||||
|
||||
return context.update_status(u'Completed grades')
|
||||
return context.update_status('Completed grades')
|
||||
|
||||
def _success_headers(self, context):
|
||||
"""
|
||||
@@ -442,7 +438,7 @@ class CourseGradeReport(object):
|
||||
["Student ID", "Email", "Username"] +
|
||||
self._grades_header(context) +
|
||||
(['Cohort Name'] if context.cohorts_enabled else []) +
|
||||
[u'Experiment Group ({})'.format(partition.name) for partition in context.course_experiments] +
|
||||
[f'Experiment Group ({partition.name})' for partition in context.course_experiments] +
|
||||
(['Team Name'] if context.teams_enabled else []) +
|
||||
['Enrollment Track', 'Verification Status'] +
|
||||
['Certificate Eligible', 'Certificate Delivered', 'Certificate Type'] +
|
||||
@@ -496,9 +492,9 @@ class CourseGradeReport(object):
|
||||
"""
|
||||
graded_assignments = context.graded_assignments
|
||||
grades_header = ["Grade"]
|
||||
for assignment_info in six.itervalues(graded_assignments):
|
||||
for assignment_info in graded_assignments.values():
|
||||
if assignment_info['separate_subsection_avg_headers']:
|
||||
grades_header.extend(six.itervalues(assignment_info['subsection_headers']))
|
||||
grades_header.extend(assignment_info['subsection_headers'].values())
|
||||
grades_header.append(assignment_info['average_header'])
|
||||
return grades_header
|
||||
|
||||
@@ -519,10 +515,10 @@ class CourseGradeReport(object):
|
||||
verified_only (boolean): is a boolean when True, returns only verified enrollees.
|
||||
"""
|
||||
if optimize_get_learners_switch_enabled():
|
||||
TASK_LOG.info(u'%s, Creating Course Grade with optimization', task_log_message)
|
||||
TASK_LOG.info('%s, Creating Course Grade with optimization', task_log_message)
|
||||
return users_for_course_v2(course_id, verified_only=verified_only)
|
||||
|
||||
TASK_LOG.info(u'%s, Creating Course Grade without optimization', task_log_message)
|
||||
TASK_LOG.info('%s, Creating Course Grade without optimization', task_log_message)
|
||||
return users_for_course(course_id, verified_only=verified_only)
|
||||
|
||||
def users_for_course(course_id, verified_only=False):
|
||||
@@ -565,7 +561,7 @@ class CourseGradeReport(object):
|
||||
).select_related('profile')
|
||||
yield users
|
||||
course_id = context.course_id
|
||||
task_log_message = u'{}, Task type: {}'.format(context.task_info_string, context.action_name)
|
||||
task_log_message = f'{context.task_info_string}, Task type: {context.action_name}'
|
||||
return get_enrolled_learners_for_course(course_id=course_id, verified_only=context.report_for_verified_only)
|
||||
|
||||
def _user_grades(self, course_grade, context):
|
||||
@@ -574,7 +570,7 @@ class CourseGradeReport(object):
|
||||
to the headers for this report.
|
||||
"""
|
||||
grade_results = []
|
||||
for _, assignment_info in six.iteritems(context.graded_assignments):
|
||||
for _, assignment_info in context.graded_assignments.items():
|
||||
subsection_grades, subsection_grades_results = self._user_subsection_grades(
|
||||
course_grade,
|
||||
assignment_info['subsection_headers'],
|
||||
@@ -599,7 +595,7 @@ class CourseGradeReport(object):
|
||||
if subsection_grade.attempted_graded or subsection_grade.override:
|
||||
grade_result = subsection_grade.percent_graded
|
||||
else:
|
||||
grade_result = u'Not Attempted'
|
||||
grade_result = 'Not Attempted'
|
||||
grade_results.append([grade_result])
|
||||
subsection_grades.append(subsection_grade)
|
||||
return subsection_grades, grade_results
|
||||
@@ -691,7 +687,7 @@ class CourseGradeReport(object):
|
||||
):
|
||||
if not course_grade:
|
||||
# An empty gradeset means we failed to grade a student.
|
||||
error_rows.append([user.id, user.username, text_type(error)])
|
||||
error_rows.append([user.id, user.username, str(error)])
|
||||
else:
|
||||
success_rows.append(
|
||||
[user.id, user.email, user.username] +
|
||||
@@ -774,7 +770,7 @@ class ProblemGradeReport(GradeReportBase):
|
||||
):
|
||||
context.task_progress.attempted += 1
|
||||
if not course_grade:
|
||||
err_msg = text_type(error)
|
||||
err_msg = str(error)
|
||||
# There was an error grading this student.
|
||||
if not err_msg:
|
||||
err_msg = 'Unknown error'
|
||||
@@ -818,7 +814,7 @@ class ProblemGradeReport(GradeReportBase):
|
||||
get_cache(CourseEnrollment.MODE_CACHE_NAMESPACE).clear()
|
||||
|
||||
|
||||
class ProblemResponses(object):
|
||||
class ProblemResponses:
|
||||
"""
|
||||
Class to encapsulate functionality related to generating Problem Responses Reports.
|
||||
"""
|
||||
@@ -862,8 +858,7 @@ class ProblemResponses(object):
|
||||
|
||||
for block in course_blocks.get_children(root):
|
||||
name = course_blocks.get_xblock_field(block, 'display_name') or block.block_type
|
||||
for result in cls._build_problem_list(course_blocks, block, path + [name]):
|
||||
yield result
|
||||
yield from cls._build_problem_list(course_blocks, block, path + [name])
|
||||
|
||||
@classmethod
|
||||
def _build_student_data(
|
||||
|
||||
@@ -5,7 +5,9 @@ running state of a course.
|
||||
"""
|
||||
|
||||
|
||||
import csv
|
||||
import logging
|
||||
import os # lint-amnesty, pylint: disable=unused-import
|
||||
from collections import OrderedDict
|
||||
from contextlib import contextmanager
|
||||
from datetime import datetime
|
||||
@@ -13,10 +15,6 @@ from io import StringIO # lint-amnesty, pylint: disable=unused-import
|
||||
from tempfile import TemporaryFile
|
||||
from time import time
|
||||
from zipfile import ZipFile # lint-amnesty, pylint: disable=unused-import
|
||||
import csv
|
||||
import os # lint-amnesty, pylint: disable=unused-import
|
||||
import unicodecsv
|
||||
import six
|
||||
|
||||
from django.contrib.auth.models import User # lint-amnesty, pylint: disable=imported-auth-user
|
||||
from django.core.exceptions import ValidationError
|
||||
@@ -26,18 +24,12 @@ from pytz import UTC
|
||||
|
||||
from lms.djangoapps.instructor_analytics.basic import get_proctored_exam_results
|
||||
from lms.djangoapps.instructor_analytics.csvs import format_dictlist
|
||||
from lms.djangoapps.survey.models import SurveyAnswer
|
||||
from openedx.core.djangoapps.course_groups.cohorts import add_user_to_cohort
|
||||
from openedx.core.djangoapps.course_groups.models import CourseUserGroup
|
||||
from lms.djangoapps.survey.models import SurveyAnswer
|
||||
from common.djangoapps.util.file import UniversalNewlineIterator
|
||||
|
||||
from .runner import TaskProgress
|
||||
from .utils import (
|
||||
UPDATE_STATUS_FAILED,
|
||||
UPDATE_STATUS_SUCCEEDED,
|
||||
upload_csv_to_report_store,
|
||||
upload_zip_to_report_store,
|
||||
)
|
||||
from .utils import UPDATE_STATUS_FAILED, UPDATE_STATUS_SUCCEEDED, upload_csv_to_report_store, upload_zip_to_report_store
|
||||
|
||||
# define different loggers for use within tasks and on client side
|
||||
TASK_LOG = logging.getLogger('edx.celery.task')
|
||||
@@ -156,7 +148,7 @@ def _get_csv_file_content(csv_file):
|
||||
returns appropriate csv file content based on input and output is
|
||||
compatible with python versions
|
||||
"""
|
||||
if (not isinstance(csv_file, str)) and six.PY3:
|
||||
if not isinstance(csv_file, str):
|
||||
content = csv_file.read()
|
||||
else:
|
||||
content = csv_file
|
||||
@@ -166,10 +158,7 @@ def _get_csv_file_content(csv_file):
|
||||
else:
|
||||
csv_content = content
|
||||
|
||||
if six.PY3:
|
||||
return csv_content
|
||||
else:
|
||||
return UniversalNewlineIterator(csv_content)
|
||||
return csv_content
|
||||
|
||||
|
||||
def cohort_students_and_upload(_xmodule_instance_args, _entry_id, course_id, task_input, action_name): # lint-amnesty, pylint: disable=too-many-statements
|
||||
@@ -183,10 +172,7 @@ def cohort_students_and_upload(_xmodule_instance_args, _entry_id, course_id, tas
|
||||
# Iterate through rows to get total assignments for task progress
|
||||
with DefaultStorage().open(task_input['file_name']) as f:
|
||||
total_assignments = 0
|
||||
if six.PY3:
|
||||
reader = csv.DictReader(_get_csv_file_content(f).splitlines())
|
||||
else:
|
||||
reader = unicodecsv.DictReader(_get_csv_file_content(f), encoding='utf-8')
|
||||
reader = csv.DictReader(_get_csv_file_content(f).splitlines())
|
||||
|
||||
for _line in reader:
|
||||
total_assignments += 1
|
||||
@@ -204,10 +190,7 @@ def cohort_students_and_upload(_xmodule_instance_args, _entry_id, course_id, tas
|
||||
|
||||
with DefaultStorage().open(task_input['file_name']) as f:
|
||||
|
||||
if six.PY3:
|
||||
reader = csv.DictReader(_get_csv_file_content(f).splitlines())
|
||||
else:
|
||||
reader = unicodecsv.DictReader(_get_csv_file_content(f), encoding='utf-8')
|
||||
reader = csv.DictReader(_get_csv_file_content(f).splitlines())
|
||||
|
||||
for row in reader:
|
||||
# Try to use the 'email' field to identify the user. If it's not present, use 'username'.
|
||||
@@ -277,7 +260,7 @@ def cohort_students_and_upload(_xmodule_instance_args, _entry_id, course_id, tas
|
||||
else status_dict[column_name]
|
||||
for column_name in output_header
|
||||
]
|
||||
for _cohort_name, status_dict in six.iteritems(cohorts_status)
|
||||
for _cohort_name, status_dict in cohorts_status.items()
|
||||
]
|
||||
output_rows.insert(0, output_header)
|
||||
upload_csv_to_report_store(output_rows, 'cohort_results', course_id, start_date)
|
||||
@@ -298,21 +281,21 @@ def upload_ora2_data(
|
||||
num_attempted = 1
|
||||
num_total = 1
|
||||
|
||||
fmt = u'Task: {task_id}, InstructorTask ID: {entry_id}, Course: {course_id}, Input: {task_input}'
|
||||
fmt = 'Task: {task_id}, InstructorTask ID: {entry_id}, Course: {course_id}, Input: {task_input}'
|
||||
task_info_string = fmt.format(
|
||||
task_id=_xmodule_instance_args.get('task_id') if _xmodule_instance_args is not None else None,
|
||||
entry_id=_entry_id,
|
||||
course_id=course_id,
|
||||
task_input=_task_input
|
||||
)
|
||||
TASK_LOG.info(u'%s, Task type: %s, Starting task execution', task_info_string, action_name)
|
||||
TASK_LOG.info('%s, Task type: %s, Starting task execution', task_info_string, action_name)
|
||||
|
||||
task_progress = TaskProgress(action_name, num_total, start_time)
|
||||
task_progress.attempted = num_attempted
|
||||
|
||||
curr_step = {'step': "Collecting responses"}
|
||||
TASK_LOG.info(
|
||||
u'%s, Task type: %s, Current step: %s for all submissions',
|
||||
'%s, Task type: %s, Current step: %s for all submissions',
|
||||
task_info_string,
|
||||
action_name,
|
||||
curr_step,
|
||||
@@ -336,7 +319,7 @@ def upload_ora2_data(
|
||||
task_progress.succeeded = 1
|
||||
curr_step = {'step': "Uploading CSV"}
|
||||
TASK_LOG.info(
|
||||
u'%s, Task type: %s, Current step: %s',
|
||||
'%s, Task type: %s, Current step: %s',
|
||||
task_info_string,
|
||||
action_name,
|
||||
curr_step,
|
||||
@@ -347,7 +330,7 @@ def upload_ora2_data(
|
||||
|
||||
curr_step = {'step': 'Finalizing ORA data report'}
|
||||
task_progress.update_task_state(extra_meta=curr_step)
|
||||
TASK_LOG.info(u'%s, Task type: %s, Upload complete.', task_info_string, action_name)
|
||||
TASK_LOG.info('%s, Task type: %s, Upload complete.', task_info_string, action_name)
|
||||
|
||||
return UPDATE_STATUS_SUCCEEDED
|
||||
|
||||
@@ -408,7 +391,7 @@ def upload_ora2_submission_files(
|
||||
course_id=course_id,
|
||||
task_input=_task_input
|
||||
)
|
||||
TASK_LOG.info(u'%s, Task type: %s, Starting task execution', task_info_string, action_name)
|
||||
TASK_LOG.info('%s, Task type: %s, Starting task execution', task_info_string, action_name)
|
||||
|
||||
task_progress = TaskProgress(action_name, num_total, start_time)
|
||||
task_progress.attempted = num_attempted
|
||||
@@ -452,6 +435,6 @@ def upload_ora2_submission_files(
|
||||
task_progress.succeeded = 1
|
||||
curr_step = {'step': 'Finalizing attachments extracting'}
|
||||
task_progress.update_task_state(extra_meta=curr_step)
|
||||
TASK_LOG.info(u'%s, Task type: %s, Upload complete.', task_info_string, action_name)
|
||||
TASK_LOG.info('%s, Task type: %s, Upload complete.', task_info_string, action_name)
|
||||
|
||||
return UPDATE_STATUS_SUCCEEDED
|
||||
|
||||
@@ -7,22 +7,21 @@ import json
|
||||
import logging
|
||||
from time import time
|
||||
|
||||
import six
|
||||
from django.utils.translation import ugettext_noop
|
||||
from opaque_keys.edx.keys import UsageKey
|
||||
from xblock.runtime import KvsFieldData
|
||||
from xblock.scorable import Score
|
||||
|
||||
from capa.responsetypes import LoncapaProblemError, ResponseError, StudentInputError
|
||||
from common.djangoapps.student.models import get_user_by_username_or_email
|
||||
from common.djangoapps.track.event_transaction_utils import create_new_event_transaction_id, set_event_transaction_type
|
||||
from common.djangoapps.track.views import task_track
|
||||
from common.djangoapps.util.db import outer_atomic
|
||||
from lms.djangoapps.courseware.courses import get_course_by_id, get_problems_in_section
|
||||
from lms.djangoapps.courseware.model_data import DjangoKeyValueStore, FieldDataCache
|
||||
from lms.djangoapps.courseware.models import StudentModule
|
||||
from lms.djangoapps.courseware.module_render import get_module_for_descriptor_internal
|
||||
from lms.djangoapps.grades.api import events as grades_events
|
||||
from common.djangoapps.student.models import get_user_by_username_or_email
|
||||
from common.djangoapps.track.event_transaction_utils import create_new_event_transaction_id, set_event_transaction_type
|
||||
from common.djangoapps.track.views import task_track
|
||||
from common.djangoapps.util.db import outer_atomic
|
||||
from xmodule.modulestore.django import modulestore
|
||||
|
||||
from ..exceptions import UpdateProblemModuleStateError
|
||||
@@ -75,7 +74,7 @@ def perform_module_state_update(update_fcn, filter_fcn, _entry_id, course_id, ta
|
||||
|
||||
# find the problem descriptor:
|
||||
problem_descriptor = modulestore().get_item(usage_key)
|
||||
problems[six.text_type(usage_key)] = problem_descriptor
|
||||
problems[str(usage_key)] = problem_descriptor
|
||||
|
||||
# if entrance_exam is present grab all problems in it
|
||||
if entrance_exam_url:
|
||||
@@ -91,7 +90,7 @@ def perform_module_state_update(update_fcn, filter_fcn, _entry_id, course_id, ta
|
||||
|
||||
for module_to_update in modules_to_update:
|
||||
task_progress.attempted += 1
|
||||
module_descriptor = problems[six.text_type(module_to_update.module_state_key)]
|
||||
module_descriptor = problems[str(module_to_update.module_state_key)]
|
||||
# There is no try here: if there's an error, we let it throw, and the task will
|
||||
# be marked as FAILED, with a stack trace.
|
||||
update_status = update_fcn(module_descriptor, module_to_update, task_input)
|
||||
@@ -104,7 +103,7 @@ def perform_module_state_update(update_fcn, filter_fcn, _entry_id, course_id, ta
|
||||
elif update_status == UPDATE_STATUS_SKIPPED:
|
||||
task_progress.skipped += 1
|
||||
else:
|
||||
raise UpdateProblemModuleStateError(u"Unexpected update_status returned: {}".format(update_status))
|
||||
raise UpdateProblemModuleStateError(f"Unexpected update_status returned: {update_status}")
|
||||
|
||||
return task_progress.update_task_state()
|
||||
|
||||
@@ -144,7 +143,7 @@ def rescore_problem_module_state(xmodule_instance_args, module_descriptor, stude
|
||||
if instance is None:
|
||||
# Either permissions just changed, or someone is trying to be clever
|
||||
# and load something they shouldn't have access to.
|
||||
msg = u"No module {location} for student {student}--access denied?".format(
|
||||
msg = "No module {location} for student {student}--access denied?".format(
|
||||
location=usage_key,
|
||||
student=student
|
||||
)
|
||||
@@ -154,7 +153,7 @@ def rescore_problem_module_state(xmodule_instance_args, module_descriptor, stude
|
||||
if not hasattr(instance, 'rescore'):
|
||||
# This should not happen, since it should be already checked in the
|
||||
# caller, but check here to be sure.
|
||||
msg = u"Specified module {0} of type {1} does not support rescoring.".format(usage_key, instance.__class__)
|
||||
msg = f"Specified module {usage_key} of type {instance.__class__} does not support rescoring."
|
||||
raise UpdateProblemModuleStateError(msg)
|
||||
|
||||
# We check here to see if the problem has any submissions. If it does not, we don't want to rescore it
|
||||
@@ -172,8 +171,8 @@ def rescore_problem_module_state(xmodule_instance_args, module_descriptor, stude
|
||||
instance.rescore(only_if_higher=task_input['only_if_higher'])
|
||||
except (LoncapaProblemError, StudentInputError, ResponseError):
|
||||
TASK_LOG.warning(
|
||||
u"error processing rescore call for course %(course)s, problem %(loc)s "
|
||||
u"and student %(student)s",
|
||||
"error processing rescore call for course %(course)s, problem %(loc)s "
|
||||
"and student %(student)s",
|
||||
dict(
|
||||
course=course_id,
|
||||
loc=usage_key,
|
||||
@@ -184,8 +183,8 @@ def rescore_problem_module_state(xmodule_instance_args, module_descriptor, stude
|
||||
|
||||
instance.save()
|
||||
TASK_LOG.debug(
|
||||
u"successfully processed rescore call for course %(course)s, problem %(loc)s "
|
||||
u"and student %(student)s",
|
||||
"successfully processed rescore call for course %(course)s, problem %(loc)s "
|
||||
"and student %(student)s",
|
||||
dict(
|
||||
course=course_id,
|
||||
loc=usage_key,
|
||||
@@ -229,7 +228,7 @@ def override_score_module_state(xmodule_instance_args, module_descriptor, studen
|
||||
if instance is None:
|
||||
# Either permissions just changed, or someone is trying to be clever
|
||||
# and load something they shouldn't have access to.
|
||||
msg = u"No module {location} for student {student}--access denied?".format(
|
||||
msg = "No module {location} for student {student}--access denied?".format(
|
||||
location=usage_key,
|
||||
student=student
|
||||
)
|
||||
@@ -264,8 +263,8 @@ def override_score_module_state(xmodule_instance_args, module_descriptor, studen
|
||||
instance.publish_grade()
|
||||
instance.save()
|
||||
TASK_LOG.debug(
|
||||
u"successfully processed score override for course %(course)s, problem %(loc)s "
|
||||
u"and student %(student)s",
|
||||
"successfully processed score override for course %(course)s, problem %(loc)s "
|
||||
"and student %(student)s",
|
||||
dict(
|
||||
course=course_id,
|
||||
loc=usage_key,
|
||||
|
||||
@@ -10,13 +10,13 @@ from time import time
|
||||
from celery import current_task
|
||||
from django.db import reset_queries
|
||||
|
||||
from lms.djangoapps.instructor_task.models import PROGRESS, InstructorTask
|
||||
from common.djangoapps.util.db import outer_atomic
|
||||
from lms.djangoapps.instructor_task.models import PROGRESS, InstructorTask
|
||||
|
||||
TASK_LOG = logging.getLogger('edx.celery.task')
|
||||
|
||||
|
||||
class TaskProgress(object):
|
||||
class TaskProgress:
|
||||
"""
|
||||
Encapsulates the current task's progress by keeping track of
|
||||
'attempted', 'succeeded', 'skipped', 'failed', 'total',
|
||||
@@ -103,15 +103,15 @@ def run_main_task(entry_id, task_fcn, action_name):
|
||||
task_input = json.loads(entry.task_input)
|
||||
|
||||
# Construct log message
|
||||
fmt = u'Task: {task_id}, InstructorTask ID: {entry_id}, Course: {course_id}, Input: {task_input}'
|
||||
fmt = 'Task: {task_id}, InstructorTask ID: {entry_id}, Course: {course_id}, Input: {task_input}'
|
||||
task_info_string = fmt.format(task_id=task_id, entry_id=entry_id, course_id=course_id, task_input=task_input)
|
||||
TASK_LOG.info(u'%s, Starting update (nothing %s yet)', task_info_string, action_name)
|
||||
TASK_LOG.info('%s, Starting update (nothing %s yet)', task_info_string, action_name)
|
||||
|
||||
# Check that the task_id submitted in the InstructorTask matches the current task
|
||||
# that is running.
|
||||
request_task_id = _get_current_task().request.id
|
||||
if task_id != request_task_id:
|
||||
fmt = u'{task_info}, Requested task did not match actual task "{actual_id}"'
|
||||
fmt = '{task_info}, Requested task did not match actual task "{actual_id}"'
|
||||
message = fmt.format(task_info=task_info_string, actual_id=request_task_id)
|
||||
TASK_LOG.error(message)
|
||||
raise ValueError(message)
|
||||
@@ -123,7 +123,7 @@ def run_main_task(entry_id, task_fcn, action_name):
|
||||
reset_queries()
|
||||
|
||||
# Log and exit, returning task_progress info as task result
|
||||
TASK_LOG.info(u'%s, Task type: %s, Finishing task: %s', task_info_string, action_name, task_progress)
|
||||
TASK_LOG.info('%s, Task type: %s, Finishing task: %s', task_info_string, action_name, task_progress)
|
||||
return task_progress
|
||||
|
||||
|
||||
|
||||
@@ -5,10 +5,10 @@ Utility methods for instructor tasks
|
||||
|
||||
from eventtracking import tracker
|
||||
|
||||
from lms.djangoapps.instructor_task.models import ReportStore
|
||||
from common.djangoapps.util.file import course_filename_prefix_generator
|
||||
from lms.djangoapps.instructor_task.models import ReportStore
|
||||
|
||||
REPORT_REQUESTED_EVENT_NAME = u'edx.instructor.report.requested'
|
||||
REPORT_REQUESTED_EVENT_NAME = 'edx.instructor.report.requested'
|
||||
|
||||
# define value to use when no task_id is provided:
|
||||
UNKNOWN_TASK_ID = 'unknown-task_id'
|
||||
@@ -37,7 +37,7 @@ def upload_csv_to_report_store(rows, csv_name, course_id, timestamp, config_name
|
||||
report_name: string - Name of the generated report
|
||||
"""
|
||||
report_store = ReportStore.from_config(config_name)
|
||||
report_name = u"{course_prefix}_{csv_name}_{timestamp_str}.csv".format(
|
||||
report_name = "{course_prefix}_{csv_name}_{timestamp_str}.csv".format(
|
||||
course_prefix=course_filename_prefix_generator(course_id),
|
||||
csv_name=csv_name,
|
||||
timestamp_str=timestamp.strftime("%Y-%m-%d-%H%M")
|
||||
@@ -54,7 +54,7 @@ def upload_zip_to_report_store(file, zip_name, course_id, timestamp, config_name
|
||||
"""
|
||||
report_store = ReportStore.from_config(config_name)
|
||||
|
||||
report_name = u"{course_prefix}_{zip_name}_{timestamp_str}.zip".format(
|
||||
report_name = "{course_prefix}_{zip_name}_{timestamp_str}.zip".format(
|
||||
course_prefix=course_filename_prefix_generator(course_id),
|
||||
zip_name=zip_name,
|
||||
timestamp_str=timestamp.strftime("%Y-%m-%d-%H%M")
|
||||
|
||||
Reference in New Issue
Block a user