Beispiel #1
0
    def test_cloning_asset_with_enclosed_item_also_clones_item(self):
        edx_asset_record = Type(**ASSET_RECORD_TYPES['edx-asset'])
        enclosure_record_type = Type(**ASSET_RECORD_TYPES['enclosure'])

        am = get_assessment_manager()
        bank_1 = am.get_bank(self.repo_1.ident)
        form = bank_1.get_item_form_for_create([])
        item = bank_1.create_item(form)

        create_form = self.repo_1.get_asset_form_for_create(
            [edx_asset_record, enclosure_record_type])
        create_form.set_enclosed_object(item.ident)
        asset = self.repo_1.create_asset(create_form)

        bank_2 = am.get_bank(self.repo_2.ident)

        assert bank_2.get_items().available() == 0

        new_asset = asset.clone_to(self.repo_2)

        assert bank_2.get_items().available() == 1

        assert new_asset._my_map['enclosedObjectId'] != asset._my_map[
            'enclosedObjectId']

        for bank in am.get_banks():
            for item in bank.get_items():
                bank.delete_item(item.ident)
            am.delete_bank(bank.ident)
Beispiel #2
0
def set_answer_form_genus_and_feedback(answer, answer_form):
    """answer is a dictionary"""
    if 'genus' in answer:
        answer_form.genus_type = Type(answer['genus'])
        if answer['genus'] == str(Type(**ANSWER_GENUS_TYPES['wrong-answer'])):
            if 'feedback' in answer:
                answer_form._init_record(
                    str(Type(**ANSWER_RECORD_TYPES['answer-with-feedback'])))
                answer_form.set_feedback(str(answer['feedback']))
            if 'confusedLearningObjectiveIds' in answer:
                if not isinstance(answer['confusedLearningObjectiveIds'],
                                  list):
                    los = [answer['confusedLearningObjectiveIds']]
                else:
                    los = answer['confusedLearningObjectiveIds']
                answer_form.set_confused_learning_objective_ids(los)
    else:
        # default is correct answer, if not supplied
        answer_form.set_genus_type(Type(**ANSWER_GENUS_TYPES['right-answer']))
        try:
            # remove the feedback components
            del answer_form._my_map['texts']['feedback']
            del answer_form._my_map['recordTypeIds'][str(
                Type(**ANSWER_RECORD_TYPES['answer-with-feedback']))]
        except KeyError:
            pass
    return answer_form
Beispiel #3
0
    def test_export_olx_handles_identical_display_names(self):
        edx_asset_record = Type(**ASSET_RECORD_TYPES['edx-asset'])
        edx_asset_content_record = Type(
            **ASSET_CONTENT_RECORD_TYPES['edx-asset-content-text-files'])
        edx_asset_content_genus = Type(**ASSET_CONTENT_GENUS_TYPES['html'])
        edx_composition_record = Type(
            **COMPOSITION_RECORD_TYPES['edx-composition'])

        form = self.repo_1.get_asset_form_for_create([edx_asset_record])
        form.display_name = 'Introduction to Python'
        asset_2 = self.repo_1.create_asset(form)

        form = self.repo_1.get_asset_content_form_for_create(
            asset_2.ident, [edx_asset_content_record])
        form.set_text('<html><body><div>foo2!</div></body></html>')
        form.set_genus_type(edx_asset_content_genus)
        self.repo_1.create_asset_content(form)
        asset_2 = self.repo_1.get_asset(asset_2.ident)

        form = self.repo_1.get_composition_form_for_create(
            [edx_composition_record])
        form.display_name = 'A vertical!'
        form.set_genus_type(Type(**COMPOSITION_GENUS_TYPES['vertical']))
        form.set_file_name('vertical/a-vertical.xml')
        vertical = self.repo_1.create_composition(form)

        self.repo_1.add_asset(self.asset.ident, vertical.ident)
        self.repo_1.add_asset(asset_2.ident, vertical.ident)

        vertical = self.repo_1.get_composition(vertical.ident)

        vertical.export_olx(self.tarball, '')

        self.stream.seek(0)
        reader = tarfile.open(fileobj=self.stream, mode='r')

        included_files = reader.getnames()
        assert len(included_files) == 5

        for expected_file in [
                'html/introduction-to-python.html',
                'html/introduction-to-python.xml',
                'html/introduction-to-python-1.html',
                'html/introduction-to-python-1.xml', 'vertical/a-vertical.xml'
        ]:
            assert expected_file in included_files

        html_1 = reader.extractfile('html/introduction-to-python.html')
        assert 'foo!' in html_1.read().decode('utf-8')

        html_2 = reader.extractfile('html/introduction-to-python-1.html')
        assert 'foo2!' in html_2.read().decode('utf-8')

        vertical_xml = reader.extractfile(
            'vertical/a-vertical.xml').read().decode('utf-8')
        assert '"introduction-to-python"' in vertical_xml
        assert '"introduction-to-python-1"' in vertical_xml
Beispiel #4
0
def get_answer_records(answer):
    """answer is a dictionary"""
    # check for wrong-answer genus type to get the right
    # record types for feedback
    a_type = Type(answer['type'])
    if 'genus' in answer and answer['genus'] == str(
            Type(**ANSWER_GENUS_TYPES['wrong-answer'])):
        a_types = [a_type, Type(**ANSWER_RECORD_TYPES['answer-with-feedback'])]
    else:
        a_types = [a_type]
    return a_types
Beispiel #5
0
def edx_asset_test_fixture(request):
    request.cls.stream = BytesIO()
    request.cls.tarball = tarfile.open(fileobj=request.cls.stream, mode='w')

    request.cls.rm = get_repository_manager()

    edx_asset_record = Type(**ASSET_RECORD_TYPES['edx-asset'])
    edx_asset_content_record = Type(
        **ASSET_CONTENT_RECORD_TYPES['edx-asset-content-text-files'])
    edx_asset_content_genus = Type(**ASSET_CONTENT_GENUS_TYPES['html'])

    form = request.cls.rm.get_repository_form_for_create([])
    form.display_name = 'Test Repo 1'
    request.cls.repo_1 = request.cls.rm.create_repository(form)

    form = request.cls.rm.get_repository_form_for_create([])
    form.display_name = 'Test Repo 2'
    request.cls.repo_2 = request.cls.rm.create_repository(form)

    form = request.cls.repo_1.get_asset_form_for_create([edx_asset_record])
    form.display_name = 'Introduction to Python'
    request.cls.asset = request.cls.repo_1.create_asset(form)

    form = request.cls.repo_1.get_asset_content_form_for_create(
        request.cls.asset.ident, [edx_asset_content_record])
    form.set_text('<html><body><div>foo!</div></body></html>')
    form.set_genus_type(edx_asset_content_genus)
    request.cls.repo_1.create_asset_content(form)
    request.cls.asset = request.cls.repo_1.get_asset(request.cls.asset.ident)

    def test_tear_down():
        for repository in request.cls.rm.get_repositories():
            repository.use_unsequestered_composition_view()
            for asset in repository.get_assets():
                repository.delete_asset(asset.ident)
            while repository.get_compositions().available() > 0:
                for composition in repository.get_compositions():
                    try:
                        repository.delete_composition(composition.ident)
                    except errors.IllegalState:
                        pass
            request.cls.rm.delete_repository(repository.ident)

    request.addfinalizer(test_tear_down)
Beispiel #6
0
    def test_match_asset_content_genus_type(self):
        assert self.query._my_osid_query._query_terms == {}

        self.query.match_asset_content_genus_type(Type('fake%3Agenus%40MIT'),
                                                  True)
        assert 'assetContents.0.genusTypeId' in self.query._my_osid_query._query_terms
        assert self.query._my_osid_query._query_terms[
            'assetContents.0.genusTypeId'] == {
                '$in': ['fake%3Agenus%40MIT']
            }
Beispiel #7
0
    def test_clear_match_composition_descendants(self):
        rm = get_repository_manager()

        edx_asset_record = Type(**ASSET_RECORD_TYPES['edx-asset'])

        form = rm.get_repository_form_for_create([])
        form.display_name = 'Test Repo'
        repo = rm.create_repository(form)

        form = repo.get_asset_form_for_create([edx_asset_record])
        form.display_name = 'Introduction to Python'
        asset = repo.create_asset(form)

        form = repo.get_composition_form_for_create([])
        child = repo.create_composition(form)

        repo.add_asset(asset.ident, child.ident)

        form = repo.get_composition_form_for_create([])
        form.set_children([child.ident])
        composition = repo.create_composition(form)

        query = QueryWrapper(runtime=repo._catalog._runtime)
        query = edXAssetQueryRecord(query)

        query.match_composition_descendants(composition.ident, repo.ident,
                                            True)

        assert '_id' in query._my_osid_query._query_terms
        assert query._my_osid_query._query_terms['_id'] == {
            '$in': [ObjectId(asset.ident.identifier)]
        }

        query.clear_match_composition_descendants()

        assert '_id' not in query._my_osid_query._query_terms

        for asset in repo.get_assets():
            repo.delete_asset(asset.ident)
        for composition in repo.get_compositions():
            repo.delete_composition(composition.ident)
        rm.delete_repository(repo.ident)
Beispiel #8
0
def is_right_answer(answer):
    return (answer.genus_type == Type(**ANSWER_GENUS_TYPES['right-answer'])
            or str(answer.genus_type) == 'GenusType%3ADEFAULT%40dlkit.mit.edu')
Beispiel #9
0
def create_new_item(bank, data):
    if ('question' in data and 'genusTypeId' in data['question']
            and 'edx' in data['question']['genusTypeId']):
        # should have body / setup
        # should have list of choices
        # should have set of right answers
        # metadata (if not present, it is okay):
        #  * max attempts
        #  * weight
        #  * showanswer
        #  * rerandomize
        #  * author username
        #  * student display name
        #  * author comments
        #  * extra python script
        # any files?
        form = bank.get_item_form_for_create([EDX_ITEM_RECORD_TYPE])
        form.display_name = data['displayName']
        form.description = data['description']
        form.set_genus_type(EDX_MULTI_CHOICE_PROBLEM_TYPE)

        if 'learningObjectiveIds' in data:
            form = set_item_learning_objectives(data, form)

        expected = ['question']
        gutils.verify_keys_present(data, expected)

        expected = ['questionString']
        gutils.verify_keys_present(data['question'], expected)

        form.add_text(data['question']['questionString'], 'questionString')

        optional = ['python_script', 'latex', 'edxml', 'solution']
        for opt in optional:
            if opt in data:
                form.add_text(data[opt], opt)

        metadata = [
            'attempts', 'markdown', 'rerandomize', 'showanswer', 'weight'
        ]
        # 'author','author_comments','student_display_name']
        for datum in metadata:
            if datum in data:
                method = getattr(form, 'add_' + datum)
                method(data[datum])

        irt = ['difficulty', 'discrimination']
        for datum in irt:
            if datum in data:
                method = getattr(form, 'set_' + datum + '_value')
                method(data[datum])

        if 'files' in data:
            files_list = {}
            for filename, file in data['files'].iteritems():
                files_list[filename] = DataInputStream(file)
            form = add_files_to_form(form, files_list)
    else:
        form = bank.get_item_form_for_create([])
        form.display_name = str(data['displayName'])
        form.description = str(data['description'])
        if 'genusTypeId' in data:
            form.set_genus_type(Type(data['genusTypeId']))

        if 'learningObjectiveIds' in data:
            form = set_item_learning_objectives(data, form)

    new_item = bank.create_item(form)
    return new_item
Beispiel #10
0
import json

from django.db import IntegrityError

from dlkit.runtime.errors import *
from dlkit.runtime.primitives import Type

from rest_framework.response import Response
from rest_framework.renderers import BrowsableAPIRenderer

from utilities import assessment as autils
from utilities import general as gutils
from producer.views import ProducerAPIViews, DLJSONRenderer

TOPIC_GENUS = Type('mc3-objective%3Amc3.learning.topic%40MIT-OEIT')
OUTCOME_GENUS = Type('mc3-objective%3Amc3.learning.outcome%40MIT-OEIT')
OUTCOME_GENERIC_GENUS = Type(
    'mc3-objective%3Amc3.learning.generic.outcome%40MIT-OEIT')


class ObjectiveBanksList(ProducerAPIViews):
    """
    Return list of objective banks from MC3

    api/v1/learning/objectivebanks/

    GET

    Note that for RESTful calls, you need to set the request header
    'content-type' to 'application/json'
Beispiel #11
0
    def post(self, request, bank_id=None, format=None):
        try:
            if bank_id is None:
                expected = ['bankId']
                gutils.verify_keys_present(self.data, expected)
                bank_id = self.data['bankId']

            bank = self.am.get_bank(gutils.clean_id(bank_id))
            new_item = autils.create_new_item(bank, self.data)
            # create questions and answers if they are part of the
            # input data. There must be a better way to figure out
            # which attributes I should set, given the
            # question type?
            if 'question' in self.data:
                question = self.data['question']
                if isinstance(question, basestring):
                    question = json.loads(question)
                q_type = Type(question['type'])
                qfc = bank.get_question_form_for_create(
                    item_id=new_item.ident, question_record_types=[q_type])
                qfc = autils.update_question_form(request,
                                                  question,
                                                  qfc,
                                                  create=True)

                if 'genus' in question:
                    qfc.genus_type = Type(question['genus'])

                if ('fileIds' in new_item.object_map
                        and len(new_item.object_map['fileIds'].keys()) > 0):
                    # add these files to the question, too
                    file_ids = new_item.object_map['fileIds']
                    qfc = autils.add_file_ids_to_form(qfc, file_ids)

                new_question = bank.create_question(qfc)

            if 'answers' in self.data:
                answers = self.data['answers']
                if isinstance(answers, basestring):
                    answers = json.loads(answers)
                for answer in answers:
                    a_types = autils.get_answer_records(answer)

                    afc = bank.get_answer_form_for_create(
                        new_item.ident, a_types)

                    if 'multi-choice' in answer['type']:
                        # because multiple choice answers need to match to
                        # the actual MC3 ChoiceIds, NOT the index passed
                        # in by the consumer.
                        if not new_question:
                            raise NullArgument('Question')
                        afc = autils.update_answer_form(
                            answer, afc, new_question)
                    else:
                        afc = autils.update_answer_form(answer, afc)

                    afc = autils.set_answer_form_genus_and_feedback(
                        answer, afc)
                    new_answer = bank.create_answer(afc)

            full_item = bank.get_item(new_item.ident)
            data = gutils.convert_dl_object(full_item)
            return gutils.CreatedResponse(data)
        except (KeyError, IntegrityError, PermissionDenied, Unsupported,
                InvalidArgument, NullArgument) as ex:
            gutils.handle_exceptions(ex)