Example #1
0
def send_statement_without_timeout(statement, success, result):
    # construct an LRS
    lrs = RemoteLRS(
        version=settings.LRS_VERSION,
        endpoint=settings.LRS_ENDPOINT,
        auth=settings.LRS_AUTH,
    )
    try:
        # save our statement to the remote_lrs and store the response in 'response'
        lrs_response = lrs.save_statement(statement)
        if lrs_response:
            if lrs_response.success:
                try:
                    # retrieve our statement from the remote_lrs using the id returned in the response
                    lrs_response = lrs.retrieve_statement(
                        lrs_response.content.id)
                    if lrs_response.success:
                        result = lrs_response.content
                        success = True
                    else:
                        result = lrs_response.data
                except Exception as e:
                    result = e
            else:
                result = lrs_response.data
    except Exception as e:
        result = e
Example #2
0
    def _send_lrs_statements(cls, statements):
        if not cls.enabled:
            return

        # should only be called by delayed task send_lrs_statements
        lrs_settings = {
            'version': cls._version,
            'endpoint': current_app.config.get('LRS_STATEMENT_ENDPOINT')
        }

        if current_app.config.get('LRS_AUTH'):
            lrs_settings['auth'] = current_app.config.get('LRS_AUTH')
        else:
            lrs_settings['username'] = current_app.config.get('LRS_USERNAME')
            lrs_settings['password'] = current_app.config.get('LRS_PASSWORD')

        lrs =  RemoteLRS(**lrs_settings)
        try:
            lrs_response = lrs.save_statements(statements)

            if not lrs_response.success:
                current_app.logger.error("xAPI Failed with: " + str(lrs_response.data))
                current_app.logger.error("xAPI Request Body: " + lrs_response.request.content)

        except socket.error as error:
            if error.errno != socket.errno.ECONNREFUSED:
                raise error

            current_app.logger.error("xAPI Failed with: Connection refused")
            current_app.logger.error("xAPI Statements:")
            for statement in statements:
                current_app.logger.error(statement.to_json(cls._version))
Example #3
0
File: xapi.py Project: ubc/compair
    def _emit_to_lrs(cls, statement_json):
        if not cls.enabled:
            return

        # should only be called by delayed task send_lrs_statement
        lrs_settings = {
            'version': cls._version,
            'endpoint': current_app.config.get('LRS_XAPI_STATEMENT_ENDPOINT')
        }

        if current_app.config.get('LRS_XAPI_AUTH'):
            lrs_settings['auth'] = current_app.config.get('LRS_XAPI_AUTH')
        else:
            lrs_settings['username'] = current_app.config.get(
                'LRS_XAPI_USERNAME')
            lrs_settings['password'] = current_app.config.get(
                'LRS_XAPI_PASSWORD')

        statement = Statement(statement_json)
        lrs = RemoteLRS(**lrs_settings)
        lrs_response = lrs.save_statement(statement)

        if not lrs_response.success:
            current_app.logger.error("xAPI Failed with: " +
                                     str(lrs_response.data))
            current_app.logger.error("xAPI Request Body: " +
                                     lrs_response.request.content)
Example #4
0
    def setUp(self):
        self.endpoint = lrs_properties.endpoint
        self.version = lrs_properties.version
        self.username = lrs_properties.username
        self.password = lrs_properties.password
        self.lrs = RemoteLRS(
            version=self.version,
            endpoint=self.endpoint,
            username=self.username,
            password=self.password,
        )

        self.agent = Agent(mbox="mailto:[email protected]")
        self.agent2 = Agent(mbox="mailto:[email protected]")
        self.verb = Verb(id="http://adlnet.gov/expapi/verbs/experienced",
                         display=LanguageMap({"en-US": "experienced"}))

        self.group = Group(member=[self.agent, self.agent2])

        self.activity = Activity(
            id="http://tincanapi.com/TinCanPython/Test/Unit/0",
            definition=ActivityDefinition())
        self.activity.definition.type = "http://id.tincanapi.com/activitytype/unit-test"
        self.activity.definition.name = LanguageMap({"en-US": "Python Tests"})
        self.activity.definition.description = LanguageMap(
            {"en-US": "Unit test in the test suite for the Python library"})
        self.activity.object_type = 'Activity'

        self.parent = Activity(id="http://tincanapi.com/TinCanPython/Test",
                               definition=ActivityDefinition())
        self.parent.definition.type = "http://id.tincanapi.com/activitytype/unit-test-suite"
        self.parent.definition.name = LanguageMap({"en-US": "Python Tests"})
        self.parent.definition.description = LanguageMap(
            {"en-US": "Unit test in the test suite for the Python library"})
        self.parent.object_type = 'Activity'

        self.statement_ref = StatementRef(id=uuid.uuid4())

        self.context = Context(registration=uuid.uuid4(),
                               statement=self.statement_ref)
        # self.context.context_activities = ContextActivities(parent=[self.parent])

        self.score = Score(raw=97, scaled=0.97, max=100, min=0)

        self.result = Result(score=self.score,
                             success=True,
                             completion=True,
                             duration="PT120S")

        self.substatement = SubStatement(
            actor=self.agent,
            verb=self.verb,
            object=self.activity,
        )
def xApi(verb_id,verb_disp,extension_dict):
    
    #orismos LRS 
    lrs = RemoteLRS(
        version=lrs_actor.version,
        endpoint=lrs_actor.endpoint,
        username=lrs_actor.username,
        password=lrs_actor.password,
    )

    #orismos actor 
    actor=Agent(name=lrs_actor.actorName, mbox='mailto:'+lrs_actor.actorMail,) 
    #orimos verb
    verb = Verb(
                id=verb_id,
                display=LanguageMap({'en-US': verb_disp}),
                )
    #ορισμός object
    object = Activity(
                      id='https://pithos.okeanos.grnet.gr/public/8jiz0aVKZxjVI2CvNl7XV3',
                      definition=ActivityDefinition(
                    name=LanguageMap({'en-US': 'Python file'}),
                    description=LanguageMap({'en-US': 'A python source code file'}),
                    ),
                      )
    #ορισμος extension 
    extension=Extensions(extension_dict)
    #ορισμός context
    context = Context(extensions=extension)
    #Κατασκευή statement
    statement = Statement(
                          actor=actor,
                          verb=verb,
                          object=object,
                          context=context
                          )

    # save our statement to the remote_lrs and store the response in 'response'
    print "saving the Statement..."
    response = lrs.save_statement(statement)

    if not response:
        raise ValueError("statement failed to save")
        error_icon="images/error_icon.png"
#        msgbox("Can't save statement!\n Check the file: lrs_actor.py",title="Error!!!",image=error_icon)
        print "Can't save statement!!\n Check the file: lrs_actor.py"

    print "...done     verb: " ,verb_disp 
Example #6
0
    def _send_lrs_statement(cls, statement_json):
        if not cls.enabled:
            return

        # should only be called by delayed task send_lrs_statement
        lrs_settings = {
            'version': cls._version,
            'endpoint': current_app.config.get('LRS_STATEMENT_ENDPOINT')
        }

        if current_app.config.get('LRS_AUTH'):
            lrs_settings['auth'] = current_app.config.get('LRS_AUTH')
        else:
            lrs_settings['username'] = current_app.config.get('LRS_USERNAME')
            lrs_settings['password'] = current_app.config.get('LRS_PASSWORD')

        statement = Statement(statement_json)
        # check statement.result.response, object.definition.name, object.definition.description
        if statement.result and statement.result.response:
            statement.result.response = cls._trim_text_to_size(
                statement.result.response)
        if statement.object and statement.object.definition and statement.object.definition.name:
            statement.object.definition.name['en-US'] = cls._trim_text_to_size(
                statement.object.definition.name['en-US'])
        if statement.object and statement.object.definition and statement.object.definition.description:
            statement.object.definition.description[
                'en-US'] = cls._trim_text_to_size(
                    statement.object.definition.description['en-US'])

        lrs = RemoteLRS(**lrs_settings)
        lrs_response = lrs.save_statement(statement)

        if not lrs_response.success:
            current_app.logger.error("xAPI Failed with: " +
                                     str(lrs_response.data))
            current_app.logger.error("xAPI Request Body: " +
                                     lrs_response.request.content)
Example #7
0
 def _setup_LRSs(self):
     with open('lrs_config.json', 'r') as fi:
         llist = json.load(fi)
     for lrsconf in llist:
         obj = {'name': lrsconf['name'], 'online': True}
         if 'active' in lrsconf:
             obj['active'] = lrsconf['active']
             del (lrsconf['active'])
         else:
             obj['active'] = True
         del (lrsconf['name'])
         lrs = RemoteLRS(**lrsconf)
         obj['lrs'] = lrs
         #self._LRSs.append(lrs)
         self._LRSs.append(obj)
Example #8
0
    def test_about_failure(self):
        lrs = RemoteLRS(endpoint="http://cloud.scorm.com/tc/3TQLAI9/sandbox/")
        response = lrs.about()

        self.assertFalse(response.success)
Example #9
0
 def test_instantiation(self):
     lrs = RemoteLRS()
     self.assertIsInstance(lrs, RemoteLRS)
     self.assertIsNone(lrs.endpoint)
     self.assertIsNone(lrs.auth)
     self.assertEqual(Version.latest, lrs.version)
Example #10
0
    RemoteLRS,
    Statement,
    Agent,
    Verb,
    Activity,
    Context,
    LanguageMap,
    ActivityDefinition,
    StateDocument,
)

# construct an LRS
print "constructing the LRS..."
lrs = RemoteLRS(
    version=lrs_properties.version,
    endpoint=lrs_properties.endpoint,
    username=lrs_properties.username,
    password=lrs_properties.password,
)
print "...done"

# construct the actor of the statement
print "constructing the Actor..."
actor = Agent(
    name='UserMan',
    mbox='mailto:[email protected]',
)
print "...done"

# construct the verb of the statement
print "constructing the Verb..."
verb = Verb(
Example #11
0
def put_statement(request, user, verb, object, target, language=XAPI_LANGUAGE):

    # construct an LRS
    lrs = RemoteLRS(
        version=settings.LRS_VERSION,
        endpoint=settings.LRS_ENDPOINT,
        auth=settings.LRS_AUTH,
    )

    # construct the actor of the statement
    # IMPORTANT - account is OK but cannot coexist with mbox or other way of uniquely identifying the actor
    try:
        actor = Agent(
            name=user.get_display_name(),
            mbox='mailto:%s' % user.email,
            # account=AgentAccount(name=str(user.pk), home_page='https://www.commonspaces.eu')
        )
    except:
        return False

    # construct the verb of the statement
    verb = XAPI_VERB_ALIASES.get(verb,
                                 verb)  # for compatibility with CommonSpaces
    verb = Verb(
        id=xapi_verbs[verb]['id'],
        display=LanguageMap(**xapi_verbs[verb]['display']),
    )

    action = object.__class__.__name__
    action = XAPI_ACTIVITY_ALIASES.get(
        action, action)  # for compatibility with CommonSpaces
    activity_type = xapi_activities[action]['type']
    object_id = get_object_id(request,
                              object)  # 190307 GT: defined get_object_id
    object_name = get_name(object)  # 190307 GT: defined get_name
    object_description = get_description(object)
    object_language = get_language(object)
    activity_definition = ActivityDefinition(
        name=LanguageMap(**{object_language: object_name}),
        description=object_description
        and LanguageMap(**{object_language: object_description}) or None,
        type=activity_type,
    )

    # construct the object of the statement
    object = Activity(
        id=object_id,
        definition=activity_definition,
    )

    context = {'platform': XAPI_PLATFORM, 'language': get_current_language()}
    """ 190308 GT: would produce the exception "Object of type 'UUID' is not JSON serializable" in getting the response
    if request:
        context['registration'] = str(get_registration(request))
    """
    if target:
        target_type = target.__class__.__name__
        context_activities = {}
        if target_type in ['Folder', 'Forum', 'LearningPath']:
            context_activities['parent'] = {
                'objectType': 'Activity',
                'id': get_object_id(request, target),
                'definition': {
                    'type':
                    xapi_activities[XAPI_ACTIVITY_ALIASES.get(
                        target_type, target_type)]['type'],
                    'name': {
                        'en': get_name(target)
                    }
                }
            }
            if target_type == 'Folder':
                project = target.get_project()
                if project:
                    context_activities['grouping'] = get_context_grouping(
                        request, project)
            elif target_type == 'Forum':
                # project = target.forum_get_project()
                project = target.get_project()
                if project:
                    context_activities['grouping'] = get_context_grouping(
                        request, project)
            elif target_type == 'LearningPath':
                if target.project:
                    context_activities['grouping'] = get_context_grouping(
                        request, target.project)
        elif target_type == 'Project':
            context_activities['grouping'] = get_context_grouping(
                request, target)
        if context_activities:
            context['context_activities'] = context_activities
    context = Context(**context)

    # construct the actual statement
    statement = Statement(
        actor=actor,
        verb=verb,
        object=object,
        context=context,
    )
    return send_statement(statement)
Example #12
0
statement_number = 1  # keep number order for statements
# Identifiers
machine_id, student_hash, partner_hash, input_type = _init_id()
session_id = None  # Session ID, Initialized in initialize_tracing()
# Tracing behaviour
tracing_enabled = None  # Enable user to enable/disable tracing, Initialized in initialize_tracing()
send_to_LRS = config.send_to_LRS  # Send the created statements to the LRS
debug_log_print = config.debug_log_print  # Keep Log of statements and Print messages related to tracing
# Error and function data
error_groups = config.error_groups
function_names_context = config.function_names_context
# Timestamps
opened_timestamp = None  # Opened app
last_typing_timestamp = None  # Last typed in editor
last_interacting_timestamp = None  # Last interacted with software
start_execution_timestamp = None  # Last execution start

#
# xAPI and LRS setup
#
lrs = RemoteLRS(
    version=config.lrs_version,
    endpoint=config.lrs_endpoint,
    username=config.lrs_username,
    password=config.lrs_password,
    proxy_name=config.proxy_name,
    proxy_port=config.proxy_port)
actor = _create_actor()
verbs = config.verbs
activities = config.activities
Example #13
0
#
# global variables used during tracing
#
statement_number = 1  # keep number order for statements
# Identifiers
machine_id, student_hash, partner_hash, input_type = _init_id()
session_id = None  # Session ID, Initialized in initialize_tracing()
# Tracing behaviour
tracing_enabled = None  # Enable user to enable/disable tracing, Initialized in initialize_tracing()
send_to_LRS = config.send_to_LRS  # Send the created statements to the LRS
debug_log_print = config.debug_log_print  # Keep Log of statements and Print messages related to tracing
# Error and function data
error_groups = config.error_groups
function_names_context = config.function_names_context
# Timestamps
opened_timestamp = None  # Opened app
last_typing_timestamp = None  # Last typed in editor
last_interacting_timestamp = None  # Last interacted with software
start_execution_timestamp = None  # Last execution start

#
# xAPI and LRS setup
#
lrs = RemoteLRS(version=config.lrs_version,
                endpoint=config.lrs_endpoint,
                username=config.lrs_username,
                password=config.lrs_password)
actor = _create_actor()
verbs = config.verbs
activities = config.activities
class LRSClient:

    # config LRS endpoint and auth info here
    LRS = RemoteLRS(
        version="1.0.1",
        endpoint="http://localhost/learninglocker/public/data/xAPI/",
        username="******",
        password="******"
    )

    verbs = {
        "selected": "http://id.tincanapi.com/verb/selected",
        "access": "http://activitystrea.ms/schema/1.0/access",
        "experienced": "http://adlnet.gov/expapi/verbs/experienced",
        "listen": "http://activitystrea.ms/schema/1.0/listen",
        "answered": "http://adlnet.gov/expapi/verbs/answered",
        "requested": "https://w3id.org/xapi/adb/verbs/requested",
        "logged-in": "https://w3id.org/xapi/adl/verbs/logged-in",
        "logged-out": "https://w3id.org/xapi/adl/verbs/logged-out",
        "create": "http://activitystrea.ms/schema/1.0/create",
        "delete": "http://activitystrea.ms/schema/1.0/delete",
        "update": "http://activitystrea.ms/schema/1.0/update",
        "completed": "http://adlnet.gov/expapi/verbs/completed",
        "consume": "http://activitystrea.ms/schema/1.0/consume",
        "earned": "http://id.tincanapi.com/verb/earned",
        "passed": "http://adlnet.gov/expapi/verbs/passed",
        "failed": "http://adlnet.gov/expapi/verbs/failed",
        "launched": "http://adlnet.gov/expapi/verbs/launched",
        "start": "http://activitystrea.ms/schema/1.0/start",
        "leave": "http://activitystrea.ms/schema/1.0/leave",
        "paused": "http://id.tincanapi.com/verb/paused",
        "resumed": "http://adlnet.gov/expapi/verbs/resumed",
        "terminated": "http://adlnet.gov/expapi/verbs/terminated"
    }

    objects = {
        "resource": "http://id.tincanapi.com/activitytype/resource"
    }

    extensions = {
        "topic": "http://id.tincanapi.com/extension/topic",
        "interaction": "http://id.tincanapi.com/extension/interaction",
        "difficulty": "http://id.tincanapi.com/extension/difficulty",
        "feedback": "http://id.tincanapi.com/extension/feedback"
    }

    def sendStatement(self, reqData):
        #load requested data for statement generation
        data = json.loads(reqData)

        # create RemoteLRS endpoint
        lrs = self.LRS

        # generate statement

        # 1. actor
        actor = Agent(
            name=data["name"],
            mbox='mailto:' + data["name"] + '@id.lrs',
        )

        # 2. verb
        verb = Verb(
            id=self.verbs.get(data["verb"]),
            display=LanguageMap({'en-US': data["verb"]}),
        )

        # 3. object
        obj = Activity(
            id=self.objects.get(data["activity"]),
            definition=ActivityDefinition(
                name=LanguageMap({'en-US': data["activityid"]})
            )
        )

        # 4. context
        context = Context(
            extensions=Extensions({
                self.extensions.get("difficulty"): data["difficulty"],
                self.extensions.get("interaction"): data["interaction"],
                self.extensions.get("topic"): data["topic"]
            })
        )

        # 5. result
        result = Result(
            score=Score(
                raw=data["score"]
            ),
            success=data["success"]
        )

        # build statement
        statement = Statement(
            actor=actor,
            verb=verb,
            object=obj,
            context=context,
            result=result
        )

        # save statement
        response = lrs.save_statement(statement)

        # check response
        if not response:
            raise ValueError("statement failed to save")
        return str(True)

    # returns statements of an user
    def getStatements(self, name):

        # connect LRS
        lrs = self.LRS

        # specify user as agent
        actor = Agent(
            name=name,
            mbox='mailto:' + name + '@id.lrs',
        )

        # optional specify verb
        verb = Verb(
            id=self.verbs.get("experienced"),
            display=LanguageMap({'en-US': 'experienced'}),
        )

        query = {
            "agent": actor,
            #"verb": verb,
            "limit": 1000 #change limit if needed
        }

        # query LRS for statements
        response = lrs.query_statements(query)

        # check response
        if not response:
            raise ValueError("statements could not be queried")

        # return queried statements
        return response
Example #15
0
#	Nice formatting + Headings		#
#####################################
print "=" * 43
print " " * 3 + " MOAT project's moodle xAPI importer " + " " * 9
print "=" * 43
print ""
# Print settings

#####################################
#	Construct actual connections	#
#####################################
print "Creating Connections"
sys.stdout.write("\tLRS Connection...")
sys.stdout.flush()
lrs = RemoteLRS(version=config.LRS_VERSION,
                endpoint=config.LRS_ENDPOINT,
                username=config.LRS_USERNAME,
                password=config.LRS_PASSWORD)
print "done"
##
sys.stdout.write("\tMoodle Connection...")
sys.stdout.flush()
try:
    conn = psycopg2.connect(database=config.DB_NAME,
                            user=config.DB_USER,
                            password=config.DB_PASS,
                            host=config.DB_HOST)
    cur = conn.cursor('cursor_one',
                      cursor_factory=psycopg2.extras.RealDictCursor)
    cur.itersize = config.ITER_SIZE
    cur2 = conn.cursor(cursor_factory=psycopg2.extras.RealDictCursor)
except:
Example #16
0
class RemoteLRSTest(unittest.TestCase):
    def setUp(self):
        self.endpoint = lrs_properties.endpoint
        self.version = lrs_properties.version
        self.username = lrs_properties.username
        self.password = lrs_properties.password
        self.lrs = RemoteLRS(
            version=self.version,
            endpoint=self.endpoint,
            username=self.username,
            password=self.password,
        )

        self.agent = Agent(mbox="mailto:[email protected]")
        self.agent2 = Agent(mbox="Agent2.mailto:[email protected]")
        self.verb = Verb(
            id="http://adlnet.gov/expapi/verbs/experienced",
            display=LanguageMap({"en-US": "experienced"})
        )

        self.group = Group(member=[self.agent, self.agent2])

        self.activity = Activity(
            id="http://tincanapi.com/TinCanPython/Test/Unit/0",
            definition=ActivityDefinition()
        )
        self.activity.definition.type = "http://id.tincanapi.com/activitytype/unit-test"
        self.activity.definition.name = LanguageMap({"en-US": "Python Tests"})
        self.activity.definition.description = LanguageMap(
            {"en-US": "Unit test in the test suite for the Python library"}
        )
        self.activity.object_type = 'Activity'

        self.parent = Activity(
            id="http://tincanapi.com/TinCanPython/Test",
            definition=ActivityDefinition())
        self.parent.definition.type = "http://id.tincanapi.com/activitytype/unit-test-suite"
        self.parent.definition.name = LanguageMap({"en-US": "Python Tests"})
        self.parent.definition.description = LanguageMap(
            {"en-US": "Unit test in the test suite for the Python library"}
        )
        self.parent.object_type = 'Activity'

        self.statement_ref = StatementRef(id=uuid.uuid4())

        self.context = Context(registration=uuid.uuid4(), statement=self.statement_ref)
        # self.context.context_activities = ContextActivities(parent=[self.parent])

        self.score = Score(
            raw=97,
            scaled=0.97,
            max=100,
            min=0
        )

        self.result = Result(
            score=self.score,
            success=True,
            completion=True,
            duration="PT120S"
        )

        self.substatement = SubStatement(
            actor=self.agent,
            verb=self.verb,
            object=self.activity,
        )

    def tearDown(self):
        pass

    def test_instantiation(self):
        lrs = RemoteLRS()
        self.assertIsInstance(lrs, RemoteLRS)
        self.assertIsNone(lrs.endpoint)
        self.assertIsNone(lrs.auth)
        self.assertEqual(Version.latest, lrs.version)

    def test_about(self):
        response = self.lrs.about()

        self.assertIsInstance(response, LRSResponse)
        self.assertTrue(response.success)
        self.assertIsInstance(response.content, About)

    def test_about_failure(self):
        lrs = RemoteLRS(endpoint="http://cloud.scorm.com/tc/3TQLAI9/sandbox/")
        response = lrs.about()

        self.assertFalse(response.success)

    def test_save_statement(self):
        statement = Statement(
            actor=self.agent,
            verb=self.verb,
            object=self.activity
        )
        response = self.lrs.save_statement(statement)

        self.assertIsInstance(response, LRSResponse)
        self.assertTrue(response.success)
        self.assertIsNotNone(response.content.id)
        self._vars_verifier(statement, response.content, ['_authority', '_stored'])

    def test_save_statement_with_id(self):
        statement = Statement(
            actor=self.agent,
            verb=self.verb,
            object=self.activity,
            id=str(uuid.uuid4())
        )
        response = self.lrs.save_statement(statement)

        self.assertIsInstance(response, LRSResponse)
        self.assertTrue(response.success)
        self._vars_verifier(statement, response.content)

    def test_save_statement_conflict(self):
        test_id = unicode(uuid.uuid4())

        statement1 = Statement(
            actor=self.agent,
            verb=self.verb,
            object=self.substatement,
            id=test_id
        )
        statement2 = Statement(
            actor=self.agent2,
            verb=self.verb,
            object=self.substatement,
            id=test_id
        )
        response = self.lrs.save_statement(statement1)

        self.assertIsInstance(response, LRSResponse)
        self.assertTrue(response.success)

        response = self.lrs.save_statement(statement2)

        self.assertIsInstance(response, LRSResponse)
        self.assertFalse(response.success)
        self.assertEquals(response.response.status, 409)

    def test_save_statement_ref(self):
        statement = Statement(
            actor=self.agent,
            verb=self.verb,
            object=self.statement_ref,
            id=str(uuid.uuid4())
        )
        response = self.lrs.save_statement(statement)

        self.assertIsInstance(response, LRSResponse)
        self.assertTrue(response.success)
        self._vars_verifier(statement, response.content, ['_authority', '_stored'])

    def test_save_statement_group(self):
        statement = Statement(
            actor=self.agent,
            verb=self.verb,
            object=self.group,
            id=str(uuid.uuid4())
        )
        response = self.lrs.save_statement(statement)

        self.assertIsInstance(response, LRSResponse)
        self.assertTrue(response.success)
        self._vars_verifier(statement, response.content)

    def test_save_statement_substatement(self):
        statement = Statement(
            actor=self.agent,
            verb=self.verb,
            object=self.substatement,
            id=str(uuid.uuid4())
        )
        response = self.lrs.save_statement(statement)

        self.assertIsInstance(response, LRSResponse)
        self.assertTrue(response.success)
        self._vars_verifier(statement, response.content, ['_authority', '_stored'])

    def test_save_statements(self):
        statement1 = Statement(
            actor=self.agent,
            verb=self.verb,
            object=self.activity
        )
        statement2 = Statement(
            actor=self.agent,
            verb=self.verb,
            object=self.activity,
            context=self.context
        )
        response = self.lrs.save_statements([statement1, statement2])

        self.assertIsInstance(response, LRSResponse)
        self.assertTrue(response.success)
        self.assertIsNotNone(response.content[0].id)
        self.assertIsNotNone(response.content[1].id)
        self._vars_verifier(statement1, response.content[0], ['_authority', '_stored'])
        self._vars_verifier(statement2, response.content[1], ['_authority', '_stored'])

    @unittest.skip("LRS truncates timestamps which makes returned statements evaluate not equal")
    def test_retrieve_statement(self):
        id_str = str(uuid.uuid4())
        statement = Statement(
            actor=self.agent,
            verb=self.verb,
            object=self.activity,
            context=self.context,
            result=self.result,
            id=id_str,
            version=Version.latest,
            timestamp=utc.localize(datetime.utcnow())
        )
        save_resp = self.lrs.save_statement(statement)

        self.assertTrue(save_resp.success)
        response = self.lrs.retrieve_statement(save_resp.content.id)
        self.assertIsInstance(response, LRSResponse)
        self.assertTrue(response.success)
        self._vars_verifier(response.content, statement, ['_authority', '_stored'])

    def test_retrieve_statement_no_microsecond(self):
        id_str = str(uuid.uuid4())
        dt = utc.localize(datetime.utcnow())
        statement = Statement(
            actor=self.agent,
            verb=self.verb,
            object=self.activity,
            context=self.context,
            result=self.result,
            id=id_str,
            version=Version.latest,
            timestamp=dt
        )
        save_resp = self.lrs.save_statement(statement)

        self.assertTrue(save_resp.success)
        response = self.lrs.retrieve_statement(save_resp.content.id)
        self.assertIsInstance(response, LRSResponse)
        self.assertTrue(response.success)
        self._vars_verifier(response.content, statement, ['_authority', '_stored'])

    @unittest.skip("LRS truncates timestamps which makes returned statements evaluate not equal")
    def test_query_statements(self):
        tstamp = utc.localize(datetime.utcnow())
        s1 = Statement(
            actor=self.agent,
            verb=self.verb,
            object=self.parent,
            result=self.result,
            id=str(uuid.uuid4()),
            timestamp=tstamp
        )
        self.lrs.save_statement(s1)

        s2 = Statement(
            actor=self.agent,
            verb=self.verb,
            object=self.parent,
            result=self.result,
            id=str(uuid.uuid4()),
            timestamp=tstamp
        )
        self.lrs.save_statement(s2)

        s3 = Statement(
            actor=self.agent,
            verb=self.verb,
            object=self.parent,
            result=self.result,
            id=str(uuid.uuid4()),
            timestamp=tstamp
        )
        self.lrs.save_statement(s3)

        query = {
            "agent": self.agent,
            "verb": self.verb,
            "activity": self.parent,
            "related_activities": True,
            "related_agents": True,
            "limit": 2
        }
        response = self.lrs.query_statements(query)

        self.assertIsInstance(response, LRSResponse)
        self.assertTrue(response.success)
        self.assertIsInstance(response.content, StatementsResult)
        self.assertTrue(hasattr(response.content, 'more'))
        self.assertIsNotNone(response.content.more)
        self._vars_verifier(s1, response.content.statements[0])
        self._vars_verifier(s2, response.content.statements[1])

    def test_query_statements_no_microsecond(self):
        tstamp = utc.localize(datetime.utcnow())
        s1 = Statement(
            actor=self.agent,
            verb=self.verb,
            object=self.parent,
            result=self.result,
            id=str(uuid.uuid4()),
            timestamp=tstamp
        )
        self.lrs.save_statement(s1)

        s2 = Statement(
            actor=self.agent,
            verb=self.verb,
            object=self.parent,
            result=self.result,
            id=str(uuid.uuid4()),
            timestamp=tstamp
        )
        self.lrs.save_statement(s2)

        s3 = Statement(
            actor=self.agent,
            verb=self.verb,
            object=self.parent,
            result=self.result,
            id=str(uuid.uuid4()),
            timestamp=tstamp
        )
        self.lrs.save_statement(s3)

        query = {
            "agent": self.agent,
            "verb": self.verb,
            "activity": self.parent,
            "related_activities": True,
            "related_agents": True,
            "limit": 2
        }
        response = self.lrs.query_statements(query)

        self.assertIsInstance(response, LRSResponse)
        self.assertTrue(response.success)
        self.assertIsInstance(response.content, StatementsResult)
        self.assertTrue(hasattr(response.content, 'more'))
        self.assertIsNotNone(response.content.more)
        self._vars_verifier(s1, response.content.statements[0])
        self._vars_verifier(s2, response.content.statements[1])

    def test_query_none(self):
        query = {
            "agent": self.agent,
            "verb": self.verb,
            "activity": self.parent,
            "related_activities": True,
            "related_agents": True,
            "format": "ids",
            "limit": 2,
            "registration": unicode(uuid.uuid4()),
        }
        response = self.lrs.query_statements(query)

        self.assertIsInstance(response, LRSResponse)
        self.assertTrue(response.success)
        self.assertIsInstance(response.content, StatementsResult)
        self.assertTrue(hasattr(response.content, 'more'))
        self.assertTrue(hasattr(response.content, 'statements'))
        self.assertEquals(response.content.statements, [])

    def test_more_statements(self):
        s1 = Statement(
            actor=self.agent,
            verb=self.verb,
            object=self.parent,
            result=self.result,
            id=str(uuid.uuid4())
        )
        self.lrs.save_statement(s1)

        s2 = Statement(
            actor=self.agent,
            verb=self.verb,
            object=self.parent,
            result=self.result,
            id=str(uuid.uuid4())
        )
        self.lrs.save_statement(s2)

        s3 = Statement(
            actor=self.agent,
            verb=self.verb,
            object=self.parent,
            result=self.result,
            id=str(uuid.uuid4())
        )
        self.lrs.save_statement(s3)

        query = {
            "agent": self.agent,
            "verb": self.verb,
            "activity": self.parent,
            "related_activities": True,
            "related_agents": True,
            "format": "ids",
            "limit": 2
        }
        query_resp = self.lrs.query_statements(query)

        self.assertIsInstance(query_resp, LRSResponse)
        self.assertTrue(query_resp.success)
        self.assertIsNotNone(query_resp.content.more)

        response = self.lrs.more_statements(query_resp.content)
        self.assertIsInstance(response, LRSResponse)
        self.assertTrue(response.success)
        self.assertIsInstance(response.content, StatementsResult)

    def test_retrieve_state_ids(self):
        response = self.lrs.retrieve_state_ids(activity=self.activity, agent=self.agent)
        self.assertIsInstance(response, LRSResponse)
        self.assertTrue(response.success)

    def test_retrieve_state(self):
        response = self.lrs.retrieve_state(
            activity=self.activity,
            agent=self.agent,
            state_id="test"
        )
        self.assertIsInstance(response, LRSResponse)
        self.assertTrue(response.success)

    def test_save_state(self):
        doc = StateDocument(
            activity=self.activity,
            agent=self.agent,
            id="test",
            content=bytearray("Test value", encoding="utf-8")
        )
        saveResp = self.lrs.save_state(doc)

        self.assertIsInstance(saveResp, LRSResponse)
        self.assertTrue(saveResp.success)

        response = self.lrs.retrieve_state(
            activity=self.activity,
            agent=self.agent,
            state_id="test"
        )
        self.assertIsInstance(response, LRSResponse)
        self.assertTrue(response.success)
        self._vars_verifier(response.content, doc)

    def test_delete_state(self):
        doc = StateDocument(
            activity=self.activity,
            agent=self.agent,
            id="test"
        )
        response = self.lrs.delete_state(doc)

        self.assertIsInstance(response, LRSResponse)
        self.assertTrue(response.success)

    def test_clear_state(self):
        response = self.lrs.clear_state(activity=self.activity, agent=self.agent)

        self.assertIsInstance(response, LRSResponse)
        self.assertTrue(response.success)

    def test_retrieve_activity_profile_ids(self):
        response = self.lrs.retrieve_activity_profile_ids(activity=self.activity)

        self.assertIsInstance(response, LRSResponse)
        self.assertTrue(response.success)

    def test_retrieve_activity_profile(self):
        response = self.lrs.retrieve_activity_profile(activity=self.activity, profile_id="test")

        self.assertIsInstance(response, LRSResponse)
        self.assertTrue(response.success)

    def test_save_activity_profile(self):
        doc = ActivityProfileDocument(
            activity=self.activity,
            id="test",
            content=bytearray("Test value", encoding="utf-8")
        )
        saveResp = self.lrs.save_activity_profile(doc)

        self.assertIsInstance(saveResp, LRSResponse)
        self.assertTrue(saveResp.success)

        response = self.lrs.retrieve_activity_profile(
            activity=self.activity,
            profile_id="test"
        )
        self.assertIsInstance(response, LRSResponse)
        self.assertTrue(response.success)
        self._vars_verifier(response.content, doc)

    def test_delete_activity_profile(self):
        doc = ActivityProfileDocument(activity=self.activity, id="test")
        response = self.lrs.delete_activity_profile(doc)

        self.assertIsInstance(response, LRSResponse)
        self.assertTrue(response.success)

    def test_retrieve_agent_profile_ids(self):
        response = self.lrs.retrieve_agent_profile_ids(self.agent)
        self.assertIsInstance(response, LRSResponse)
        self.assertTrue(response.success)

    def test_retrieve_agent_profile(self):
        response = self.lrs.retrieve_agent_profile(agent=self.agent, profile_id="test")
        self.assertIsInstance(response, LRSResponse)
        self.assertTrue(response.success)

    def test_save_agent_profile(self):
        doc = AgentProfileDocument(
            agent=self.agent,
            id="test",
            content=bytearray("Test value", encoding="utf-8")
        )
        saveResp = self.lrs.save_agent_profile(doc)
        self.assertIsInstance(saveResp, LRSResponse)
        self.assertTrue(saveResp.success)

        response = self.lrs.retrieve_agent_profile(
            agent=self.agent,
            profile_id="test"
        )
        self.assertIsInstance(response, LRSResponse)
        self.assertTrue(response.success)
        self._vars_verifier(response.content, doc)

    def test_delete_agent_profile(self):
        doc = AgentProfileDocument(agent=self.agent, id="test")
        response = self.lrs.delete_agent_profile(doc)

        self.assertIsInstance(response, LRSResponse)
        self.assertTrue(response.success)

    def _vars_verifier(self, obj1, obj2, _ignored_attrs=None):
        if _ignored_attrs is None:
            _ignored_attrs = ['_authority', '_stored', '_id']
        for k, v in vars(obj1).iteritems():
            if k in _ignored_attrs:
                continue
            elif isinstance(v, datetime):
                dt1 = getattr(obj1, k)
                dt2 = getattr(obj2, k)
                ts1 = timegm(dt1.timetuple())
                ts2 = timegm(dt2.timetuple())
                self.assertEqual(ts1, ts2)

                #
                # dealing in math operations on the microsecond was too much of a pain,
                # and the value should be truncated as opposed to rounded so it is just
                # as easy to deal with it in string form, so convert to string, zero pad
                # to 6 characters, then truncate to only the first 3 of those characters
                # and then string compare
                #
                self.assertEqual(str(dt1.microsecond).zfill(6)[:3], str(dt2.microsecond).zfill(6)[:3])
            elif isinstance(v, Base):
                self._vars_verifier(getattr(obj1, k), getattr(obj2, k))
            else:
                self.assertEqual(getattr(obj1, k), getattr(obj2, k))
    def setUp(self):
        self.endpoint = lrs_properties.endpoint
        self.version = lrs_properties.version
        self.username = lrs_properties.username
        self.password = lrs_properties.password
        self.lrs = RemoteLRS(
            version=self.version,
            endpoint=self.endpoint,
            username=self.username,
            password=self.password,
        )

        self.agent = Agent(mbox="mailto:[email protected]")
        self.agent2 = Agent(mbox="Agent2.mailto:[email protected]")
        self.verb = Verb(
            id="http://adlnet.gov/expapi/verbs/experienced",
            display=LanguageMap({"en-US": "experienced"})
        )

        self.group = Group(member=[self.agent, self.agent2])

        self.activity = Activity(
            id="http://tincanapi.com/TinCanPython/Test/Unit/0",
            definition=ActivityDefinition()
        )
        self.activity.definition.type = "http://id.tincanapi.com/activitytype/unit-test"
        self.activity.definition.name = LanguageMap({"en-US": "Python Tests"})
        self.activity.definition.description = LanguageMap(
            {"en-US": "Unit test in the test suite for the Python library"}
        )
        self.activity.object_type = 'Activity'

        self.parent = Activity(
            id="http://tincanapi.com/TinCanPython/Test",
            definition=ActivityDefinition())
        self.parent.definition.type = "http://id.tincanapi.com/activitytype/unit-test-suite"
        self.parent.definition.name = LanguageMap({"en-US": "Python Tests"})
        self.parent.definition.description = LanguageMap(
            {"en-US": "Unit test in the test suite for the Python library"}
        )
        self.parent.object_type = 'Activity'

        self.statement_ref = StatementRef(id=uuid.uuid4())

        self.context = Context(registration=uuid.uuid4(), statement=self.statement_ref)
        # self.context.context_activities = ContextActivities(parent=[self.parent])

        self.score = Score(
            raw=97,
            scaled=0.97,
            max=100,
            min=0
        )

        self.result = Result(
            score=self.score,
            success=True,
            completion=True,
            duration="PT120S"
        )

        self.substatement = SubStatement(
            actor=self.agent,
            verb=self.verb,
            object=self.activity,
        )
        verb=verb,
        object=object,
        context=context,
    )


if __name__ == '__main__':
    import fileinput
    import sys

    csv_entries = (l.strip() for l in fileinput.input())

    remote_lrs = RemoteLRS(
        endpoint=lrs['endpoint'],
        # RemoteLRS uses HTTP Basic Auth
        # so username, password will be sent out
        # with the authorization header.
        username=lrs['username'],
        password=lrs['password'],
    )

    for csv_entry in csv_entries:
        try:
            statement = create_statement(csv_entry)
        except ValueError, e:
            # ignore invalid entries
            print("Failed to create statement for %s with the error: %s" %
                  (csv_entry, e),
                  file=sys.stderr)
            continue
        # XXX: Look out for response == None
        # and possibly add the statement to a retry queue