Commit a2056eba by Ali Mohammad

New interface tests for get_mod_date and get_mod_date_many.

parent 73640930
......@@ -160,7 +160,7 @@ class XBlockUserStateClient(object):
block_key="block_key",
scope=ScopeBase,
fields="seq(basestring)|set(basestring)|None",
returns="dict(basestring: datetime)",
returns=XBlockUserState,
modify_docstring=False,
)
def get_mod_date(self, username, block_key, scope=Scope.user_state, fields=None):
......@@ -172,16 +172,17 @@ class XBlockUserStateClient(object):
block_key: The key identifying which xblock modification dates to retrieve.
scope (Scope): The scope to retrieve from.
fields: A list of fields to query. If None, query all fields.
Specific implementations are free to return the same modification date
for all fields, if they don't store changes individually per field.
Implementations may omit fields for which data has not been stored.
Returns: dict of {field_name: modified_date} for each selected field.
Specific implementations are free to return the same modification date
for all fields, if they don't store changes individually per field.
Implementations may omit fields for which data has not been stored.
Returns: XBlockUserState instance. The updated attribute is a
guarantee that none of the fields have been modified since
then.
"""
results = self.get_mod_date_many(username, [block_key], scope, fields=fields)
return {
field: date for (_, field, date) in results
}
return results.next()
@contract(
username="basestring",
......@@ -266,12 +267,16 @@ class XBlockUserStateClient(object):
username: The name of the user whose state should be queried
block_key: The key identifying which xblock modification dates to retrieve.
scope (Scope): The scope to retrieve from.
fields: A list of fields to query. If None, delete all stored fields.
Specific implementations are free to return the same modification date
for all fields, if they don't store changes individually per field.
Implementations may omit fields for which data has not been stored.
fields: A list of fields to query. If None, returns dates for all
stored fields.
Specific implementations are free to return the same modification date
for all fields, if they don't store changes individually per field.
Implementations may omit fields for which data has not been stored.
Yields: tuples of (block, field_name, modified_date) for each selected field.
Yields: XBlockUserState instances with the requested fields for each
key. The updated attribute is a guarantee that none of the
fields have been modified since then.
"""
raise NotImplementedError()
......
......@@ -210,6 +210,38 @@ class _UserStateClientTestUtils(TestCase):
scope=self.scope,
)
@contract(user=int, block="int", fields="list(string)|None")
def get_mod_date(self, user, block, fields=None):
"""
Get the modification dates for the fields for the specified block.
This wraps :meth:`~XBlockUserStateClient.get_mod_date`
to take indexes rather than actual values, to make tests easier
to write concisely.
"""
return self.client.get_mod_date(
username=self._user(user),
block_key=self._block(block),
scope=self.scope,
fields=fields,
)
@contract(user=int, blocks="list(int)", fields="list(string)|None")
def get_mod_date_many(self, user, blocks, fields=None):
"""
Get the modification times for the specified user, blocks, and fields.
This wraps :meth:`~XBlockUserStateClient.get_mod_date_many`
to take indexes rather than actual values to make tests easier
to write concisely.
"""
return self.client.get_mod_date_many(
username=self._user(user),
block_keys=[self._block(block) for block in blocks],
scope=self.scope,
fields=fields,
)
class _UserStateClientTestCRUD(_UserStateClientTestUtils):
"""
......@@ -352,6 +384,41 @@ class _UserStateClientTestCRUD(_UserStateClientTestUtils):
self.delete_many(user=0, blocks=[0, 1], fields=['a', 'b'])
self.assertItemsEqual(self.get_many(user=0, blocks=[0, 1]), [])
def test_get_mod_date(self):
start_time = datetime.now()
self.set_many(user=0, block_to_state={0: {'a': 'b'}, 1: {'b': 'c'}})
end_time = datetime.now()
mod_dates = self.get_mod_date(user=0, block=0)
self.assertItemsEqual(mod_dates.state.keys(), ["a"])
self.assertGreater(mod_dates.updated, start_time)
self.assertLess(mod_dates.updated, end_time)
def test_get_mod_date_many(self):
start_time = datetime.now()
self.set_many(
user=0,
block_to_state={0: {'a': 'b'}, 1: {'b': 'c', 'c': 'd'}})
self.set_many(
user=0,
block_to_state={0: {'a': 'b2'}, 1: {'b': 'c2', 'c': 'd'}})
end_time = datetime.now()
mod_dates = list(self.get_mod_date_many(
user=0,
blocks=[0, 1],
fields=["b", "c"]))
self.assertItemsEqual(
[result.block_key for result in mod_dates],
[self._block(1)])
self.assertItemsEqual(
sorted(mod_dates[0].state.keys()),
["b", "c"])
self.assertGreater(mod_dates[0].updated, start_time)
self.assertLess(mod_dates[0].updated, end_time)
class _UserStateClientTestHistory(_UserStateClientTestUtils):
"""
......@@ -630,7 +697,31 @@ class DictUserStateClient(XBlockUserStateClient):
self._add_state(username, key, scope, state)
def get_mod_date_many(self, username, block_keys, scope=Scope.user_state, fields=None):
raise NotImplementedError()
for key in block_keys:
if (username, key, scope) not in self._history:
continue
entry = self._history[(username, key, scope)][0]
if entry.state is None:
continue
if fields is None:
current_fields = entry.state.keys()
else:
current_fields = fields
filtered_state = {
field: entry.state[field]
for field in current_fields
if field in entry.state
}
if len(filtered_state) > 0:
yield XBlockUserState(username,
key,
filtered_state,
entry.updated,
entry.scope)
def get_history(self, username, block_key, scope=Scope.user_state):
"""
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment