Ran pyupgrade on lms/djangoapps

Ran pyupgrade on lms/djangoapps/mailing
Ran pyupgrade on lms/djangoapps/mobile_api
Ran pyupgrade on lms/djangoapps/monitoring
This commit is contained in:
usamasadiq
2021-02-16 17:24:37 +05:00
parent ba16e05899
commit dc36d0bfe8
24 changed files with 102 additions and 122 deletions

View File

@@ -42,8 +42,8 @@ class Command(BaseCommand):
list_with_id = by_web_id.get(web_id, None)
if list_with_id:
print(u"id: {} for web_id: {}".format(list_with_id['id'], web_id))
print(u"list name: {}".format(list_with_id['name']))
print("id: {} for web_id: {}".format(list_with_id['id'], web_id))
print("list name: {}".format(list_with_id['name']))
else:
print(u"list with web_id: {} not found.".format(web_id))
print(f"list with web_id: {web_id} not found.")
sys.exit(1)

View File

@@ -10,8 +10,6 @@ import random
from collections import namedtuple
from itertools import chain
import six
from six.moves import range
from django.core.management.base import BaseCommand
from mailsnake import MailSnake
from opaque_keys.edx.keys import CourseKey
@@ -59,7 +57,7 @@ class Command(BaseCommand):
course_id = options['course_id']
num_segments = options['num_segments']
log.info(u'Syncronizing email list for %s', course_id)
log.info('Syncronizing email list for %s', course_id)
mailchimp = connect_mailchimp(key)
@@ -83,7 +81,7 @@ class Command(BaseCommand):
unsubscribe(mailchimp, list_id, non_enrolled_emails)
subscribed = subscribed.union(set(d['EMAIL'] for d in to_subscribe))
subscribed = subscribed.union({d['EMAIL'] for d in to_subscribe})
make_segments(mailchimp, list_id, num_segments, subscribed)
@@ -111,7 +109,7 @@ def verify_list(mailchimp, list_id, course_id):
list_name = lists[0]['name']
log.debug(u'list name: %s', list_name)
log.debug('list name: %s', list_name)
# check that we are connecting to the correct list
parts = course_id.replace('_', ' ').replace('/', ' ').split()
@@ -246,7 +244,7 @@ def update_merge_tags(mailchimp, list_id, tag_names):
The purpose of this function is unclear.
"""
mc_vars = mailchimp.listMergeVars(id=list_id)
mc_names = set(v['name'] for v in mc_vars)
mc_names = {v['name'] for v in mc_vars}
mc_merge = mailchimp.listMergeVarAdd
@@ -288,7 +286,7 @@ def subscribe_with_data(mailchimp, list_id, user_data):
Returns None
"""
format_entry = lambda e: {name_to_tag(k): v for k, v in six.iteritems(e)}
format_entry = lambda e: {name_to_tag(k): v for k, v in e.items()}
formated_data = list(format_entry(e) for e in user_data)
# send the updates in batches of a fixed size
@@ -299,7 +297,7 @@ def subscribe_with_data(mailchimp, list_id, user_data):
update_existing=True)
log.debug(
u"Added: %s Error on: %s", result['add_count'], result['error_count']
"Added: %s Error on: %s", result['add_count'], result['error_count']
)
@@ -334,7 +332,7 @@ def make_segments(mailchimp, list_id, count, emails):
# create segments and add emails
for seg in range(count):
name = 'random_{0:002}'.format(seg)
name = f'random_{seg:002}'
seg_id = mailchimp.listStaticSegmentAdd(id=list_id, name=name)
for batch in chunk(chunks[seg], BATCH_SIZE):
mailchimp.listStaticSegmentMembersAdd(

View File

@@ -17,7 +17,7 @@ class AppVersionConfigAdmin(admin.ModelAdmin):
fields = ('platform', 'version', 'expire_at', 'enabled')
list_filter = ['platform']
class Meta(object):
class Meta:
ordering = ['-major_version', '-minor_version', '-patch_version']
def get_list_display(self, __):

View File

@@ -6,7 +6,6 @@ Tests for course_info
import ddt
from django.conf import settings
from milestones.tests.utils import MilestonesTestCaseMixin
from six.moves import range
from lms.djangoapps.mobile_api.testutils import MobileAPITestCase, MobileAuthTestMixin, MobileCourseAccessTestMixin
from lms.djangoapps.mobile_api.utils import API_V1, API_V05
@@ -24,7 +23,7 @@ class TestUpdates(MobileAPITestCase, MobileAuthTestMixin, MobileCourseAccessTest
REVERSE_INFO = {'name': 'course-updates-list', 'params': ['course_id', 'api_version']}
def verify_success(self, response):
super(TestUpdates, self).verify_success(response) # lint-amnesty, pylint: disable=super-with-arguments
super().verify_success(response)
assert response.data == []
@ddt.data(
@@ -67,7 +66,7 @@ class TestUpdates(MobileAPITestCase, MobileAuthTestMixin, MobileCourseAccessTest
# old format stores the updates with the newest first
for num in range(num_updates, 0, -1):
update_data += "<li><h2>Date" + str(num) + "</h2><a href=\"/static/\">Update" + str(num) + "</a></li>"
course_updates.data = u"<ol>" + update_data + "</ol>"
course_updates.data = "<ol>" + update_data + "</ol>"
modulestore().update_item(course_updates, self.user.id)
# call API

View File

@@ -10,12 +10,12 @@ from .views import CourseHandoutsList, CourseUpdatesList
urlpatterns = [
url(
r'^{}/handouts$'.format(settings.COURSE_ID_PATTERN),
fr'^{settings.COURSE_ID_PATTERN}/handouts$',
CourseHandoutsList.as_view(),
name='course-handouts-list'
),
url(
r'^{}/updates$'.format(settings.COURSE_ID_PATTERN),
fr'^{settings.COURSE_ID_PATTERN}/updates$',
CourseUpdatesList.as_view(),
name='course-updates-list'
),

View File

@@ -6,9 +6,9 @@ Views for course info API
from rest_framework import generics
from rest_framework.response import Response
from common.djangoapps.static_replace import make_static_urls_absolute
from lms.djangoapps.courseware.courses import get_course_info_section_module
from openedx.core.lib.xblock_utils import get_course_update_items
from common.djangoapps.static_replace import make_static_urls_absolute
from ..decorators import mobile_course_access, mobile_view

View File

@@ -10,7 +10,6 @@ from django.core.cache import cache
from django.http import HttpResponse
from django.utils.deprecation import MiddlewareMixin
from pytz import UTC
import six
from lms.djangoapps.mobile_api.mobile_platform import MobilePlatform
from lms.djangoapps.mobile_api.models import AppVersionConfig
@@ -79,7 +78,7 @@ class AppVersionUpgrade(MiddlewareMixin):
Returns:
string: Cache key to be used.
"""
return "mobile_api.app_version_upgrade.{}.{}".format(field, key)
return f"mobile_api.app_version_upgrade.{field}.{key}"
def _get_version_info(self, request):
"""
@@ -112,7 +111,7 @@ class AppVersionUpgrade(MiddlewareMixin):
request_cache_dict[self.LAST_SUPPORTED_DATE_HEADER] = last_supported_date
latest_version = cached_data.get(latest_version_cache_key)
if not (latest_version and isinstance(latest_version, six.text_type)):
if not (latest_version and isinstance(latest_version, str)):
latest_version = self._get_latest_version(platform.NAME)
cache.set(latest_version_cache_key, latest_version, self.CACHE_TIMEOUT)
request_cache_dict[self.LATEST_VERSION_HEADER] = latest_version

View File

@@ -1,6 +1,3 @@
# -*- coding: utf-8 -*-
import django.db.models.deletion
from django.conf import settings
from django.db import migrations, models
@@ -19,7 +16,7 @@ class Migration(migrations.Migration):
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
('change_date', models.DateTimeField(auto_now_add=True, verbose_name='Change date')),
('enabled', models.BooleanField(default=False, verbose_name='Enabled')),
('video_profiles', models.TextField(help_text=u'A comma-separated list of names of profiles to include for videos returned from the mobile API.', blank=True)),
('video_profiles', models.TextField(help_text='A comma-separated list of names of profiles to include for videos returned from the mobile API.', blank=True)),
('changed_by', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, editable=False, to=settings.AUTH_USER_MODEL, null=True, verbose_name='Changed by')),
],
options={

View File

@@ -1,6 +1,3 @@
# -*- coding: utf-8 -*-
from django.db import migrations, models
@@ -15,12 +12,12 @@ class Migration(migrations.Migration):
name='AppVersionConfig',
fields=[
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
('platform', models.CharField(max_length=50, choices=[(u'Android', u'Android'), (u'iOS', u'iOS')])),
('version', models.CharField(help_text=u'Version should be in the format X.X.X.Y where X is a number and Y is alphanumeric', max_length=50)),
('platform', models.CharField(max_length=50, choices=[('Android', 'Android'), ('iOS', 'iOS')])),
('version', models.CharField(help_text='Version should be in the format X.X.X.Y where X is a number and Y is alphanumeric', max_length=50)),
('major_version', models.IntegerField()),
('minor_version', models.IntegerField()),
('patch_version', models.IntegerField()),
('expire_at', models.DateTimeField(null=True, verbose_name=u'Expiry date for platform version', blank=True)),
('expire_at', models.DateTimeField(null=True, verbose_name='Expiry date for platform version', blank=True)),
('enabled', models.BooleanField(default=True)),
('created_at', models.DateTimeField(auto_now_add=True)),
('updated_at', models.DateTimeField(auto_now=True)),
@@ -31,6 +28,6 @@ class Migration(migrations.Migration):
),
migrations.AlterUniqueTogether(
name='appversionconfig',
unique_together=set([('platform', 'version')]),
unique_together={('platform', 'version')},
),
]

View File

@@ -1,6 +1,3 @@
# -*- coding: utf-8 -*-
import django.db.models.deletion
from django.conf import settings
from django.db import migrations, models

View File

@@ -6,10 +6,8 @@ Platform related Operations for Mobile APP
import abc
import re
import six
class MobilePlatform(six.with_metaclass(abc.ABCMeta)):
class MobilePlatform(metaclass=abc.ABCMeta):
"""
MobilePlatform class creates an instance of platform based on user agent and supports platform
related operations.
@@ -58,14 +56,14 @@ class IOS(MobilePlatform):
""" iOS platform """
USER_AGENT_REGEX = (r'\((?P<version>[0-9]+.[0-9]+.[0-9]+(\.[0-9a-zA-Z]*)?); OS Version [0-9.]+ '
r'\(Build [0-9a-zA-Z]*\)\)')
NAME = u"iOS"
NAME = "iOS"
class Android(MobilePlatform):
""" Android platform """
USER_AGENT_REGEX = (r'Dalvik/[.0-9]+ \(Linux; U; Android [.0-9]+; (.*) (Build|MIUI)/[0-9a-zA-Z-.]*\) '
r'(.*)/(?P<version>[0-9]+.[0-9]+.[0-9]+(\.[0-9a-zA-Z]*)?)')
NAME = u"Android"
NAME = "Android"
# a list of all supported mobile platforms

View File

@@ -22,10 +22,10 @@ class MobileApiConfig(ConfigurationModel):
"""
video_profiles = models.TextField(
blank=True,
help_text=u"A comma-separated list of names of profiles to include for videos returned from the mobile API."
help_text="A comma-separated list of names of profiles to include for videos returned from the mobile API."
)
class Meta(object):
class Meta:
app_label = "mobile_api"
@classmethod
@@ -51,12 +51,12 @@ class AppVersionConfig(models.Model):
version = models.CharField(
max_length=50,
blank=False,
help_text=u"Version should be in the format X.X.X.Y where X is a number and Y is alphanumeric"
help_text="Version should be in the format X.X.X.Y where X is a number and Y is alphanumeric"
)
major_version = models.IntegerField()
minor_version = models.IntegerField()
patch_version = models.IntegerField()
expire_at = models.DateTimeField(null=True, blank=True, verbose_name=u"Expiry date for platform version")
expire_at = models.DateTimeField(null=True, blank=True, verbose_name="Expiry date for platform version")
enabled = models.BooleanField(default=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
@@ -67,7 +67,7 @@ class AppVersionConfig(models.Model):
ordering = ['-major_version', '-minor_version', '-patch_version']
def __str__(self):
return "{}_{}".format(self.platform, self.version)
return f"{self.platform}_{self.version}"
@classmethod
def latest_version(cls, platform):
@@ -88,7 +88,7 @@ class AppVersionConfig(models.Model):
def save(self, *args, **kwargs): # lint-amnesty, pylint: disable=signature-differs
""" parses version into major, minor and patch versions before saving """
self.major_version, self.minor_version, self.patch_version = utils.parsed_version(self.version)
super(AppVersionConfig, self).save(*args, **kwargs) # lint-amnesty, pylint: disable=super-with-arguments
super().save(*args, **kwargs)
class IgnoreMobileAvailableFlagConfig(ConfigurationModel):
@@ -102,5 +102,5 @@ class IgnoreMobileAvailableFlagConfig(ConfigurationModel):
.. no_pii:
"""
class Meta(object):
class Meta:
app_label = "mobile_api"

View File

@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
"""
Tests for mobile API utilities.
"""

View File

@@ -4,9 +4,9 @@ Tests for Version Based App Upgrade Middleware
from datetime import datetime
from unittest import mock
import ddt
import mock
from django.core.cache import caches
from django.http import HttpRequest, HttpResponse
from pytz import UTC
@@ -25,7 +25,7 @@ class TestAppVersionUpgradeMiddleware(CacheIsolationTestCase):
ENABLED_CACHES = ['default']
def setUp(self):
super(TestAppVersionUpgradeMiddleware, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
super().setUp()
self.middleware = AppVersionUpgrade()
self.set_app_version_config()

View File

@@ -3,19 +3,19 @@ Milestone related tests for the mobile_api
"""
import six
from unittest.mock import patch
from crum import set_current_request
from django.conf import settings
from mock import patch
from common.djangoapps.util.milestones_helpers import add_prerequisite_course, fulfill_course_milestone
from lms.djangoapps.courseware.access_response import MilestoneAccessError
from lms.djangoapps.courseware.tests.test_entrance_exam import add_entrance_exam_milestone, answer_entrance_exam_problem
from openedx.core.djangolib.testing.utils import get_mock_request
from common.djangoapps.util.milestones_helpers import add_prerequisite_course, fulfill_course_milestone
from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory
class MobileAPIMilestonesMixin(object):
class MobileAPIMilestonesMixin:
"""
Tests the Mobile API decorators for milestones.
@@ -114,7 +114,7 @@ class MobileAPIMilestonesMixin(object):
add_entrance_exam_milestone(self.course, self.entrance_exam)
self.course.entrance_exam_minimum_score_pct = 0.50
self.course.entrance_exam_id = six.text_type(self.entrance_exam.location)
self.course.entrance_exam_id = str(self.entrance_exam.location)
self.store.update_item(self.course, self.user.id)
def _add_prerequisite_course(self):

View File

@@ -96,13 +96,13 @@ class TestMobileApiConfig(TestCase):
"""Check that video_profiles config is returned in order as a list"""
MobileApiConfig(video_profiles="mobile_low,mobile_high,youtube").save()
video_profile_list = MobileApiConfig.get_video_profiles()
assert video_profile_list == [u'mobile_low', u'mobile_high', u'youtube']
assert video_profile_list == ['mobile_low', 'mobile_high', 'youtube']
def test_video_profile_list_with_whitespace(self):
"""Check video_profiles config with leading and trailing whitespace"""
MobileApiConfig(video_profiles=" mobile_low , mobile_high,youtube ").save()
video_profile_list = MobileApiConfig.get_video_profiles()
assert video_profile_list == [u'mobile_low', u'mobile_high', u'youtube']
assert video_profile_list == ['mobile_low', 'mobile_high', 'youtube']
def test_empty_video_profile(self):
"""Test an empty video_profile"""

View File

@@ -13,24 +13,23 @@ Test utilities for mobile API tests:
import datetime
from unittest.mock import patch
import ddt
import pytz
import six
from django.conf import settings
from django.urls import reverse
from django.utils import timezone
from mock import patch
from opaque_keys.edx.keys import CourseKey
from rest_framework.test import APITestCase
from common.djangoapps.student import auth
from common.djangoapps.student.models import CourseEnrollment
from lms.djangoapps.courseware.access_response import MobileAvailabilityError, StartDateError, VisibilityError
from lms.djangoapps.courseware.tests.factories import UserFactory
from lms.djangoapps.mobile_api.models import IgnoreMobileAvailableFlagConfig
from lms.djangoapps.mobile_api.tests.test_milestones import MobileAPIMilestonesMixin
from lms.djangoapps.mobile_api.utils import API_V1
from common.djangoapps.student import auth
from common.djangoapps.student.models import CourseEnrollment
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
from xmodule.modulestore.tests.factories import CourseFactory
@@ -43,7 +42,7 @@ class MobileAPITestCase(ModuleStoreTestCase, APITestCase):
They may also override any of the methods defined in this class to control the behavior of the TestMixins.
"""
def setUp(self):
super(MobileAPITestCase, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
super().setUp()
self.course = CourseFactory.create(
mobile_available=True,
static_asset_path="needed_for_split",
@@ -57,7 +56,7 @@ class MobileAPITestCase(ModuleStoreTestCase, APITestCase):
IgnoreMobileAvailableFlagConfig(enabled=False).save()
def tearDown(self):
super(MobileAPITestCase, self).tearDown() # lint-amnesty, pylint: disable=super-with-arguments
super().tearDown()
self.logout()
def login(self):
@@ -96,7 +95,7 @@ class MobileAPITestCase(ModuleStoreTestCase, APITestCase):
"""Base implementation that returns URL for endpoint that's being tested."""
reverse_args = reverse_args or {}
if 'course_id' in self.REVERSE_INFO['params']:
reverse_args.update({'course_id': six.text_type(kwargs.get('course_id', self.course.id))})
reverse_args.update({'course_id': str(kwargs.get('course_id', self.course.id))})
if 'username' in self.REVERSE_INFO['params']:
reverse_args.update({'username': kwargs.get('username', self.user.username)})
if 'api_version' in self.REVERSE_INFO['params']:
@@ -108,7 +107,7 @@ class MobileAPITestCase(ModuleStoreTestCase, APITestCase):
return self.client.get(url, data=data)
class MobileAuthTestMixin(object):
class MobileAuthTestMixin:
"""
Test Mixin for testing APIs decorated with mobile_view.
"""

View File

@@ -3,15 +3,14 @@ Serializer for user API
"""
import six
from rest_framework import serializers
from rest_framework.reverse import reverse
from lms.djangoapps.courseware.access import has_access
from lms.djangoapps.certificates.api import certificate_downloadable_status
from openedx.features.course_duration_limits.access import get_user_course_expiration_date
from common.djangoapps.student.models import CourseEnrollment, User
from common.djangoapps.util.course import get_encoded_course_sharing_utm_params, get_link_for_about_page
from lms.djangoapps.certificates.api import certificate_downloadable_status
from lms.djangoapps.courseware.access import has_access
from openedx.features.course_duration_limits.access import get_user_course_expiration_date
class CourseOverviewField(serializers.RelatedField): # lint-amnesty, pylint: disable=abstract-method
@@ -19,7 +18,7 @@ class CourseOverviewField(serializers.RelatedField): # lint-amnesty, pylint: di
Custom field to wrap a CourseOverview object. Read-only.
"""
def to_representation(self, course_overview): # lint-amnesty, pylint: disable=arguments-differ
course_id = six.text_type(course_overview.id)
course_id = str(course_overview.id)
request = self.context.get('request')
api_version = self.context.get('api_version')
enrollment = CourseEnrollment.get_enrollment(user=self.context.get('request').user, course_key=course_id)
@@ -111,7 +110,7 @@ class CourseEnrollmentSerializer(serializers.ModelSerializer):
else:
return {}
class Meta(object):
class Meta:
model = CourseEnrollment
fields = ('audit_access_expires', 'created', 'mode', 'is_active', 'course', 'certificate')
lookup_field = 'username'
@@ -122,7 +121,7 @@ class CourseEnrollmentSerializerv05(CourseEnrollmentSerializer):
Serializes CourseEnrollment models for v0.5 api
Does not include 'audit_access_expires' field that is present in v1 api
"""
class Meta(object):
class Meta:
model = CourseEnrollment
fields = ('created', 'mode', 'is_active', 'course', 'certificate')
lookup_field = 'username'
@@ -145,7 +144,7 @@ class UserSerializer(serializers.ModelSerializer):
request=request
)
class Meta(object):
class Meta:
model = User
fields = ('id', 'username', 'email', 'name', 'course_enrollments')
lookup_field = 'username'

View File

@@ -4,10 +4,11 @@ Tests for users API
import datetime
from unittest.mock import patch
from urllib.parse import parse_qs
import ddt
import pytz
import six
from completion.test_utils import CompletionWaffleTestMixin, submit_completions_for_testing
from django.conf import settings
from django.template import defaultfilters
@@ -15,15 +16,16 @@ from django.test import RequestFactory, override_settings
from django.utils import timezone
from django.utils.timezone import now
from milestones.tests.utils import MilestonesTestCaseMixin
from mock import patch
from six.moves import range
from six.moves.urllib.parse import parse_qs
from common.djangoapps.course_modes.models import CourseMode
from lms.djangoapps.courseware.access_response import MilestoneAccessError, StartDateError, VisibilityError
from common.djangoapps.student.models import CourseEnrollment
from common.djangoapps.student.tests.factories import CourseEnrollmentFactory
from common.djangoapps.util.milestones_helpers import set_prerequisite_courses
from common.djangoapps.util.testing import UrlResetMixin
from lms.djangoapps.certificates.api import generate_user_certificates
from lms.djangoapps.certificates.models import CertificateStatuses
from lms.djangoapps.certificates.tests.factories import GeneratedCertificateFactory
from lms.djangoapps.courseware.access_response import MilestoneAccessError, StartDateError, VisibilityError
from lms.djangoapps.grades.tests.utils import mock_passing_grade
from lms.djangoapps.mobile_api.testutils import (
MobileAPITestCase,
@@ -36,10 +38,6 @@ from openedx.core.djangoapps.schedules.tests.factories import ScheduleFactory
from openedx.core.lib.courses import course_image_url
from openedx.features.course_duration_limits.models import CourseDurationLimitConfig
from openedx.features.course_experience.tests.views.helpers import add_course_mode
from common.djangoapps.student.models import CourseEnrollment
from common.djangoapps.student.tests.factories import CourseEnrollmentFactory
from common.djangoapps.util.milestones_helpers import set_prerequisite_courses
from common.djangoapps.util.testing import UrlResetMixin
from xmodule.course_module import DEFAULT_START_DATE
from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory
@@ -118,13 +116,13 @@ class TestUserEnrollmentApi(UrlResetMixin, MobileAPITestCase, MobileAuthUserTest
@patch.dict(settings.FEATURES, {"ENABLE_DISCUSSION_SERVICE": True})
def setUp(self):
super(TestUserEnrollmentApi, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
super().setUp()
def verify_success(self, response):
"""
Verifies user course enrollment response for success
"""
super(TestUserEnrollmentApi, self).verify_success(response) # lint-amnesty, pylint: disable=super-with-arguments
super().verify_success(response)
courses = response.data
assert len(courses) == 1
@@ -132,7 +130,7 @@ class TestUserEnrollmentApi(UrlResetMixin, MobileAPITestCase, MobileAuthUserTest
assert 'courses/{}/about'.format(self.course.id) in found_course['course_about']
assert 'course_info/{}/updates'.format(self.course.id) in found_course['course_updates']
assert 'course_info/{}/handouts'.format(self.course.id) in found_course['course_handouts']
assert found_course['id'] == six.text_type(self.course.id)
assert found_course['id'] == str(self.course.id)
assert courses[0]['mode'] == CourseMode.DEFAULT_MODE_SLUG
assert courses[0]['course']['subscription_id'] == self.course.clean_id(padding_char='_')
@@ -161,7 +159,7 @@ class TestUserEnrollmentApi(UrlResetMixin, MobileAPITestCase, MobileAuthUserTest
response = self.api_response(api_version=api_version)
for course_index in range(num_courses):
assert response.data[course_index]['course']['id'] ==\
six.text_type(courses[((num_courses - course_index) - 1)].id)
str(courses[((num_courses - course_index) - 1)].id)
@ddt.data(API_V05, API_V1)
@patch.dict(settings.FEATURES, {
@@ -174,7 +172,7 @@ class TestUserEnrollmentApi(UrlResetMixin, MobileAPITestCase, MobileAuthUserTest
course_with_prereq = CourseFactory.create(start=self.LAST_WEEK, mobile_available=True)
prerequisite_course = CourseFactory.create()
set_prerequisite_courses(course_with_prereq.id, [six.text_type(prerequisite_course.id)])
set_prerequisite_courses(course_with_prereq.id, [str(prerequisite_course.id)])
# Create list of courses with various expected courseware_access responses and corresponding expected codes
courses = [
@@ -423,7 +421,7 @@ class CourseStatusAPITestCase(MobileAPITestCase):
"""
Creates a basic course structure for our course
"""
super(CourseStatusAPITestCase, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
super().setUp()
self.section = ItemFactory.create(
parent=self.course,
@@ -456,8 +454,8 @@ class TestCourseStatusGET(CourseStatusAPITestCase, MobileAuthUserTestMixin,
self.login_and_enroll()
response = self.api_response(api_version=API_V05)
assert response.data['last_visited_module_id'] == six.text_type(self.sub_section.location)
assert response.data['last_visited_module_path'] == [six.text_type(module.location) for module in
assert response.data['last_visited_module_id'] == str(self.sub_section.location)
assert response.data['last_visited_module_path'] == [str(module.location) for module in
[self.sub_section, self.section, self.course]]
def test_success_v1(self):
@@ -465,7 +463,7 @@ class TestCourseStatusGET(CourseStatusAPITestCase, MobileAuthUserTestMixin,
self.login_and_enroll()
submit_completions_for_testing(self.user, [self.unit.location])
response = self.api_response(api_version=API_V1)
assert response.data['last_visited_block_id'] == six.text_type(self.unit.location)
assert response.data['last_visited_block_id'] == str(self.unit.location)
class TestCourseStatusPATCH(CourseStatusAPITestCase, MobileAuthUserTestMixin,
@@ -479,8 +477,8 @@ class TestCourseStatusPATCH(CourseStatusAPITestCase, MobileAuthUserTestMixin,
def test_success(self):
self.login_and_enroll()
response = self.api_response(data={"last_visited_module_id": six.text_type(self.other_unit.location)})
assert response.data['last_visited_module_id'] == six.text_type(self.other_sub_section.location)
response = self.api_response(data={"last_visited_module_id": str(self.other_unit.location)})
assert response.data['last_visited_module_id'] == str(self.other_sub_section.location)
def test_invalid_module(self):
self.login_and_enroll()
@@ -498,7 +496,7 @@ class TestCourseStatusPATCH(CourseStatusAPITestCase, MobileAuthUserTestMixin,
past_date = datetime.datetime.now()
response = self.api_response(
data={
"last_visited_module_id": six.text_type(self.other_unit.location),
"last_visited_module_id": str(self.other_unit.location),
"modification_date": past_date.isoformat()
},
expected_response_code=400
@@ -513,16 +511,16 @@ class TestCourseStatusPATCH(CourseStatusAPITestCase, MobileAuthUserTestMixin,
self.login_and_enroll()
# save something so we have an initial date
self.api_response(data={"last_visited_module_id": six.text_type(initial_unit.location)})
self.api_response(data={"last_visited_module_id": str(initial_unit.location)})
# now actually update it
response = self.api_response(
data={
"last_visited_module_id": six.text_type(update_unit.location),
"last_visited_module_id": str(update_unit.location),
"modification_date": date.isoformat()
}
)
assert response.data['last_visited_module_id'] == six.text_type(expected_subsection.location)
assert response.data['last_visited_module_id'] == str(expected_subsection.location)
def test_old_date(self):
self.login_and_enroll()
@@ -538,11 +536,11 @@ class TestCourseStatusPATCH(CourseStatusAPITestCase, MobileAuthUserTestMixin,
self.login_and_enroll()
response = self.api_response(
data={
"last_visited_module_id": six.text_type(self.other_unit.location),
"last_visited_module_id": str(self.other_unit.location),
"modification_date": timezone.now().isoformat()
}
)
assert response.data['last_visited_module_id'] == six.text_type(self.other_sub_section.location)
assert response.data['last_visited_module_id'] == str(self.other_sub_section.location)
def test_invalid_date(self):
self.login_and_enroll()
@@ -560,7 +558,7 @@ class TestCourseEnrollmentSerializer(MobileAPITestCase, MilestonesTestCaseMixin)
ENABLED_SIGNALS = ['course_published']
def setUp(self):
super(TestCourseEnrollmentSerializer, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
super().setUp()
self.login_and_enroll()
self.request = RequestFactory().get('/')
self.request.user = self.user

View File

@@ -15,7 +15,7 @@ urlpatterns = [
UserCourseEnrollmentsList.as_view(),
name='courseenrollment-detail'
),
url('^{}/course_status_info/{}'.format(settings.USERNAME_PATTERN, settings.COURSE_ID_PATTERN),
url(f'^{settings.USERNAME_PATTERN}/course_status_info/{settings.COURSE_ID_PATTERN}',
UserCourseStatus.as_view(),
name='user-course-status')
]

View File

@@ -3,9 +3,9 @@ Views for user API
"""
import six
from completion.utilities import get_key_to_last_completed_block
from completion.exceptions import UnavailableCompletionData
from completion.utilities import get_key_to_last_completed_block
from django.contrib.auth.models import User # lint-amnesty, pylint: disable=imported-auth-user
from django.contrib.auth.signals import user_logged_in
from django.shortcuts import redirect
from django.utils import dateparse
@@ -16,17 +16,16 @@ from rest_framework.decorators import api_view
from rest_framework.response import Response
from xblock.fields import Scope
from xblock.runtime import KeyValueStore
from django.contrib.auth.models import User # lint-amnesty, pylint: disable=imported-auth-user
from common.djangoapps.student.models import CourseEnrollment, User # lint-amnesty, pylint: disable=reimported
from lms.djangoapps.courseware.access import is_mobile_available_for_user
from lms.djangoapps.courseware.access_utils import ACCESS_GRANTED
from lms.djangoapps.courseware.courses import get_current_child
from lms.djangoapps.courseware.model_data import FieldDataCache
from lms.djangoapps.courseware.module_render import get_module_for_descriptor
from lms.djangoapps.courseware.views.index import save_positions_recursively_up
from lms.djangoapps.courseware.access_utils import ACCESS_GRANTED
from lms.djangoapps.mobile_api.utils import API_V05, API_V1
from lms.djangoapps.mobile_api.utils import API_V1, API_V05
from openedx.features.course_duration_limits.access import check_course_expired
from common.djangoapps.student.models import CourseEnrollment, User # lint-amnesty, pylint: disable=reimported
from xmodule.modulestore.django import modulestore
from xmodule.modulestore.exceptions import ItemNotFoundError
@@ -72,7 +71,7 @@ class UserDetail(generics.RetrieveAPIView):
lookup_field = 'username'
def get_serializer_context(self):
context = super(UserDetail, self).get_serializer_context() # lint-amnesty, pylint: disable=super-with-arguments
context = super().get_serializer_context()
context['api_version'] = self.kwargs.get('api_version')
return context
@@ -152,7 +151,7 @@ class UserCourseStatus(views.APIView):
Returns the course status
"""
path = self._last_visited_module_path(request, course)
path_ids = [six.text_type(module.location) for module in path]
path_ids = [str(module.location) for module in path]
return Response({
"last_visited_module_id": path_ids[0],
"last_visited_module_path": path_ids,
@@ -312,7 +311,7 @@ class UserCourseEnrollmentsList(generics.ListAPIView):
return check_org is None or (check_org.lower() == course_org.lower())
def get_serializer_context(self):
context = super(UserCourseEnrollmentsList, self).get_serializer_context() # lint-amnesty, pylint: disable=super-with-arguments
context = super().get_serializer_context()
context['api_version'] = self.kwargs.get('api_version')
return context

View File

@@ -1,7 +1,6 @@
"""
Common utility methods for Mobile APIs.
"""
from six.moves import map
API_V05 = 'v0.5'
API_V1 = 'v1'

View File

@@ -18,6 +18,7 @@ Or for more details::
"""
import csv
import click
@@ -54,7 +55,7 @@ def main(unmapped_csv):
Script removes duplicates in addition to providing sorted list of plain app names.
"""
with open(unmapped_csv, 'r') as file:
with open(unmapped_csv) as file:
csv_data = file.read()
reader = csv.DictReader(csv_data.splitlines())

View File

@@ -12,10 +12,11 @@ Or for more details::
"""
import csv
import click
import os
import re
import click
# Maps edx-platform installed Django apps to the edx repo that contains
# the app code.
EDX_REPO_APPS = {
@@ -113,10 +114,10 @@ def main(repo_csv, app_csv, dep_csv):
print('# Do not hand edit CODE_OWNER_MAPPINGS. Generated by {}'.format(os.path.basename(__file__)))
print('CODE_OWNER_MAPPINGS:')
for owner, path_list in sorted(owner_to_paths_map.items()):
print(" {}:".format(owner))
print(f" {owner}:")
path_list.sort()
for path in path_list:
print(" - {}".format(path))
print(f" - {path}")
owner_with_mappings_set = set(owner_to_paths_map.keys())
print('# Do not hand edit CODE_OWNER_THEMES. Generated by {}'.format(os.path.basename(__file__)))
@@ -126,10 +127,10 @@ def main(repo_csv, app_csv, dep_csv):
# only include the theme's list of owners that have mappings
theme_owner_with_mappings_list = list(theme_owner_set & owner_with_mappings_set)
if theme_owner_with_mappings_list:
print(" {}:".format(theme))
print(f" {theme}:")
theme_owner_with_mappings_list.sort()
for owner in theme_owner_with_mappings_list:
print(" - {}".format(owner))
print(f" - {owner}")
def _map_repo_apps(csv_type, repo_csv, app_to_repo_map, owner_map, owner_to_paths_map):
@@ -144,7 +145,7 @@ def _map_repo_apps(csv_type, repo_csv, app_to_repo_map, owner_map, owner_to_path
owner_to_paths_map (dict): Holds results mapping owner to paths
"""
with open(repo_csv, 'r') as file:
with open(repo_csv) as file:
csv_data = file.read()
reader = csv.DictReader(csv_data.splitlines())
@@ -160,14 +161,14 @@ def _map_repo_apps(csv_type, repo_csv, app_to_repo_map, owner_map, owner_to_path
owner_to_paths_map[owner] = []
owner_to_paths_map[owner].append(app)
else:
print('WARNING: Repo {} was not found in {} csv. Needed for app {}.'.format(repo_url, csv_type, app))
print(f'WARNING: Repo {repo_url} was not found in {csv_type} csv. Needed for app {app}.')
def _map_edx_platform_apps(app_csv, owner_map, owner_to_paths_map):
"""
Reads CSV of edx-platform app ownership and updates mappings
"""
with open(app_csv, 'r') as file:
with open(app_csv) as file:
csv_data = file.read()
reader = csv.DictReader(csv_data.splitlines())
for row in reader:
@@ -215,7 +216,7 @@ def _get_and_map_code_owner(row, owner_map):
if theme:
theme = theme.lower()
owner = '{}-{}'.format(theme, squad) if theme else squad
owner = f'{theme}-{squad}' if theme else squad
theme = theme or squad
if squad not in owner_map['squad_to_theme_map']: