INCR-411: Updates on Python 3.x
This commit is contained in:
@@ -13,6 +13,8 @@ Main module which shows problems (of "capa" type).
|
||||
This is used by capa_module.
|
||||
"""
|
||||
|
||||
from __future__ import absolute_import
|
||||
|
||||
import logging
|
||||
import os.path
|
||||
import re
|
||||
@@ -21,6 +23,7 @@ from copy import deepcopy
|
||||
from datetime import datetime
|
||||
from xml.sax.saxutils import unescape
|
||||
|
||||
import six
|
||||
from lxml import etree
|
||||
from pytz import UTC
|
||||
|
||||
@@ -208,7 +211,7 @@ class LoncapaProblem(object):
|
||||
|
||||
# Run response late_transforms last (see MultipleChoiceResponse)
|
||||
# Sort the responses to be in *_1 *_2 ... order.
|
||||
responses = self.responders.values()
|
||||
responses = list(self.responders.values())
|
||||
responses = sorted(responses, key=lambda resp: int(resp.id[resp.id.rindex('_') + 1:]))
|
||||
for response in responses:
|
||||
if hasattr(response, 'late_transforms'):
|
||||
@@ -492,7 +495,7 @@ class LoncapaProblem(object):
|
||||
answer_ids = []
|
||||
for response in self.responders.keys():
|
||||
results = self.responder_answers[response]
|
||||
answer_ids.append(results.keys())
|
||||
answer_ids.append(list(results.keys()))
|
||||
return answer_ids
|
||||
|
||||
def find_correct_answer_text(self, answer_id):
|
||||
@@ -612,7 +615,7 @@ class LoncapaProblem(object):
|
||||
self.find_answer_text(answer_id, answer) for answer in current_answer
|
||||
)
|
||||
|
||||
elif isinstance(current_answer, basestring) and current_answer.startswith('choice_'):
|
||||
elif isinstance(current_answer, six.string_types) and current_answer.startswith('choice_'):
|
||||
# Many problem (e.g. checkbox) report "choice_0" "choice_1" etc.
|
||||
# Here we transform it
|
||||
elems = self.tree.xpath('//*[@id="{answer_id}"]//*[@name="{choice_number}"]'.format(
|
||||
@@ -625,7 +628,7 @@ class LoncapaProblem(object):
|
||||
choices_map = dict(input_cls.extract_choices(choicegroup, self.capa_system.i18n, text_only=True))
|
||||
answer_text = choices_map[current_answer]
|
||||
|
||||
elif isinstance(current_answer, basestring):
|
||||
elif isinstance(current_answer, six.string_types):
|
||||
# Already a string with the answer
|
||||
answer_text = current_answer
|
||||
|
||||
@@ -903,7 +906,7 @@ class LoncapaProblem(object):
|
||||
|
||||
Used by get_html.
|
||||
"""
|
||||
if not isinstance(problemtree.tag, basestring):
|
||||
if not isinstance(problemtree.tag, six.string_types):
|
||||
# Comment and ProcessingInstruction nodes are not Elements,
|
||||
# and we're ok leaving those behind.
|
||||
# BTW: etree gives us no good way to distinguish these things
|
||||
|
||||
@@ -2,18 +2,17 @@
|
||||
"""
|
||||
Commandline tool for doing operations on Problems
|
||||
"""
|
||||
from __future__ import unicode_literals
|
||||
from __future__ import print_function
|
||||
from __future__ import absolute_import, print_function, unicode_literals
|
||||
|
||||
import argparse
|
||||
import logging
|
||||
import sys
|
||||
from io import BytesIO
|
||||
|
||||
from calc import UndefinedVariable
|
||||
from mako.lookup import TemplateLookup
|
||||
from path import Path as path
|
||||
|
||||
from calc import UndefinedVariable
|
||||
from capa.capa_problem import LoncapaProblem
|
||||
|
||||
logging.basicConfig(format="%(levelname)s %(message)s")
|
||||
|
||||
@@ -38,6 +38,8 @@ graded status as'status'
|
||||
# makes sense, but a bunch of problems have markup that assumes block. Bigger TODO: figure out a
|
||||
# general css and layout strategy for capa, document it, then implement it.
|
||||
|
||||
from __future__ import absolute_import
|
||||
|
||||
import json
|
||||
import logging
|
||||
import re
|
||||
@@ -49,16 +51,17 @@ from datetime import datetime
|
||||
import bleach
|
||||
import html5lib
|
||||
import pyparsing
|
||||
import six
|
||||
from calc.preview import latex_preview
|
||||
from lxml import etree
|
||||
from six import text_type
|
||||
|
||||
import xqueue_interface
|
||||
from calc.preview import latex_preview
|
||||
from capa.xqueue_interface import XQUEUE_TIMEOUT
|
||||
from chem import chemcalc
|
||||
from openedx.core.djangolib.markup import HTML, Text
|
||||
from xmodule.stringify import stringify_children
|
||||
|
||||
from . import xqueue_interface
|
||||
from .registry import TagRegistry
|
||||
from .util import sanitize_html
|
||||
|
||||
@@ -82,7 +85,7 @@ class Status(object):
|
||||
}
|
||||
__slots__ = ('classname', '_status', 'display_name', 'display_tooltip')
|
||||
|
||||
def __init__(self, status, gettext_func=unicode):
|
||||
def __init__(self, status, gettext_func=six.text_type):
|
||||
self.classname = self.css_classes.get(status, status)
|
||||
_ = gettext_func
|
||||
names = {
|
||||
@@ -107,7 +110,7 @@ class Status(object):
|
||||
['incomplete', 'unanswered', 'unsubmitted'], _('Not yet answered.')
|
||||
)
|
||||
)
|
||||
self.display_name = names.get(status, unicode(status))
|
||||
self.display_name = names.get(status, six.text_type(status))
|
||||
self.display_tooltip = tooltips.get(status, u'')
|
||||
self._status = status or ''
|
||||
|
||||
@@ -253,7 +256,7 @@ class InputTypeBase(object):
|
||||
# Something went wrong: add xml to message, but keep the traceback
|
||||
msg = u"Error in xml '{x}': {err} ".format(
|
||||
x=etree.tostring(xml), err=text_type(err))
|
||||
raise Exception, msg, sys.exc_info()[2]
|
||||
six.reraise(Exception, msg, sys.exc_info()[2])
|
||||
|
||||
@classmethod
|
||||
def get_attributes(cls):
|
||||
@@ -341,14 +344,14 @@ class InputTypeBase(object):
|
||||
# Every list should contain the status id
|
||||
status_id = 'status_' + self.input_id
|
||||
descriptions.append(status_id)
|
||||
descriptions.extend(self.response_data.get('descriptions', {}).keys())
|
||||
descriptions.extend(list(self.response_data.get('descriptions', {}).keys()))
|
||||
description_ids = ' '.join(descriptions)
|
||||
context.update(
|
||||
{'describedby_html': HTML('aria-describedby="{}"').format(description_ids)}
|
||||
)
|
||||
|
||||
context.update(
|
||||
(a, v) for (a, v) in self.loaded_attributes.iteritems() if a in self.to_render
|
||||
(a, v) for (a, v) in six.iteritems(self.loaded_attributes) if a in self.to_render
|
||||
)
|
||||
context.update(self._extra_context())
|
||||
if self.answervariable:
|
||||
@@ -554,7 +557,7 @@ class ChoiceGroup(InputTypeBase):
|
||||
return choices
|
||||
|
||||
def get_user_visible_answer(self, internal_answer):
|
||||
if isinstance(internal_answer, basestring):
|
||||
if isinstance(internal_answer, six.string_types):
|
||||
return self._choices_map[internal_answer]
|
||||
|
||||
return [self._choices_map[i] for i in internal_answer]
|
||||
@@ -689,7 +692,7 @@ class TextLine(InputTypeBase):
|
||||
'class_name': self.loaded_attributes['preprocessorClassName'],
|
||||
'script_src': self.loaded_attributes['preprocessorSrc'],
|
||||
}
|
||||
if None in self.preprocessor.values():
|
||||
if None in list(self.preprocessor.values()):
|
||||
self.preprocessor = None
|
||||
|
||||
def _extra_context(self):
|
||||
@@ -1594,7 +1597,7 @@ class AnnotationInput(InputTypeBase):
|
||||
d = {}
|
||||
|
||||
comment_value = d.get('comment', '')
|
||||
if not isinstance(comment_value, basestring):
|
||||
if not isinstance(comment_value, six.string_types):
|
||||
comment_value = ''
|
||||
|
||||
options_value = d.get('options', [])
|
||||
|
||||
@@ -50,7 +50,7 @@ class TagRegistry(object):
|
||||
"""
|
||||
Get a list of all the tags that have been registered.
|
||||
"""
|
||||
return self._mapping.keys()
|
||||
return list(self._mapping.keys())
|
||||
|
||||
def get_class_for_tag(self, tag):
|
||||
"""
|
||||
|
||||
@@ -10,6 +10,8 @@ Used by capa_problem.py
|
||||
|
||||
# pylint: disable=attribute-defined-outside-init
|
||||
# standard library imports
|
||||
from __future__ import absolute_import
|
||||
|
||||
import abc
|
||||
# TODO: Refactor this code and fix this issue.
|
||||
import cgi
|
||||
@@ -22,6 +24,7 @@ import re
|
||||
import sys
|
||||
import textwrap
|
||||
import traceback
|
||||
from cmath import isnan
|
||||
from collections import namedtuple
|
||||
from datetime import datetime
|
||||
from sys import float_info
|
||||
@@ -29,18 +32,19 @@ from sys import float_info
|
||||
import html5lib
|
||||
import numpy
|
||||
import requests
|
||||
import six
|
||||
# specific library imports
|
||||
from calc import UndefinedVariable, UnmatchedParenthesis, evaluator
|
||||
from lxml import etree
|
||||
from lxml.html.soupparser import fromstring as fromstring_bs # uses Beautiful Soup!!! FIXME?
|
||||
from pyparsing import ParseException
|
||||
from pytz import UTC
|
||||
from shapely.geometry import MultiPoint, Point
|
||||
from six import text_type
|
||||
from six.moves import map, range, zip
|
||||
|
||||
import capa.safe_exec as safe_exec
|
||||
import capa.xqueue_interface as xqueue_interface
|
||||
# specific library imports
|
||||
from calc import UndefinedVariable, UnmatchedParenthesis, evaluator
|
||||
from cmath import isnan
|
||||
from openedx.core.djangolib.markup import HTML, Text
|
||||
|
||||
from . import correctmap
|
||||
@@ -103,7 +107,7 @@ class StudentInputError(Exception):
|
||||
# Main base class for CAPA responsetypes
|
||||
|
||||
|
||||
class LoncapaResponse(object):
|
||||
class LoncapaResponse(six.with_metaclass(abc.ABCMeta, object)):
|
||||
"""
|
||||
Base class for CAPA responsetypes. Each response type (ie a capa question,
|
||||
which is part of a capa problem) is represented as a subclass,
|
||||
@@ -140,7 +144,6 @@ class LoncapaResponse(object):
|
||||
- hint_tag : xhtml tag identifying hint associated with this response inside
|
||||
hintgroup
|
||||
"""
|
||||
__metaclass__ = abc.ABCMeta # abc = Abstract Base Class
|
||||
|
||||
tags = None
|
||||
hint_tag = None
|
||||
@@ -179,14 +182,14 @@ class LoncapaResponse(object):
|
||||
for abox in inputfields:
|
||||
if abox.tag not in self.allowed_inputfields:
|
||||
msg = "%s: cannot have input field %s" % (
|
||||
unicode(self), abox.tag)
|
||||
six.text_type(self), abox.tag)
|
||||
msg += "\nSee XML source line %s" % getattr(
|
||||
xml, 'sourceline', '[unavailable]')
|
||||
raise LoncapaProblemError(msg)
|
||||
|
||||
if self.max_inputfields and len(inputfields) > self.max_inputfields:
|
||||
msg = "%s: cannot have more than %s input fields" % (
|
||||
unicode(self), self.max_inputfields)
|
||||
six.text_type(self), self.max_inputfields)
|
||||
msg += "\nSee XML source line %s" % getattr(
|
||||
xml, 'sourceline', '[unavailable]')
|
||||
raise LoncapaProblemError(msg)
|
||||
@@ -194,7 +197,7 @@ class LoncapaResponse(object):
|
||||
for prop in self.required_attributes:
|
||||
if not xml.get(prop):
|
||||
msg = "Error in problem specification: %s missing required attribute %s" % (
|
||||
unicode(self), prop)
|
||||
six.text_type(self), prop)
|
||||
msg += "\nSee XML source line %s" % getattr(
|
||||
xml, 'sourceline', '[unavailable]')
|
||||
raise LoncapaProblemError(msg)
|
||||
@@ -1455,10 +1458,10 @@ class OptionResponse(LoncapaResponse):
|
||||
Return student answers variable name if exist in context else None.
|
||||
"""
|
||||
if aid in student_answers:
|
||||
for key, val in self.context.iteritems():
|
||||
for key, val in six.iteritems(self.context):
|
||||
# convert val into unicode because student answer always be a unicode string
|
||||
# even it is a list, dict etc.
|
||||
if unicode(val) == student_answers[aid]:
|
||||
if six.text_type(val) == student_answers[aid]:
|
||||
return '$' + key
|
||||
return None
|
||||
|
||||
@@ -2170,7 +2173,7 @@ class CustomResponse(LoncapaResponse):
|
||||
"""
|
||||
_ = self.capa_system.i18n.ugettext
|
||||
|
||||
log.debug('%s: student_answers=%s', unicode(self), student_answers)
|
||||
log.debug('%s: student_answers=%s', six.text_type(self), student_answers)
|
||||
|
||||
# ordered list of answer id's
|
||||
# sort the responses on the bases of the problem's position number
|
||||
@@ -2284,7 +2287,7 @@ class CustomResponse(LoncapaResponse):
|
||||
|
||||
def execute_check_function(self, idset, submission):
|
||||
# exec the check function
|
||||
if isinstance(self.code, basestring):
|
||||
if isinstance(self.code, six.string_types):
|
||||
try:
|
||||
safe_exec.safe_exec(
|
||||
self.code,
|
||||
@@ -2897,7 +2900,7 @@ class ExternalResponse(LoncapaResponse):
|
||||
# no <answer> stanza; get code from <script>
|
||||
self.code = self.context['script_code']
|
||||
if not self.code:
|
||||
msg = '%s: Missing answer script code for externalresponse' % unicode(
|
||||
msg = '%s: Missing answer script code for externalresponse' % six.text_type(
|
||||
self)
|
||||
msg += "\nSee XML source line %s" % getattr(
|
||||
self.xml, 'sourceline', '[unavailable]')
|
||||
@@ -2972,8 +2975,8 @@ class ExternalResponse(LoncapaResponse):
|
||||
except Exception as err: # pylint: disable=broad-except
|
||||
log.error('Error %s', err)
|
||||
if self.capa_system.DEBUG:
|
||||
cmap.set_dict(dict(zip(sorted(
|
||||
self.answer_ids), ['incorrect'] * len(idset))))
|
||||
cmap.set_dict(dict(list(zip(sorted(
|
||||
self.answer_ids), ['incorrect'] * len(idset)))))
|
||||
cmap.set_property(
|
||||
self.answer_ids[0], 'msg',
|
||||
Text('<span class="inline-error">{}</span>').format(str(err))
|
||||
@@ -3013,7 +3016,7 @@ class ExternalResponse(LoncapaResponse):
|
||||
log.error('Expected %s answers from external server, only got %s!',
|
||||
len(self.answer_ids), len(exans))
|
||||
raise Exception('Short response from external server')
|
||||
return dict(zip(self.answer_ids, exans))
|
||||
return dict(list(zip(self.answer_ids, exans)))
|
||||
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
@@ -3151,9 +3154,8 @@ class FormulaResponse(LoncapaResponse):
|
||||
"""
|
||||
variables = samples.split('@')[0].split(',')
|
||||
numsamples = int(samples.split('@')[1].split('#')[1])
|
||||
sranges = zip(*map(lambda x: map(float, x.split(",")),
|
||||
samples.split('@')[1].split('#')[0].split(':')))
|
||||
ranges = dict(zip(variables, sranges))
|
||||
sranges = list(zip(*[list(map(float, x.split(","))) for x in samples.split('@')[1].split('#')[0].split(':')]))
|
||||
ranges = dict(list(zip(variables, sranges)))
|
||||
|
||||
out = []
|
||||
for _ in range(numsamples):
|
||||
@@ -3286,7 +3288,7 @@ class SchematicResponse(LoncapaResponse):
|
||||
msg = _('Error in evaluating SchematicResponse. The error was: {error_msg}').format(error_msg=err)
|
||||
raise ResponseError(msg)
|
||||
cmap = CorrectMap()
|
||||
cmap.set_dict(dict(zip(sorted(self.answer_ids), self.context['correct'])))
|
||||
cmap.set_dict(dict(list(zip(sorted(self.answer_ids), self.context['correct']))))
|
||||
return cmap
|
||||
|
||||
def get_answers(self):
|
||||
@@ -3468,8 +3470,8 @@ class AnnotationResponse(LoncapaResponse):
|
||||
student_option = self._get_submitted_option_id(student_answer)
|
||||
|
||||
scoring = self.scoring_map[self.answer_id]
|
||||
is_valid = student_option is not None and student_option in scoring.keys(
|
||||
)
|
||||
is_valid = student_option is not None and student_option in list(scoring.keys(
|
||||
))
|
||||
|
||||
(correctness, points) = ('incorrect', None)
|
||||
if is_valid:
|
||||
@@ -3541,7 +3543,7 @@ class AnnotationResponse(LoncapaResponse):
|
||||
json_d = {}
|
||||
|
||||
comment_value = json_d.get('comment', '')
|
||||
if not isinstance(json_d, basestring):
|
||||
if not isinstance(json_d, six.string_types):
|
||||
comment_value = ''
|
||||
|
||||
options_value = json_d.get('options', [])
|
||||
@@ -3849,7 +3851,7 @@ class ChoiceTextResponse(LoncapaResponse):
|
||||
"""
|
||||
_ = self.capa_system.i18n.ugettext
|
||||
inputs_correct = True
|
||||
for answer_name, answer_value in numtolerance_inputs.iteritems():
|
||||
for answer_name, answer_value in six.iteritems(numtolerance_inputs):
|
||||
# If `self.corrrect_inputs` does not contain an entry for
|
||||
# `answer_name`, this means that answer_name is a decoy
|
||||
# input's value, and validation of its numericality is the
|
||||
|
||||
@@ -1,17 +1,18 @@
|
||||
"""
|
||||
Utility functions for capa.
|
||||
"""
|
||||
from __future__ import absolute_import
|
||||
|
||||
import re
|
||||
from cmath import isinf, isnan
|
||||
from decimal import Decimal
|
||||
|
||||
import bleach
|
||||
from calc import evaluator
|
||||
from lxml import etree
|
||||
|
||||
from calc import evaluator
|
||||
from cmath import isinf, isnan
|
||||
from openedx.core.djangolib.markup import HTML
|
||||
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
#
|
||||
# Utility functions used in CAPA responsetypes
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
from __future__ import absolute_import
|
||||
|
||||
from setuptools import find_packages, setup
|
||||
|
||||
setup(
|
||||
|
||||
Reference in New Issue
Block a user