pyupgrade on course_creators, maintenance and models apps under CMS (#26709)

This commit is contained in:
M. Zulqarnain
2021-03-02 16:45:20 +05:00
committed by GitHub
parent ba86198519
commit 3a5be3b074
9 changed files with 73 additions and 81 deletions

View File

@@ -114,7 +114,7 @@ def send_user_notification_callback(sender, **kwargs): # lint-amnesty, pylint:
try:
user.email_user(subject, message, studio_request_email)
except: # lint-amnesty, pylint: disable=bare-except
log.warning(u"Unable to send course creator status e-mail to %s", user.email)
log.warning("Unable to send course creator status e-mail to %s", user.email)
@receiver(send_admin_notification, sender=CourseCreator)
@@ -140,4 +140,4 @@ def send_admin_notification_callback(sender, **kwargs): # lint-amnesty, pylint:
fail_silently=False
)
except SMTPException:
log.warning(u"Failure sending 'pending state' e-mail for %s to %s", user.email, studio_request_email)
log.warning("Failure sending 'pending state' e-mail for %s to %s", user.email, studio_request_email)

View File

@@ -1,6 +1,3 @@
# -*- coding: utf-8 -*-
from django.conf import settings
from django.db import migrations, models
@@ -16,8 +13,8 @@ class Migration(migrations.Migration):
name='CourseCreator',
fields=[
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
('state_changed', models.DateTimeField(help_text='The date when state was last updated', verbose_name=u'state last updated', auto_now_add=True)),
('state', models.CharField(default=u'unrequested', help_text='Current course creator state', max_length=24, choices=[(u'unrequested', 'unrequested'), (u'pending', 'pending'), (u'granted', 'granted'), (u'denied', 'denied')])),
('state_changed', models.DateTimeField(help_text='The date when state was last updated', verbose_name='state last updated', auto_now_add=True)),
('state', models.CharField(default='unrequested', help_text='Current course creator state', max_length=24, choices=[('unrequested', 'unrequested'), ('pending', 'pending'), ('granted', 'granted'), ('denied', 'denied')])),
('note', models.CharField(help_text='Optional notes about this user (for example, why course creation access was denied)', max_length=512, blank=True)),
('user', models.OneToOneField(to=settings.AUTH_USER_MODEL, help_text='Studio user', on_delete=models.CASCADE)),
],

View File

@@ -28,21 +28,21 @@ class CourseCreator(models.Model):
.. no_pii:
"""
UNREQUESTED = u'unrequested'
PENDING = u'pending'
GRANTED = u'granted'
DENIED = u'denied'
UNREQUESTED = 'unrequested'
PENDING = 'pending'
GRANTED = 'granted'
DENIED = 'denied'
# Second value is the "human-readable" version.
STATES = (
(UNREQUESTED, _(u'unrequested')),
(PENDING, _(u'pending')),
(GRANTED, _(u'granted')),
(DENIED, _(u'denied')),
(UNREQUESTED, _('unrequested')),
(PENDING, _('pending')),
(GRANTED, _('granted')),
(DENIED, _('denied')),
)
user = models.OneToOneField(User, help_text=_("Studio user"), on_delete=models.CASCADE)
state_changed = models.DateTimeField(u'state last updated', auto_now_add=True,
state_changed = models.DateTimeField('state last updated', auto_now_add=True,
help_text=_("The date when state was last updated"))
state = models.CharField(max_length=24, blank=False, choices=STATES, default=UNREQUESTED,
help_text=_("Current course creator state"))
@@ -50,7 +50,7 @@ class CourseCreator(models.Model):
"why course creation access was denied)"))
def __str__(self):
return u"{0} | {1} [{2}]".format(self.user, self.state, self.state_changed)
return f"{self.user} | {self.state} [{self.state_changed}]"
@receiver(post_init, sender=CourseCreator)

View File

@@ -3,13 +3,13 @@ Tests course_creators.admin.py.
"""
import mock
from unittest import mock
from django.contrib.admin.sites import AdminSite
from django.contrib.auth.models import User # lint-amnesty, pylint: disable=imported-auth-user
from django.core import mail
from django.http import HttpRequest
from django.test import TestCase
from six.moves import range
from cms.djangoapps.course_creators.admin import CourseCreatorAdmin
from cms.djangoapps.course_creators.models import CourseCreator
@@ -29,7 +29,7 @@ class CourseCreatorAdminTest(TestCase):
def setUp(self):
""" Test case setup """
super(CourseCreatorAdminTest, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
super().setUp()
self.user = User.objects.create_user('test_user', 'test_user+courses@edx.org', 'foo')
self.table_entry = CourseCreator(user=self.user)
self.table_entry.save()
@@ -113,7 +113,7 @@ class CourseCreatorAdminTest(TestCase):
# message sent. Admin message will follow.
base_num_emails = 1 if expect_sent_to_user else 0
if expect_sent_to_admin:
context = {'user_name': u'test_user', 'user_email': u'test_user+courses@edx.org'}
context = {'user_name': 'test_user', 'user_email': 'test_user+courses@edx.org'}
self.assertEqual(base_num_emails + 1, len(mail.outbox), 'Expected admin message to be sent')
sent_mail = mail.outbox[base_num_emails]

View File

@@ -3,7 +3,8 @@ Tests course_creators.views.py.
"""
import mock
from unittest import mock
from django.contrib.auth.models import User # lint-amnesty, pylint: disable=imported-auth-user
from django.core.exceptions import PermissionDenied
from django.test import TestCase
@@ -27,7 +28,7 @@ class CourseCreatorView(TestCase):
def setUp(self):
""" Test case setup """
super(CourseCreatorView, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
super().setUp()
self.user = User.objects.create_user('test_user', 'test_user+courses@edx.org', 'foo')
self.admin = User.objects.create_user('Mark', 'admin+courses@edx.org', 'foo')
self.admin.is_staff = True

View File

@@ -6,13 +6,12 @@ Tests for the maintenance app views.
import json
import ddt
import six
from django.conf import settings
from django.urls import reverse
from cms.djangoapps.contentstore.management.commands.utils import get_course_versions
from openedx.features.announcements.models import Announcement
from common.djangoapps.student.tests.factories import AdminFactory, UserFactory
from openedx.features.announcements.models import Announcement
from xmodule.modulestore import ModuleStoreEnum
from xmodule.modulestore.django import modulestore
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
@@ -30,7 +29,7 @@ class TestMaintenanceIndex(ModuleStoreTestCase):
"""
def setUp(self):
super(TestMaintenanceIndex, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
super().setUp()
self.user = AdminFactory()
login_success = self.client.login(username=self.user.username, password='test')
self.assertTrue(login_success)
@@ -56,7 +55,7 @@ class MaintenanceViewTestCase(ModuleStoreTestCase):
view_url = ''
def setUp(self):
super(MaintenanceViewTestCase, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
super().setUp()
self.user = AdminFactory()
login_success = self.client.login(username=self.user.username, password='test')
self.assertTrue(login_success)
@@ -73,7 +72,7 @@ class MaintenanceViewTestCase(ModuleStoreTestCase):
Reverse the setup.
"""
self.client.logout()
super(MaintenanceViewTestCase, self).tearDown() # lint-amnesty, pylint: disable=super-with-arguments
super().tearDown()
@ddt.ddt
@@ -119,7 +118,7 @@ class MaintenanceViewAccessTests(MaintenanceViewTestCase):
response = self.client.get(url)
self.assertContains(
response,
u'Must be {platform_name} staff to perform this action.'.format(platform_name=settings.PLATFORM_NAME),
f'Must be {settings.PLATFORM_NAME} staff to perform this action.',
status_code=403
)
@@ -131,7 +130,7 @@ class TestForcePublish(MaintenanceViewTestCase):
"""
def setUp(self):
super(TestForcePublish, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
super().setUp()
self.view_url = reverse('maintenance:force_publish_course')
def setup_test_course(self):
@@ -177,7 +176,7 @@ class TestForcePublish(MaintenanceViewTestCase):
# validate non split error message
course = CourseFactory.create(default_store=ModuleStoreEnum.Type.mongo)
self.verify_error_message(
data={'course-id': six.text_type(course.id)},
data={'course-id': str(course.id)},
error_message='Force publishing course is not supported with old mongo courses.'
)
@@ -189,7 +188,7 @@ class TestForcePublish(MaintenanceViewTestCase):
# validate non split error message
course = CourseFactory.create(org='e', number='d', run='X', default_store=ModuleStoreEnum.Type.mongo)
self.verify_error_message(
data={'course-id': six.text_type(course.id)},
data={'course-id': str(course.id)},
error_message='Force publishing course is not supported with old mongo courses.'
)
# Now search for the course key in split version.
@@ -210,7 +209,7 @@ class TestForcePublish(MaintenanceViewTestCase):
# now course is published, we should get `already published course` error.
self.verify_error_message(
data={'course-id': six.text_type(course.id)},
data={'course-id': str(course.id)},
error_message='Course is already in published state.'
)
@@ -222,7 +221,7 @@ class TestForcePublish(MaintenanceViewTestCase):
course (object): a course object.
"""
# get draft and publish branch versions
versions = get_course_versions(six.text_type(course.id))
versions = get_course_versions(str(course.id))
# verify that draft and publish point to different versions
self.assertNotEqual(versions['draft-branch'], versions['published-branch'])
@@ -242,7 +241,7 @@ class TestForcePublish(MaintenanceViewTestCase):
# force publish course view
data = {
'course-id': six.text_type(course.id)
'course-id': str(course.id)
}
response = self.client.post(self.view_url, data=data, HTTP_X_REQUESTED_WITH='XMLHttpRequest')
response_data = json.loads(response.content.decode('utf-8'))
@@ -271,7 +270,7 @@ class TestAnnouncementsViews(MaintenanceViewTestCase):
"""
def setUp(self):
super(TestAnnouncementsViews, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
super().setUp()
self.admin = AdminFactory.create(
email='staff@edx.org',
username='admin',

View File

@@ -5,7 +5,6 @@ Views for the maintenance app.
import logging
import six
from django.core.validators import ValidationError
from django.db import transaction
from django.urls import reverse, reverse_lazy
@@ -16,14 +15,13 @@ from django.views.generic.edit import CreateView, DeleteView, UpdateView
from django.views.generic.list import ListView
from opaque_keys import InvalidKeyError
from opaque_keys.edx.keys import CourseKey
from six import text_type
from cms.djangoapps.contentstore.management.commands.utils import get_course_versions
from common.djangoapps.edxmako.shortcuts import render_to_response
from openedx.features.announcements.forms import AnnouncementForm
from openedx.features.announcements.models import Announcement
from common.djangoapps.util.json_request import JsonResponse
from common.djangoapps.util.views import require_global_staff
from openedx.features.announcements.forms import AnnouncementForm
from openedx.features.announcements.models import Announcement
from xmodule.modulestore import ModuleStoreEnum
from xmodule.modulestore.django import modulestore
from xmodule.modulestore.exceptions import ItemNotFoundError
@@ -84,7 +82,7 @@ class MaintenanceBaseView(View):
template = 'maintenance/container.html'
def __init__(self, view=None):
super(MaintenanceBaseView, self).__init__() # lint-amnesty, pylint: disable=super-with-arguments
super().__init__()
self.context = {
'view': view if view else '',
'form_data': {},
@@ -142,7 +140,7 @@ class ForcePublishCourseView(MaintenanceBaseView):
"""
def __init__(self):
super(ForcePublishCourseView, self).__init__(MAINTENANCE_VIEWS['force_publish_course']) # lint-amnesty, pylint: disable=super-with-arguments
super().__init__(MAINTENANCE_VIEWS['force_publish_course'])
self.context.update({
'current_versions': [],
'updated_versions': [],
@@ -157,8 +155,8 @@ class ForcePublishCourseView(MaintenanceBaseView):
Returns a dict containing unicoded values of draft and published draft versions.
"""
return {
'draft-branch': six.text_type(versions['draft-branch']),
'published-branch': six.text_type(versions['published-branch'])
'draft-branch': str(versions['draft-branch']),
'published-branch': str(versions['published-branch'])
}
@transaction.atomic
@@ -188,10 +186,10 @@ class ForcePublishCourseView(MaintenanceBaseView):
self.context['msg'] = COURSE_KEY_ERROR_MESSAGES['invalid_course_key']
except ItemNotFoundError as exc:
self.context['error'] = True
self.context['msg'] = text_type(exc)
self.context['msg'] = str(exc)
except ValidationError as exc:
self.context['error'] = True
self.context['msg'] = text_type(exc)
self.context['msg'] = str(exc)
if self.context['error']:
return self.render_response()
@@ -200,7 +198,7 @@ class ForcePublishCourseView(MaintenanceBaseView):
if not hasattr(source_store, 'force_publish_course'):
self.context['msg'] = _('Force publishing course is not supported with old mongo courses.')
log.warning(
u'Force publishing course is not supported with old mongo courses. \
'Force publishing course is not supported with old mongo courses. \
%s attempted to force publish the course %s.',
request.user,
course_id,
@@ -214,7 +212,7 @@ class ForcePublishCourseView(MaintenanceBaseView):
if current_versions['published-branch'] == current_versions['draft-branch']:
self.context['msg'] = _('Course is already in published state.')
log.warning(
u'Course is already in published state. %s attempted to force publish the course %s.',
'Course is already in published state. %s attempted to force publish the course %s.',
request.user,
course_id,
exc_info=True
@@ -223,7 +221,7 @@ class ForcePublishCourseView(MaintenanceBaseView):
self.context['current_versions'] = current_versions
log.info(
u'%s dry ran force publish the course %s.',
'%s dry ran force publish the course %s.',
request.user,
course_id,
exc_info=True
@@ -238,7 +236,7 @@ class AnnouncementBaseView(View):
@method_decorator(require_global_staff)
def dispatch(self, request, *args, **kwargs):
return super(AnnouncementBaseView, self).dispatch(request, *args, **kwargs) # lint-amnesty, pylint: disable=super-with-arguments
return super().dispatch(request, *args, **kwargs)
class AnnouncementIndexView(ListView, MaintenanceBaseView):
@@ -251,10 +249,10 @@ class AnnouncementIndexView(ListView, MaintenanceBaseView):
paginate_by = 8
def __init__(self):
super(AnnouncementIndexView, self).__init__(MAINTENANCE_VIEWS['announcement_index']) # lint-amnesty, pylint: disable=super-with-arguments
super().__init__(MAINTENANCE_VIEWS['announcement_index'])
def get_context_data(self, **kwargs):
context = super(AnnouncementIndexView, self).get_context_data(**kwargs) # lint-amnesty, pylint: disable=super-with-arguments
context = super().get_context_data(**kwargs)
context['view'] = MAINTENANCE_VIEWS['announcement_index']
return context
@@ -274,7 +272,7 @@ class AnnouncementEditView(UpdateView, AnnouncementBaseView):
template_name = '/maintenance/_announcement_edit.html'
def get_context_data(self, **kwargs):
context = super(AnnouncementEditView, self).get_context_data(**kwargs) # lint-amnesty, pylint: disable=super-with-arguments
context = super().get_context_data(**kwargs)
context['action_url'] = reverse('maintenance:announcement_edit', kwargs={'pk': context['announcement'].pk})
return context
@@ -289,7 +287,7 @@ class AnnouncementCreateView(CreateView, AnnouncementBaseView):
template_name = '/maintenance/_announcement_edit.html'
def get_context_data(self, **kwargs):
context = super(AnnouncementCreateView, self).get_context_data(**kwargs) # lint-amnesty, pylint: disable=super-with-arguments
context = super().get_context_data(**kwargs)
context['action_url'] = reverse('maintenance:announcement_create')
return context

View File

@@ -7,7 +7,6 @@ from base64 import b64encode
from datetime import timedelta
from hashlib import sha1
import six
from eventtracking import tracker
from cms.djangoapps.contentstore.signals.signals import GRADING_POLICY_CHANGED
@@ -20,7 +19,7 @@ log = logging.getLogger(__name__)
GRADING_POLICY_CHANGED_EVENT_TYPE = 'edx.grades.grading_policy_changed'
class CourseGradingModel(object):
class CourseGradingModel:
"""
Basically a DAO and Model combo for CRUD operations pertaining to grading policy.
"""
@@ -71,7 +70,7 @@ class CourseGradingModel(object):
Probably not the usual path for updates as it's too coarse grained.
"""
descriptor = modulestore().get_course(course_key)
previous_grading_policy_hash = six.text_type(hash_grading_policy(descriptor.grading_policy))
previous_grading_policy_hash = str(hash_grading_policy(descriptor.grading_policy))
graders_parsed = [CourseGradingModel.parse_grader(jsonele) for jsonele in jsondict['graders']]
fire_signal = CourseGradingModel.must_fire_grading_event_and_signal(
@@ -90,10 +89,10 @@ class CourseGradingModel(object):
CourseGradingModel.update_minimum_grade_credit_from_json(course_key, jsondict['minimum_grade_credit'], user)
descriptor = modulestore().get_course(course_key)
new_grading_policy_hash = six.text_type(hash_grading_policy(descriptor.grading_policy))
new_grading_policy_hash = str(hash_grading_policy(descriptor.grading_policy))
log.info(
"Updated course grading policy for course %s from %s to %s. fire_signal = %s",
six.text_type(course_key),
str(course_key),
previous_grading_policy_hash,
new_grading_policy_hash,
fire_signal
@@ -155,7 +154,7 @@ class CourseGradingModel(object):
grader which is a full model on the client but not on the server (just a dict)
"""
descriptor = modulestore().get_course(course_key)
previous_grading_policy_hash = six.text_type(hash_grading_policy(descriptor.grading_policy))
previous_grading_policy_hash = str(hash_grading_policy(descriptor.grading_policy))
# parse removes the id; so, grab it before parse
index = int(grader.get('id', len(descriptor.raw_grader)))
@@ -175,10 +174,10 @@ class CourseGradingModel(object):
modulestore().update_item(descriptor, user.id)
descriptor = modulestore().get_course(course_key)
new_grading_policy_hash = six.text_type(hash_grading_policy(descriptor.grading_policy))
new_grading_policy_hash = str(hash_grading_policy(descriptor.grading_policy))
log.info(
"Updated grader for course %s. Grading policy has changed from %s to %s. fire_signal = %s",
six.text_type(course_key),
str(course_key),
previous_grading_policy_hash,
new_grading_policy_hash,
fire_signal
@@ -272,12 +271,12 @@ class CourseGradingModel(object):
descriptor = modulestore().get_item(location)
return {
"graderType": descriptor.format if descriptor.format is not None else 'notgraded',
"location": six.text_type(location),
"location": str(location),
}
@staticmethod
def update_section_grader_type(descriptor, grader_type, user): # lint-amnesty, pylint: disable=missing-function-docstring
if grader_type is not None and grader_type != u'notgraded':
if grader_type is not None and grader_type != 'notgraded':
descriptor.format = grader_type
descriptor.graded = True
else:
@@ -345,12 +344,12 @@ class CourseGradingModel(object):
def _grading_event_and_signal(course_key, user_id): # lint-amnesty, pylint: disable=missing-function-docstring
name = GRADING_POLICY_CHANGED_EVENT_TYPE
course = modulestore().get_course(course_key)
grading_policy_hash = six.text_type(hash_grading_policy(course.grading_policy))
grading_policy_hash = str(hash_grading_policy(course.grading_policy))
data = {
"course_id": six.text_type(course_key),
"user_id": six.text_type(user_id),
"course_id": str(course_key),
"user_id": str(user_id),
"grading_policy_hash": grading_policy_hash,
"event_transaction_id": six.text_type(create_new_event_transaction_id()),
"event_transaction_id": str(create_new_event_transaction_id()),
"event_transaction_type": GRADING_POLICY_CHANGED_EVENT_TYPE,
}
tracker.emit(name, data)

View File

@@ -6,23 +6,21 @@ Django module for Course Metadata class -- manages advanced settings and related
from datetime import datetime
import pytz
import six
from crum import get_current_user
from django.conf import settings
from django.core.exceptions import ValidationError
from django.utils.translation import ugettext as _
from six import text_type
from xblock.fields import Scope
from cms.djangoapps.contentstore import toggles
from openedx.core.lib.teams_config import TeamsetType
from openedx.features.course_experience import COURSE_ENABLE_UNENROLLED_ACCESS_FLAG
from common.djangoapps.student.roles import GlobalStaff
from common.djangoapps.xblock_django.models import XBlockStudioConfigurationFlag
from openedx.core.lib.teams_config import TeamsetType
from openedx.features.course_experience import COURSE_ENABLE_UNENROLLED_ACCESS_FLAG
from xmodule.modulestore.django import modulestore
class CourseMetadata(object):
class CourseMetadata:
'''
For CRUD operations on metadata fields which do not have specific editors
on the other pages including any user generated ones.
@@ -158,7 +156,7 @@ class CourseMetadata(object):
metadata = cls.fetch_all(descriptor)
exclude_list_of_fields = cls.get_exclude_list_of_fields(descriptor.id)
for key, value in six.iteritems(metadata):
for key, value in metadata.items():
if key in exclude_list_of_fields:
continue
result[key] = value
@@ -203,7 +201,7 @@ class CourseMetadata(object):
# Validate the values before actually setting them.
key_values = {}
for key, model in six.iteritems(jsondict):
for key, model in jsondict.items():
# should it be an error if one of the filtered list items is in the payload?
if key in exclude_list_of_fields:
continue
@@ -212,8 +210,8 @@ class CourseMetadata(object):
if hasattr(descriptor, key) and getattr(descriptor, key) != val:
key_values[key] = descriptor.fields[key].from_json(val)
except (TypeError, ValueError) as err:
raise ValueError(_(u"Incorrect format for field '{name}'. {detailed_message}").format( # lint-amnesty, pylint: disable=raise-missing-from
name=model['display_name'], detailed_message=text_type(err)))
raise ValueError(_("Incorrect format for field '{name}'. {detailed_message}").format( # lint-amnesty, pylint: disable=raise-missing-from
name=model['display_name'], detailed_message=str(err)))
return cls.update_from_dict(key_values, descriptor, user)
@@ -236,20 +234,20 @@ class CourseMetadata(object):
if not filter_tabs:
exclude_list_of_fields.remove("tabs")
filtered_dict = dict((k, v) for k, v in six.iteritems(jsondict) if k not in exclude_list_of_fields)
filtered_dict = {k: v for k, v in jsondict.items() if k not in exclude_list_of_fields}
did_validate = True
errors = []
key_values = {}
updated_data = None
for key, model in six.iteritems(filtered_dict):
for key, model in filtered_dict.items():
try:
val = model['value']
if hasattr(descriptor, key) and getattr(descriptor, key) != val:
key_values[key] = descriptor.fields[key].from_json(val)
except (TypeError, ValueError, ValidationError) as err:
did_validate = False
errors.append({'key': key, 'message': text_type(err), 'model': model})
errors.append({'key': key, 'message': str(err), 'model': model})
team_setting_errors = cls.validate_team_settings(filtered_dict)
if team_setting_errors:
@@ -272,7 +270,7 @@ class CourseMetadata(object):
"""
Update metadata descriptor from key_values. Saves to modulestore if save is true.
"""
for key, value in six.iteritems(key_values):
for key, value in key_values.items():
setattr(descriptor, key, value)
if save and key_values: