def test_AsVersionList(self): obj = { 'category': [{'id': 'categoryList', "objectType": "Activity"}], 'parent': [{'id': 'parentList', 'objectType': 'Activity'}], 'grouping': [{'id': 'groupingList', 'objectType': 'Activity'}], 'other': [{'id': 'otherList', 'objectType': 'Activity'}]} ctx_act = ContextActivities(**obj) self.listVerificationHelper(ctx_act) ctx_act2 = ctx_act.as_version() self.assertEqual(ctx_act2, obj)
def test_AsVersionActivity(self): obj = { 'category': {'id': 'categoryActivity', 'object_type': 'Activity'}, 'parent': {'id': 'parentActivity', 'object_type': 'Activity'}, 'grouping': {'id': 'groupingActivity', 'object_type': 'Activity'}, 'other': {'id': 'otherActivity', 'object_type': 'Activity'}} check_obj = { 'category': [{'id': 'categoryActivity', 'objectType': 'Activity'}], 'parent': [{'id': 'parentActivity', 'objectType': 'Activity'}], 'grouping': [{'id': 'groupingActivity', 'objectType': 'Activity'}], 'other': [{'id': 'otherActivity', 'objectType': 'Activity'}]} ctx_act = ContextActivities(**obj) self.activityVerificationHelper(ctx_act) ctx_act2 = ctx_act.as_version() self.assertEqual(ctx_act2, check_obj)
def test_InitAsList(self): ctx_act = ContextActivities( category=ActivityList([Activity(id='categoryList')]), parent=ActivityList([Activity(id='parentList')]), grouping=ActivityList([Activity(id='groupingList')]), other=ActivityList([Activity(id='otherList')])) self.listVerificationHelper(ctx_act)
def get_context_activities(self, event): parent_activities = [ Activity( id='{}/courses/{}'.format(settings.OPENEDX_PLATFORM_URI, event['context']['course_id']), definition=course.CourseActivityDefinition(event) ), ] # browser source events don't know as much about their context if event['event_source'].lower() == 'server': parent_activities.append( Activity( id=event['referer'], definition=BlockActivityDefinition(event) ), ) other_activities = [ Activity( id=event['referer'], definition=base.ReferringActivityDefinition(event) ), ] return ContextActivities( parent=ActivityList(parent_activities), other=ActivityList(other_activities) )
def answer_evaluation_on_criterion(cls, answer, comparison_criterion, **kwargs): context = cls.basic(**kwargs) context.context_activities = ContextActivities( # parent is answer + criterion parent=ActivityList([ Activity(id=XAPIResourceIRI.answer(answer.uuid)), Activity(id=XAPIResourceIRI.criterion( comparison_criterion.criterion_uuid)) ]), # grouping is course + assignment + assignment question grouping=ActivityList([ Activity(id=XAPIResourceIRI.course(answer.course_uuid)), Activity( id=XAPIResourceIRI.assignment(answer.assignment_uuid)), Activity(id=XAPIResourceIRI.assignment_question( answer.assignment_uuid)) ]), # other is comparison + comparison question other=ActivityList([ Activity(id=XAPIResourceIRI.comparison_criterion( comparison_criterion.uuid)), Activity(id=XAPIResourceIRI.comparison( comparison_criterion.comparison_uuid)), Activity(id=XAPIResourceIRI.comparison_question( comparison_criterion.comparison_uuid)) ])) return context
def test_InitAsActivity(self): ctx_act = ContextActivities( category=Activity(id='categoryActivity'), parent=Activity(id='parentActivity'), grouping=Activity(id='groupingActivity'), other=Activity(id='otherActivity')) self.activityVerificationHelper(ctx_act)
def get_context_activities(self): """ Get context activities for xAPI transformed event. Returns: `ContextActivities` """ if self.get_data('context.course_id') is not None: course = get_course_from_id(self.get_data('context.course_id')) course_name = LanguageMap({constants.EN_US: course["display_name"]}) parent_activities = [ Activity( id=self.get_object_iri('course', self.get_data('context.course_id')), object_type=constants.XAPI_ACTIVITY_COURSE, definition=ActivityDefinition( type=constants.XAPI_ACTIVITY_COURSE, name=course_name ) ), ] return ContextActivities( parent=ActivityList(parent_activities), ) else: return None
def test_InitExceptionUnpackNotActivityOrList(self): obj = { 'category': 'notActivityOrList', 'parent': Activity(id='parentActivity') } with self.assertRaises(TypeError): ContextActivities(**obj)
def _add_default(cls, user, statement): if not statement.timestamp: statement.timestamp = LearningRecord.generate_timestamp() if impersonation.is_impersonating() and user.id == current_user.id: statement.actor = XAPIActor.generate_actor( impersonation.get_impersonation_original_user()) else: statement.actor = XAPIActor.generate_actor(user) # add default context info if not statement.context: statement.context = Context() if not statement.context.context_activities: statement.context.context_activities = ContextActivities() if not statement.context.context_activities.category: statement.context.context_activities.category = ActivityList() statement.context.context_activities.category.append( XAPIActivity.compair_source()) statement.context.platform = ResourceIRI.compair() if not statement.context.extensions: statement.context.extensions = Extensions() statement.context.extensions[ 'http://id.tincanapi.com/extension/session-info'] = { 'id': ResourceIRI.user_session(sess.get('session_id', '')), 'start_at': sess.get('start_at'), 'login_method': sess.get('login_method'), } if sess.get('end_at'): statement.context.extensions[ 'http://id.tincanapi.com/extension/session-info'][ 'end_at'] = sess.get('end_at') if impersonation.is_impersonating() and user.id == current_user.id: statement.context.extensions[ 'http://id.tincanapi.com/extension/session-info'][ 'impersonating-as'] = XAPIActor.generate_actor( user).as_version() statement.context.extensions[ 'http://id.tincanapi.com/extension/browser-info'] = {} if request and request.environ.get('HTTP_USER_AGENT'): statement.context.extensions[ 'http://id.tincanapi.com/extension/browser-info'][ 'user-agent'] = request.environ.get('HTTP_USER_AGENT') if request and request.environ.get('HTTP_REFERER'): statement.context.extensions[ 'http://id.tincanapi.com/extension/browser-info'][ 'referer'] = request.environ.get('HTTP_REFERER') return statement
def assignment(cls, assignment, **kwargs): context = cls.basic(**kwargs) context.context_activities = ContextActivities( # parent is course parent=ActivityList( [Activity(id=XAPIResourceIRI.course(assignment.course_uuid))])) return context
def assignment(cls, assignment, **kwargs): context = cls.basic(**kwargs) context.context_activities = ContextActivities( # parent is course parent=ActivityList([XAPIObject.course(assignment.course)])) cls._add_sis_data(context, assignment.course) return context
def test_FromJSONEmptyObject(self): ctx_act = ContextActivities.from_json('{}') self.assertIsInstance(ctx_act, ContextActivities) self.assertEqual(vars(ctx_act), { '_category': None, '_grouping': None, '_other': None, '_parent': None })
def test_initEmpty(self): ctx_act = ContextActivities() self.assertIsInstance(ctx_act, ContextActivities) self.assertEqual(vars(ctx_act), { '_category': None, '_grouping': None, '_other': None, '_parent': None })
def get_context_activities(self, event): parent_activities = [ Activity(id='{}/courses/{}'.format(settings.OPENEDX_PLATFORM_URI, event['context']['course_id']), definition=course.CourseActivityDefinition(event)), Activity(id=event['referer'], definition=block.BlockActivityDefinition(event)) ] return ContextActivities(parent=ActivityList(parent_activities))
def assignment_question(cls, assignment, **kwargs): context = cls.basic(**kwargs) context.context_activities = ContextActivities( # parent is assignment parent=ActivityList([XAPIObject.assignment(assignment)]), # grouping is course grouping=ActivityList([XAPIObject.course(assignment.course)])) cls._add_sis_data(context, assignment.course) return context
def test_build_statement(self): """ The build_statement function should return a valid tincan Statement. """ user = UserFactory() verb = Verb( id="https://activitystrea.ms/schema/1.0/create", display=LanguageMap({"en-US": "created"}), ) activity = Activity( id=f"id://ashley/topic/{uuid.uuid4()}", definition=ActivityDefinition( name=LanguageMap({"en-US": "test topic"}), type="http://id.tincanapi.com/activitytype/discussion", ), ) context = Context(context_activities=ContextActivities(parent=[ Activity( id=f"uuid://{uuid.uuid4()}", definition=ActivityDefinition( name=LanguageMap({"en-US": "test forum"}), type="http://id.tincanapi.com/activitytype/community-site", ), ) ])) statement1 = build_statement(user, verb, activity, context) statement2 = build_statement(user, verb, activity, context) # The function should generate a random, non empty uuid as a # statement ID self.assertIsInstance(statement1.id, uuid.UUID) self.assertIsInstance(statement2.id, uuid.UUID) self.assertNotEqual(statement1.id, statement2.id) # The statement id can also be specified statement3_id = uuid.uuid4() statement3 = build_statement(user, verb, activity, context, statement3_id) self.assertEqual(statement3_id, statement3.id) # The verb, object and context should correspond to the given arguments self.assertEqual(statement1.verb, verb) self.assertEqual(statement1.object, activity) self.assertEqual(statement1.context, context) # The Actor part of the statement should reflect the user passed as an # argument self.assertEqual(statement1.actor.account.name, user.lti_remote_user_id) self.assertEqual(statement1.actor.account.home_page, user.lti_consumer.url)
def assignment_question(cls, assignment, **kwargs): context = cls.basic(**kwargs) context.context_activities = ContextActivities( # parent is assignment parent=ActivityList( [Activity(id=XAPIResourceIRI.assignment(assignment.uuid))]), # grouping is course grouping=ActivityList( [Activity(id=XAPIResourceIRI.course(assignment.course_uuid))])) return context
def track_forum_view(sender, forum, user, request, response, **kwargs): """Log a XAPI statement when a user views a forum.""" parent_activities = None consumer = getattr(user, "lti_consumer", None) if consumer is None: logger.warning("Unable to get LTI consumer of user %s", user) return xapi_logger = logging.getLogger(f"xapi.{user.lti_consumer.slug}") verb = Verb( id="http://id.tincanapi.com/verb/viewed", display=LanguageMap({"en-US": "viewed"}), ) obj = Activity( id=f"id://ashley/forum/{forum.pk}", definition=ActivityDefinition( name=LanguageMap( {to_locale(settings.LANGUAGE_CODE).replace("_", "-"): forum.name} ), type="http://id.tincanapi.com/activitytype/community-site", ), ) if request.forum_permission_handler.current_lti_context_id is not None: try: lti_context = LTIContext.objects.get( pk=request.forum_permission_handler.current_lti_context_id ) parent_activities = [ Activity( id=lti_context.lti_id, definition=ActivityDefinition( type="http://adlnet.gov/expapi/activities/course" ), ) ] except LTIContext.DoesNotExist: pass if parent_activities is not None: context = Context( context_activities=ContextActivities(parent=parent_activities), ) else: context = None statement = build_statement(user, verb, obj, context) if statement: xapi_logger.info(statement.to_json())
def test_InitAll(self): ctx = Context( registration=uuid.uuid4(), instructor=Group(member=[Agent(name='instructorGroupMember')]), team=Group(member=[Agent(name='teamGroupMember')]), context_activities=ContextActivities(category=Activity( id='contextActivityCategory')), revision='revision', platform='platform', language='en-US', statement=StatementRef(id='016699c6-d600-48a7-96ab-86187498f16f'), extensions=Extensions({'extensions': 'extend!'})) self.ctxVerificationHelper(ctx)
def _add_default(cls, user, statement): if not statement.timestamp: statement.timestamp = datetime.datetime.now().replace( tzinfo=pytz.utc).isoformat() if impersonation.is_impersonating() and user.id == current_user.id: statement.actor = XAPIActor.generate_actor( impersonation.get_impersonation_original_user()) else: statement.actor = XAPIActor.generate_actor(user) # add default context info if not statement.context: statement.context = Context() if not statement.context.context_activities: statement.context.context_activities = ContextActivities() if not statement.context.context_activities.category: statement.context.context_activities.category = ActivityList() statement.context.context_activities.category.append( XAPIActivity.compair_source()) statement.context.platform = XAPIResourceIRI.compair() if request and request.environ.get('HTTP_USER_AGENT'): if not statement.context.extensions: statement.context.extensions = Extensions() browser_info_key = XAPIExtension.context_extensions.get( 'browser information') statement.context.extensions[ browser_info_key] = request.environ.get('HTTP_USER_AGENT') if request and request.environ.get('HTTP_REFERER'): if not statement.context.extensions: statement.context.extensions = Extensions() referer_key = XAPIExtension.context_extensions.get('referer') statement.context.extensions[referer_key] = request.environ.get( 'HTTP_REFERER') if impersonation.is_impersonating() and user.id == current_user.id: if not statement.context.extensions: statement.context.extensions = Extensions() impersonating_as_key = XAPIExtension.context_extensions.get( 'impersonating as') statement.context.extensions[ impersonating_as_key] = XAPIActor.generate_actor(user) return statement
def answer_attachment(cls, answer, **kwargs): context = cls.basic(**kwargs) context.context_activities = ContextActivities( # parent is assignment answer parent=ActivityList([XAPIObject.answer(answer)]), # grouping is course + assignment + assignment question grouping=ActivityList([ XAPIObject.assignment_question(answer.assignment), XAPIObject.assignment(answer.assignment), XAPIObject.course(answer.assignment.course) ])) cls._add_sis_data(context, answer.assignment.course) return context
def test_InitAsEither(self): ctx_act = ContextActivities( category=ActivityList([Activity(id='categoryList')]), parent=Activity(id='parentActivity'), grouping=ActivityList([Activity(id='groupingList')]), other=Activity(id='otherActivity')) self.assertIsInstance(ctx_act, ContextActivities) self.assertIsInstance(ctx_act.category, ActivityList) self.assertEqual(ctx_act.category[0].id, 'categoryList') self.assertIsInstance(ctx_act.parent, ActivityList) self.assertEqual(ctx_act.parent[0].id, 'parentActivity') self.assertIsInstance(ctx_act.grouping, ActivityList) self.assertEqual(ctx_act.grouping[0].id, 'groupingList') self.assertIsInstance(ctx_act.other, ActivityList) self.assertEqual(ctx_act.other[0].id, 'otherActivity')
def get_context_activities(self, event): parent_activities = [ Activity(id='{}/courses/{}'.format(settings.OPENEDX_PLATFORM_URI, event['context']['course_id']), definition=course.CourseActivityDefinition(event)), ] parent = settings.OPENEDX_PLATFORM_URI + ':18010/container/' + event[ 'context']['parent']['usage_key'] #parent = event['context']['parent']['usage_key'] #FOR TEST parent_activities.append( Activity(id=parent, definition=block.BlockAssessmentDefinition( event['context']['parent'])), ) return ContextActivities(parent=ActivityList(parent_activities))
def self_evaluation_question(cls, answer_comment, **kwargs): context = cls.basic(**kwargs) context.context_activities = ContextActivities( # parent is assignment + answer parent=ActivityList([ Activity(id=XAPIResourceIRI.assignment( answer_comment.assignment_uuid)), Activity(id=XAPIResourceIRI.answer(answer_comment.answer_uuid)) ]), # grouping is course grouping=ActivityList([ Activity(id=XAPIResourceIRI.course(answer_comment.course_uuid)) ])) return context
def answer(cls, answer, **kwargs): context = cls.basic(**kwargs) context.context_activities = ContextActivities( # parent is assignment question parent=ActivityList([ Activity(id=XAPIResourceIRI.assignment_question( answer.assignment_uuid)) ]), # grouping is course + assignment grouping=ActivityList([ Activity(id=XAPIResourceIRI.course(answer.course_uuid)), Activity(id=XAPIResourceIRI.assignment(answer.assignment_uuid)) ])) return context
def _add_sis_data(cls, context, course): if course.lti_has_sis_data: if not context.context_activities: context.context_activities = ContextActivities() if not context.context_activities.grouping: context.context_activities.grouping = ActivityList() sis_data = course.lti_sis_data context.extensions = Extensions() if not context.extensions else context.extensions context.extensions['sis_courses'] = [] for sis_course_id, sis_section_ids in sis_data.items(): context.extensions['sis_courses'].append({ 'id': sis_course_id, 'section_ids': sis_section_ids })
def test_InitUnpack(self): obj = { 'category': [{ 'id': 'categoryList' }], 'parent': [{ 'id': 'parentList' }], 'grouping': [{ 'id': 'groupingList' }], 'other': [{ 'id': 'otherList' }] } ctx_act = ContextActivities(**obj) self.listVerificationHelper(ctx_act)
def comparison_attempt(cls, comparison, current_comparison, **kwargs): context = cls.basic(**kwargs) context.context_activities = ContextActivities( # parent is comparison question + criterion parent=ActivityList([ XAPIObject.comparison_question(comparison.assignment, current_comparison) ]), # grouping is course + assignment + answer1 + answer2 grouping=ActivityList([ XAPIObject.assignment(comparison.assignment), XAPIObject.course(comparison.assignment.course) ]) ) cls._add_sis_data(context, comparison.assignment.course) return context
def self_evaluation_attempt(cls, answer_comment, **kwargs): context = cls.basic(**kwargs) context.context_activities = ContextActivities( # parent is assignment parent=ActivityList([ XAPIObject.self_evaluation_question(answer_comment.answer.assignment) ]), # grouping is course grouping=ActivityList([ XAPIObject.assignment(answer_comment.answer.assignment), XAPIObject.course(answer_comment.answer.assignment.course) ]) ) cls._add_sis_data(context, answer_comment.answer.assignment.course) return context
def comparison(cls, comparison, **kwargs): context = cls.basic(**kwargs) context.context_activities = ContextActivities( # parent is comparison question + criterion parent=ActivityList([ Activity( id=XAPIResourceIRI.comparison_question(comparison.uuid)) ]), # grouping is course + assignment + answer1 + answer2 grouping=ActivityList([ Activity(id=XAPIResourceIRI.course(comparison.course_uuid)), Activity( id=XAPIResourceIRI.assignment(comparison.assignment_uuid)), Activity(id=XAPIResourceIRI.answer(comparison.answer1_uuid)), Activity(id=XAPIResourceIRI.answer(comparison.answer2_uuid)) ])) return context
def test_FromJSONActivity(self): ctx_act = ContextActivities.from_json('{"category": {"id": "categoryActivity"}, "parent": {"id": "parentActivity"}, "grouping": {"id": "groupingActivity"}, "other": {"id": "otherActivity"}}') self.activityVerificationHelper(ctx_act)
def test_FromJSONEmptyObject(self): ctx_act = ContextActivities.from_json('{}') self.assertIsInstance(ctx_act, ContextActivities) self.assertEqual(vars(ctx_act), {})
def test_FromJSONExceptionPartiallyMalformedJSON(self): with self.assertRaises(AttributeError): ctx_act = ContextActivities.from_json('{"category": {"id": "test"}, "test": "invalid property"}')
def test_FromJSONExceptionMalformedJSON(self): with self.assertRaises(AttributeError): ctx_act = ContextActivities.from_json('{"test": "invalid property"}')
def test_FromJSONList(self): ctx_act = ContextActivities.from_json('{"category": [{"id": "categoryList"}], "parent": [{"id": "parentList"}], "grouping": [{"id": "groupingList"}], "other": [{"id": "otherList"}]}') self.listVerificationHelper(ctx_act)
def test_FromJSONEmptyObject(self): ctx_act = ContextActivities.from_json('{}') self.assertIsInstance(ctx_act, ContextActivities) self.assertEqual(vars(ctx_act), {'_category': None, '_grouping': None, '_other': None, '_parent': None})