Skip to content

Commit

Permalink
Post Python 3.8 Clean Up Changes (openedx-unsupported#405)
Browse files Browse the repository at this point in the history
  • Loading branch information
M. Zulqarnain authored Oct 14, 2020
1 parent e91778f commit ed46fd1
Show file tree
Hide file tree
Showing 67 changed files with 329 additions and 460 deletions.
12 changes: 5 additions & 7 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,15 @@ script:
&& make $TARGETS "
matrix:
include:
- python: 3.5
env: TESTNAME=quality-python-3.5 TARGETS="PYTHON_ENV=py35 quality"
- python: 3.5
env: TESTNAME=test-python-3.5 TARGETS="PYTHON_ENV=py35 test"
after_success:
- docker exec analytics_api_testing /edx/app/analytics_api/analytics_api/.travis/run_coverage.sh
- codecov --disable pycov
- python: 3.8
env: TESTNAME=quality-python-3.8 TARGETS="PYTHON_ENV=py38 quality"
- python: 3.8
env: TESTNAME=test-python-3.8 TARGETS="PYTHON_ENV=py38 test"
- python: 3.8
env: TESTNAME=test-python-3.8-django-3.0 TARGETS="PYTHON_ENV=py38 DJANGO_VERSION=django30 test"
after_success:
- docker exec analytics_api_testing /edx/app/analytics_api/analytics_api/.travis/run_coverage.sh
- codecov --disable pycov
env:
global:
- DOCKER_USERNAME=edxbuilder
Expand Down
5 changes: 2 additions & 3 deletions analytics_data_api/constants/country.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,16 @@

from collections import namedtuple

import six
from django_countries import countries

Country = namedtuple('Country', 'name, alpha2, alpha3, numeric')

UNKNOWN_COUNTRY_CODE = u'UNKNOWN'
UNKNOWN_COUNTRY_CODE = 'UNKNOWN'
UNKNOWN_COUNTRY = Country(UNKNOWN_COUNTRY_CODE, None, None, None)


def _get_country_property(code, property_name):
return six.text_type(getattr(countries, property_name)(code))
return str(getattr(countries, property_name)(code))


def get_country(code):
Expand Down
2 changes: 0 additions & 2 deletions analytics_data_api/constants/engagement_types.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@


from analytics_data_api.constants.engagement_events import (
ATTEMPTED,
ATTEMPTS_PER_COMPLETED,
Expand Down
14 changes: 7 additions & 7 deletions analytics_data_api/constants/enrollment_modes.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
AUDIT = u'audit'
CREDIT = u'credit'
HONOR = u'honor'
PROFESSIONAL = u'professional'
PROFESSIONAL_NO_ID = u'no-id-professional'
VERIFIED = u'verified'
MASTERS = u'masters'
AUDIT = 'audit'
CREDIT = 'credit'
HONOR = 'honor'
PROFESSIONAL = 'professional'
PROFESSIONAL_NO_ID = 'no-id-professional'
VERIFIED = 'verified'
MASTERS = 'masters'

ALL = [AUDIT, CREDIT, HONOR, PROFESSIONAL, PROFESSIONAL_NO_ID, VERIFIED, MASTERS]
8 changes: 4 additions & 4 deletions analytics_data_api/constants/genders.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
FEMALE = u'female'
MALE = u'male'
OTHER = u'other'
UNKNOWN = u'unknown'
FEMALE = 'female'
MALE = 'male'
OTHER = 'other'
UNKNOWN = 'unknown'
ALL = [FEMALE, MALE, OTHER, UNKNOWN]
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@


from django.conf import settings
from django.core.management.base import BaseCommand, CommandError
from elasticsearch import Elasticsearch
Expand All @@ -19,7 +17,7 @@ def handle(self, *args, **options):

es = Elasticsearch([settings.ELASTICSEARCH_LEARNERS_HOST])
if es.indices.exists(settings.ELASTICSEARCH_LEARNERS_INDEX):
self.stderr.write('"{}" index already exists.'.format(settings.ELASTICSEARCH_LEARNERS_INDEX))
self.stderr.write(f'"{settings.ELASTICSEARCH_LEARNERS_INDEX}" index already exists.')
else:
es.indices.create(
index=settings.ELASTICSEARCH_LEARNERS_INDEX,
Expand Down Expand Up @@ -106,7 +104,7 @@ def handle(self, *args, **options):
)

if es.indices.exists(settings.ELASTICSEARCH_LEARNERS_UPDATE_INDEX):
self.stderr.write('"{}" index already exists.'.format(settings.ELASTICSEARCH_LEARNERS_UPDATE_INDEX))
self.stderr.write(f'"{settings.ELASTICSEARCH_LEARNERS_UPDATE_INDEX}" index already exists.')
else:
es.indices.create(
index=settings.ELASTICSEARCH_LEARNERS_UPDATE_INDEX,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@


from django.conf import settings
from django.core.management.base import BaseCommand
from elasticsearch import Elasticsearch
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,9 @@
import math
import random

import six
from django.conf import settings
from django.core.management.base import BaseCommand
from django.utils import timezone
from six.moves import range, zip # pylint: disable=ungrouped-imports
from tqdm import tqdm

from analytics_data_api.constants import engagement_events
Expand Down Expand Up @@ -133,36 +131,36 @@ def generate_daily_data(self, course_id, start_date, end_date):
daily_total = get_count(daily_total)
models.CourseEnrollmentDaily.objects.create(course_id=course_id, date=date, count=daily_total)

for mode, ratio in six.iteritems(enrollment_mode_ratios):
for mode, ratio in enrollment_mode_ratios.items():
count = int(ratio * daily_total)
cumulative_count = max(cumulative_count + 10, count)
models.CourseEnrollmentModeDaily.objects.create(course_id=course_id, date=date, count=count,
cumulative_count=cumulative_count, mode=mode)

for gender, ratio in six.iteritems(gender_ratios):
for gender, ratio in gender_ratios.items():
count = int(ratio * daily_total)
models.CourseEnrollmentByGender.objects.create(course_id=course_id, date=date, count=count,
gender=gender)

for education_level, ratio in six.iteritems(education_level_ratios):
for education_level, ratio in education_level_ratios.items():
count = int(ratio * daily_total)
models.CourseEnrollmentByEducation.objects.create(course_id=course_id, date=date, count=count,
education_level=education_level)

for country_code, ratio in six.iteritems(country_ratios):
for country_code, ratio in country_ratios.items():
count = int(ratio * daily_total)
models.CourseEnrollmentByCountry.objects.create(course_id=course_id, date=date, count=count,
country_code=country_code)

for birth_year, ratio in six.iteritems(birth_years):
for birth_year, ratio in birth_years.items():
count = int(ratio * daily_total)
models.CourseEnrollmentByBirthYear.objects.create(course_id=course_id, date=date, count=count,
birth_year=birth_year)

progress.update(1)
date = date + datetime.timedelta(days=1)

for index, (mode, ratio) in enumerate(six.iteritems(enrollment_mode_ratios)):
for index, (mode, ratio) in enumerate(enrollment_mode_ratios.items()):
count = int(ratio * daily_total)
pass_rate = min(random.normalvariate(.45 + (.1 * index), .15), 1.0)
cumulative_count = count + random.randint(0, 100)
Expand Down Expand Up @@ -245,7 +243,7 @@ def generate_learner_engagement_data(self, course_id, username, start_date, end_
count = random.randint(0, max_value / 20)
entity_type = metric.split('_', 1)[0]
event = metric.split('_', 1)[1]
entity_id = 'an-id-{}-{}'.format(entity_type, event)
entity_id = f'an-id-{entity_type}-{event}'
models.ModuleEngagement.objects.create(
course_id=course_id, username=username, date=current,
entity_type=entity_type, entity_id=entity_id, event=event, count=count)
Expand Down
2 changes: 1 addition & 1 deletion analytics_data_api/management/commands/set_api_key.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ def handle(self, *args, **options):

if options['delete_key']:
delete_user_auth_token(username)
print('Removed API key for user: <{0}>'.format(username))
print(f'Removed API key for user: <{username}>')
else:
if options['api_key'] is None:
raise CommandError("You must supply both a username and key.")
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

from django.core.management import call_command
from django.test import TestCase

Expand All @@ -12,7 +11,7 @@ def testNormalRun(self):

call_command(
'generate_fake_course_data',
"--num-weeks={weeks}".format(weeks=num_weeks),
f"--num-weeks={num_weeks}",
"--no-videos",
"--course-id", course_id
)
Expand Down
2 changes: 0 additions & 2 deletions analytics_data_api/management/utils.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@


from django.conf import settings


Expand Down
6 changes: 3 additions & 3 deletions analytics_data_api/renderers.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ def render(self, data, *args, **kwargs):
"""
if not isinstance(data, list):
data = data.get(self.results_field, [])
return super(ResultsOnlyRendererMixin, self).render(data, *args, **kwargs)
return super().render(data, *args, **kwargs)


class DynamicFieldsCsvRenderer(CSVRenderer):
Expand All @@ -46,7 +46,7 @@ class DynamicFieldsCsvRenderer(CSVRenderer):

def flatten_list(self, l):
if self.concatenate_lists_sep is None:
return super(DynamicFieldsCsvRenderer, self).flatten_list(l)
return super().flatten_list(l)
return {'': self.concatenate_lists_sep.join(l)}

def get_header(self, data, renderer_context):
Expand Down Expand Up @@ -88,7 +88,7 @@ def render(self, data, media_type=None, renderer_context=None, writer_opts=None)
"""Override the default "get headers" behaviour, then render the data."""
renderer_context = renderer_context or {}
self.header = self.get_header(data, renderer_context)
return super(DynamicFieldsCsvRenderer, self).render(data, media_type, renderer_context, writer_opts)
return super().render(data, media_type, renderer_context, writer_opts)


class PaginatedCsvRenderer(ResultsOnlyRendererMixin, DynamicFieldsCsvRenderer):
Expand Down
2 changes: 1 addition & 1 deletion analytics_data_api/tests/test_renderers.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
class PaginatedCsvRendererTests(TestCase):

def setUp(self):
super(PaginatedCsvRendererTests, self).setUp()
super().setUp()
self.renderer = PaginatedCsvRenderer()
self.data = {'results': [
{
Expand Down
2 changes: 0 additions & 2 deletions analytics_data_api/tests/test_utils.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@


import datetime

from django.contrib.auth.models import User
Expand Down
2 changes: 0 additions & 2 deletions analytics_data_api/urls.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@


from django.conf.urls import include, url
from rest_framework.urlpatterns import format_suffix_patterns

Expand Down
12 changes: 4 additions & 8 deletions analytics_data_api/utils.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,14 @@


import datetime
import re
from importlib import import_module

import six
from django.conf import settings
from django.core.exceptions import SuspiciousFileOperation, SuspiciousOperation
from django.core.files.storage import default_storage
from django.db.models import Q
from opaque_keys import InvalidKeyError
from opaque_keys.edx.locator import CourseKey
from rest_framework.authtoken.models import Token
from six.moves import zip # pylint: disable=ungrouped-imports

from analytics_data_api.v0.exceptions import CannotCreateReportDownloadLinkError, ReportFileNotFoundError

Expand All @@ -23,15 +19,15 @@ def get_filename_safe_course_id(course_id, replacement_char='_'):
"""
try:
course_key = CourseKey.from_string(course_id)
filename = six.text_type(replacement_char).join([course_key.org, course_key.course, course_key.run])
filename = str(replacement_char).join([course_key.org, course_key.course, course_key.run])
except InvalidKeyError:
# If the course_id doesn't parse, we will still return a value here.
filename = course_id

# The safest characters are A-Z, a-z, 0-9, <underscore>, <period> and <hyphen>.
# We represent the first four with \w.
# TODO: Once we support courses with unicode characters, we will need to revisit this.
return re.sub(r'[^\w\.\-]', six.text_type(replacement_char), filename)
return re.sub(r'[^\w\.\-]', str(replacement_char), filename)


def delete_user_auth_token(username):
Expand All @@ -57,7 +53,7 @@ def set_user_auth_token(user, key):
"""
# Check that no other user has the same key
if Token.objects.filter(~Q(user=user), key=key).exists():
raise AttributeError("The key {} is already in use by another user.".format(key))
raise AttributeError(f"The key {key} is already in use by another user.")

Token.objects.filter(user=user).delete()
Token.objects.create(user=user, key=key)
Expand Down Expand Up @@ -204,7 +200,7 @@ def get_file_object_url(filename, download_filename):
url = default_storage.url(
name=filename,
response_headers={
'response-content-disposition': 'attachment; filename={}'.format(download_filename),
'response-content-disposition': f'attachment; filename={download_filename}',
'response-content-type': 'text/csv',
# The Expires header requires a very particular timestamp format
'response-expires': expires_at.strftime('%a, %d %b %Y %H:%M:%S GMT')
Expand Down
4 changes: 1 addition & 3 deletions analytics_data_api/v0/apps.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@


from django.apps import AppConfig
from django.conf import settings
from elasticsearch_dsl import connections
Expand All @@ -12,7 +10,7 @@ class ApiAppConfig(AppConfig):
def ready(self):
from analytics_data_api.utils import load_fully_qualified_definition # pylint: disable=import-outside-toplevel

super(ApiAppConfig, self).ready()
super().ready()
if settings.ELASTICSEARCH_LEARNERS_HOST:
connection_params = {'hosts': [settings.ELASTICSEARCH_LEARNERS_HOST]}
if settings.ELASTICSEARCH_CONNECTION_CLASS:
Expand Down
6 changes: 2 additions & 4 deletions analytics_data_api/v0/connections.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@


import json
import time

Expand All @@ -17,7 +15,7 @@ class BotoHttpConnection(Connection):

def __init__(self, host='localhost', port=443, aws_access_key_id=None, aws_secret_access_key=None,
region=None, **kwargs):
super(BotoHttpConnection, self).__init__(host=host, port=port, **kwargs)
super().__init__(host=host, port=port, **kwargs)
connection_params = {'host': host, 'port': port}

# If not provided, boto will attempt to use default environment variables to fill
Expand Down Expand Up @@ -64,7 +62,7 @@ class ESConnection(AWSAuthConnection):
def __init__(self, *args, **kwargs):
region = kwargs.pop('region', None)
kwargs.setdefault('is_secure', True)
super(ESConnection, self).__init__(*args, **kwargs)
super().__init__(*args, **kwargs)
self.auth_region_name = region
self.auth_service_name = 'es'

Expand Down
Loading

0 comments on commit ed46fd1

Please sign in to comment.