ran python-modernize and isort on files mentioned in INCR-446
changes made to comply with quality changes made to comply with quality changes made to comply with quality
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
"""
|
||||
Django admin page for bulk email models
|
||||
"""
|
||||
from __future__ import absolute_import
|
||||
|
||||
from config_models.admin import ConfigurationModelAdmin
|
||||
from django.contrib import admin
|
||||
|
||||
@@ -79,6 +81,7 @@ To enable email for the course, check the "Email enabled" box, then click "Save"
|
||||
}),
|
||||
)
|
||||
|
||||
|
||||
admin.site.register(CourseEmail, CourseEmailAdmin)
|
||||
admin.site.register(Optout, OptoutAdmin)
|
||||
admin.site.register(CourseEmailTemplate, CourseEmailTemplateAdmin)
|
||||
|
||||
@@ -1,14 +1,18 @@
|
||||
"""
|
||||
Models for bulk email
|
||||
"""
|
||||
from __future__ import absolute_import
|
||||
|
||||
import logging
|
||||
|
||||
import markupsafe
|
||||
import six
|
||||
from config_models.models import ConfigurationModel
|
||||
from django.contrib.auth.models import User
|
||||
from django.db import models
|
||||
from opaque_keys.edx.django.models import CourseKeyField
|
||||
from six import text_type
|
||||
from six.moves import zip
|
||||
|
||||
from course_modes.models import CourseMode
|
||||
from openedx.core.djangoapps.course_groups.cohorts import get_cohort_by_name
|
||||
@@ -49,10 +53,10 @@ SEND_TO_STAFF = 'staff'
|
||||
SEND_TO_LEARNERS = 'learners'
|
||||
SEND_TO_COHORT = 'cohort'
|
||||
SEND_TO_TRACK = 'track'
|
||||
EMAIL_TARGET_CHOICES = zip(
|
||||
EMAIL_TARGET_CHOICES = list(zip(
|
||||
[SEND_TO_MYSELF, SEND_TO_STAFF, SEND_TO_LEARNERS, SEND_TO_COHORT, SEND_TO_TRACK],
|
||||
['Myself', 'Staff and instructors', 'All students', 'Specific cohort', 'Specific course mode']
|
||||
)
|
||||
))
|
||||
EMAIL_TARGETS = {target[0] for target in EMAIL_TARGET_CHOICES}
|
||||
|
||||
|
||||
@@ -221,7 +225,7 @@ class CourseModeTarget(Target):
|
||||
if mode_slug is None:
|
||||
raise ValueError("Cannot create a CourseModeTarget without specifying a mode_slug.")
|
||||
try:
|
||||
validate_course_mode(unicode(course_id), mode_slug, include_expired=True)
|
||||
validate_course_mode(six.text_type(course_id), mode_slug, include_expired=True)
|
||||
except CourseModeNotFoundError:
|
||||
raise ValueError(
|
||||
u"Track {track} does not exist in course {course_id}".format(
|
||||
@@ -419,8 +423,8 @@ class CourseEmailTemplate(models.Model):
|
||||
stored HTML template and the provided `context` dict.
|
||||
"""
|
||||
# HTML-escape string values in the context (used for keyword substitution).
|
||||
for key, value in context.iteritems():
|
||||
if isinstance(value, basestring):
|
||||
for key, value in six.iteritems(context):
|
||||
if isinstance(value, six.string_types):
|
||||
context[key] = markupsafe.escape(value)
|
||||
return CourseEmailTemplate._render(self.html_template, htmltext, context)
|
||||
|
||||
@@ -458,17 +462,11 @@ class CourseAuthorization(models.Model):
|
||||
return u"Course '{}': Instructor Email {}Enabled".format(text_type(self.course_id), not_en)
|
||||
|
||||
|
||||
# .. toggle_name: require_course_email_auth
|
||||
# .. toggle_type: ConfigurationModel
|
||||
# .. toggle_default: True (enabled)
|
||||
# .. toggle_description: If the flag is enabled, course-specific authorization is required, and the course_id is either not provided or not authorixed, the feature is not available.
|
||||
# .. toggle_category: bulk email
|
||||
# .. toggle_use_cases: open_edx
|
||||
# .. toggle_creation_date: 2016-05-05
|
||||
# .. toggle_expiration_date: None
|
||||
# .. toggle_warnings: None
|
||||
# .. toggle_tickets: None
|
||||
# .. toggle_status: supported
|
||||
# .. toggle_name: require_course_email_auth .. toggle_type: ConfigurationModel .. toggle_default: True (enabled) ..
|
||||
# toggle_description: If the flag is enabled, course-specific authorization is required, and the course_id is either
|
||||
# not provided or not authorixed, the feature is not available. .. toggle_category: bulk email .. toggle_use_cases:
|
||||
# open_edx .. toggle_creation_date: 2016-05-05 .. toggle_expiration_date: None .. toggle_warnings: None ..
|
||||
# toggle_tickets: None .. toggle_status: supported
|
||||
class BulkEmailFlag(ConfigurationModel):
|
||||
"""
|
||||
Enables site-wide configuration for the bulk_email feature.
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
"""Course Email optOut Policy"""
|
||||
from __future__ import absolute_import
|
||||
|
||||
from edx_ace.policy import Policy, PolicyResult
|
||||
from edx_ace.channel import ChannelType
|
||||
from edx_ace.policy import Policy, PolicyResult
|
||||
from opaque_keys.edx.keys import CourseKey
|
||||
|
||||
from bulk_email.models import Optout
|
||||
@@ -13,6 +15,7 @@ class CourseEmailOptout(Policy):
|
||||
if not course_ids:
|
||||
return PolicyResult(deny=frozenset())
|
||||
|
||||
# pylint: disable=line-too-long
|
||||
course_keys = [CourseKey.from_string(course_id) for course_id in course_ids]
|
||||
if Optout.objects.filter(user__username=message.recipient.username, course_id__in=course_keys).count() == len(course_keys):
|
||||
return PolicyResult(deny={ChannelType.EMAIL})
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
This module contains celery task functions for handling the sending of bulk email
|
||||
to a course.
|
||||
"""
|
||||
from __future__ import absolute_import
|
||||
|
||||
import json
|
||||
import logging
|
||||
import random
|
||||
@@ -25,8 +27,6 @@ from boto.ses.exceptions import (
|
||||
SESLocalAddressCharacterError,
|
||||
SESMaxSendingRateExceededError
|
||||
)
|
||||
from util.string_utils import _has_non_ascii_characters
|
||||
|
||||
from celery import current_task, task
|
||||
from celery.exceptions import RetryTaskError
|
||||
from celery.states import FAILURE, RETRY, SUCCESS
|
||||
@@ -52,6 +52,7 @@ from lms.djangoapps.instructor_task.subtasks import (
|
||||
from openedx.core.djangoapps.site_configuration import helpers as configuration_helpers
|
||||
from openedx.core.lib.courses import course_image_url
|
||||
from util.date_utils import get_default_time_display
|
||||
from util.string_utils import _has_non_ascii_characters
|
||||
|
||||
log = logging.getLogger('edx.celery.task')
|
||||
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
"""
|
||||
Image encoding helpers for the verification app.
|
||||
"""
|
||||
from __future__ import absolute_import
|
||||
|
||||
import logging
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
"""
|
||||
Signal handler for setting default course verification dates
|
||||
"""
|
||||
from __future__ import absolute_import
|
||||
|
||||
from django.core.exceptions import ObjectDoesNotExist
|
||||
from django.dispatch.dispatcher import receiver
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ An RSA private key can be in any of the following formats:
|
||||
* PKCS#1 RSAPrivateKey DER SEQUENCE (binary or PEM encoding)
|
||||
* PKCS#8 PrivateKeyInfo DER SEQUENCE (binary or PEM encoding)
|
||||
"""
|
||||
from __future__ import division
|
||||
from __future__ import absolute_import, division
|
||||
|
||||
import base64
|
||||
import binascii
|
||||
@@ -23,7 +23,6 @@ import hmac
|
||||
import logging
|
||||
import os
|
||||
from hashlib import md5, sha256
|
||||
from six import text_type
|
||||
|
||||
from cryptography.hazmat.backends import default_backend
|
||||
from cryptography.hazmat.primitives import serialization
|
||||
@@ -33,6 +32,7 @@ from cryptography.hazmat.primitives.ciphers.algorithms import AES
|
||||
from cryptography.hazmat.primitives.ciphers.modes import CBC
|
||||
from cryptography.hazmat.primitives.hashes import SHA1
|
||||
from cryptography.hazmat.primitives.padding import PKCS7
|
||||
from six import text_type
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@@ -2,12 +2,18 @@
|
||||
Views for the verification flow
|
||||
"""
|
||||
|
||||
from __future__ import absolute_import
|
||||
|
||||
import datetime
|
||||
import decimal
|
||||
import json
|
||||
import logging
|
||||
import urllib
|
||||
|
||||
import six
|
||||
import six.moves.urllib.error # pylint: disable=import-error
|
||||
import six.moves.urllib.parse # pylint: disable=import-error
|
||||
import six.moves.urllib.request # pylint: disable=import-error
|
||||
from course_modes.models import CourseMode
|
||||
from django.conf import settings
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.contrib.staticfiles.storage import staticfiles_storage
|
||||
@@ -24,13 +30,18 @@ from django.views.decorators.csrf import csrf_exempt
|
||||
from django.views.decorators.http import require_POST
|
||||
from django.views.generic.base import View
|
||||
from edx_rest_api_client.exceptions import SlumberBaseException
|
||||
from eventtracking import tracker
|
||||
from edxmako.shortcuts import render_to_response, render_to_string
|
||||
from ipware.ip import get_ip
|
||||
from opaque_keys import InvalidKeyError
|
||||
from opaque_keys.edx.keys import CourseKey
|
||||
from shoppingcart.models import CertificateItem, Order
|
||||
from shoppingcart.processors import get_purchase_endpoint, get_signed_purchase_params
|
||||
from student.models import CourseEnrollment
|
||||
from track import segment
|
||||
from util.db import outer_atomic
|
||||
from util.json_request import JsonResponse
|
||||
from xmodule.modulestore.django import modulestore
|
||||
|
||||
from course_modes.models import CourseMode
|
||||
from edxmako.shortcuts import render_to_response, render_to_string
|
||||
from lms.djangoapps.commerce.utils import EcommerceService, is_account_activation_requirement_disabled
|
||||
from lms.djangoapps.verify_student.image import InvalidImageData, decode_image_data
|
||||
from lms.djangoapps.verify_student.models import SoftwareSecurePhotoVerification, VerificationDeadline
|
||||
@@ -45,13 +56,6 @@ from openedx.core.djangoapps.user_api.accounts import NAME_MIN_LENGTH
|
||||
from openedx.core.djangoapps.user_api.accounts.api import update_account_settings
|
||||
from openedx.core.djangoapps.user_api.errors import AccountValidationError, UserNotFound
|
||||
from openedx.core.lib.log_utils import audit_log
|
||||
from shoppingcart.models import CertificateItem, Order
|
||||
from shoppingcart.processors import get_purchase_endpoint, get_signed_purchase_params
|
||||
from student.models import CourseEnrollment
|
||||
from track import segment
|
||||
from util.db import outer_atomic
|
||||
from util.json_request import JsonResponse
|
||||
from xmodule.modulestore.django import modulestore
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
@@ -379,7 +383,7 @@ class PayAndVerifyView(View):
|
||||
if not course.start or course.start < now():
|
||||
courseware_url = reverse(
|
||||
'course_root',
|
||||
kwargs={'course_id': unicode(course_key)}
|
||||
kwargs={'course_id': six.text_type(course_key)}
|
||||
)
|
||||
|
||||
full_name = (
|
||||
@@ -392,7 +396,7 @@ class PayAndVerifyView(View):
|
||||
# use that amount to pre-fill the price selection form.
|
||||
contribution_amount = request.session.get(
|
||||
'donation_for_course', {}
|
||||
).get(unicode(course_key), '')
|
||||
).get(six.text_type(course_key), '')
|
||||
|
||||
# Remember whether the user is upgrading
|
||||
# so we can fire an analytics event upon payment.
|
||||
@@ -413,7 +417,7 @@ class PayAndVerifyView(View):
|
||||
context = {
|
||||
'contribution_amount': contribution_amount,
|
||||
'course': course,
|
||||
'course_key': unicode(course_key),
|
||||
'course_key': six.text_type(course_key),
|
||||
'checkpoint_location': request.GET.get('checkpoint'),
|
||||
'course_mode': relevant_course_mode,
|
||||
'courseware_url': courseware_url,
|
||||
@@ -441,10 +445,10 @@ class PayAndVerifyView(View):
|
||||
# utm_params is [(u'utm_content', u'course-v1:IDBx IDB20.1x 1T2017'),...
|
||||
utm_params = [item for item in self.request.GET.items() if 'utm_' in item[0]]
|
||||
# utm_params is utm_content=course-v1%3AIDBx+IDB20.1x+1T2017&...
|
||||
utm_params = urllib.urlencode(utm_params, True)
|
||||
utm_params = six.moves.urllib.parse.urlencode(utm_params, True) # pylint: disable=too-many-function-args
|
||||
# utm_params is utm_content=course-v1:IDBx+IDB20.1x+1T2017&...
|
||||
# (course-keys do not have url encoding)
|
||||
utm_params = urllib.unquote(utm_params)
|
||||
utm_params = six.moves.urllib.parse.unquote(utm_params) # pylint: disable=too-many-function-args
|
||||
if utm_params:
|
||||
if '?' in url:
|
||||
url = url + '&' + utm_params
|
||||
@@ -453,8 +457,8 @@ class PayAndVerifyView(View):
|
||||
return url
|
||||
|
||||
def _redirect_if_necessary(
|
||||
self, message, already_verified, already_paid, is_enrolled, course_key,
|
||||
user_is_trying_to_pay, user, sku
|
||||
self, message, already_verified, already_paid, is_enrolled, course_key,
|
||||
user_is_trying_to_pay, user, sku
|
||||
):
|
||||
"""Redirect the user to a more appropriate page if necessary.
|
||||
|
||||
@@ -488,7 +492,7 @@ class PayAndVerifyView(View):
|
||||
|
||||
"""
|
||||
url = None
|
||||
course_kwargs = {'course_id': unicode(course_key)}
|
||||
course_kwargs = {'course_id': six.text_type(course_key)}
|
||||
|
||||
if already_verified and already_paid:
|
||||
# If they've already paid and verified, there's nothing else to do,
|
||||
@@ -597,7 +601,7 @@ class PayAndVerifyView(View):
|
||||
return [
|
||||
{
|
||||
'name': step,
|
||||
'title': unicode(self.STEP_TITLES[step]),
|
||||
'title': six.text_type(self.STEP_TITLES[step]),
|
||||
}
|
||||
for step in display_steps
|
||||
if step not in remove_steps
|
||||
@@ -631,7 +635,7 @@ class PayAndVerifyView(View):
|
||||
|
||||
display_steps = set(step['name'] for step in display_steps)
|
||||
|
||||
for step, step_requirements in self.STEP_REQUIREMENTS.iteritems():
|
||||
for step, step_requirements in six.iteritems(self.STEP_REQUIREMENTS):
|
||||
if step in display_steps:
|
||||
for requirement in step_requirements:
|
||||
all_requirements[requirement] = True
|
||||
@@ -729,7 +733,7 @@ class PayAndVerifyView(View):
|
||||
|
||||
def checkout_with_ecommerce_service(user, course_key, course_mode, processor):
|
||||
""" Create a new basket and trigger immediate checkout, using the E-Commerce API. """
|
||||
course_id = unicode(course_key)
|
||||
course_id = six.text_type(course_key)
|
||||
try:
|
||||
api = ecommerce_api_client(user)
|
||||
# Make an API call to create the order and retrieve the results
|
||||
@@ -781,7 +785,7 @@ def checkout_with_shoppingcart(request, user, course_key, course_mode, amount):
|
||||
'payment_form_data': get_signed_purchase_params(
|
||||
cart,
|
||||
callback_url=callback_url,
|
||||
extra_data=[unicode(course_key), course_mode.slug]
|
||||
extra_data=[six.text_type(course_key), course_mode.slug]
|
||||
),
|
||||
}
|
||||
return payment_data
|
||||
@@ -798,7 +802,7 @@ def create_order(request):
|
||||
course_id = request.POST['course_id']
|
||||
course_id = CourseKey.from_string(course_id)
|
||||
donation_for_course = request.session.get('donation_for_course', {})
|
||||
contribution = request.POST.get("contribution", donation_for_course.get(unicode(course_id), 0))
|
||||
contribution = request.POST.get("contribution", donation_for_course.get(six.text_type(course_id), 0))
|
||||
try:
|
||||
amount = decimal.Decimal(contribution).quantize(decimal.Decimal('.01'), rounding=decimal.ROUND_DOWN)
|
||||
except decimal.InvalidOperation:
|
||||
@@ -1135,7 +1139,7 @@ def results_callback(request):
|
||||
access_key = access_key_and_sig.split(":")[0]
|
||||
|
||||
# This is what we should be doing...
|
||||
#if not sig_valid:
|
||||
# if not sig_valid:
|
||||
# return HttpResponseBadRequest("Signature is invalid")
|
||||
|
||||
# This is what we're doing until we can figure out why we disagree on sigs
|
||||
@@ -1237,6 +1241,7 @@ class ReverifyView(View):
|
||||
the user submitted during initial verification.
|
||||
|
||||
"""
|
||||
|
||||
@method_decorator(login_required)
|
||||
def get(self, request):
|
||||
"""
|
||||
|
||||
Reference in New Issue
Block a user