diff --git a/common/lib/xmodule/xmodule/assetstore/__init__.py b/common/lib/xmodule/xmodule/assetstore/__init__.py index 2143a36f48..6a98fa40ec 100644 --- a/common/lib/xmodule/xmodule/assetstore/__init__.py +++ b/common/lib/xmodule/xmodule/assetstore/__init__.py @@ -15,6 +15,7 @@ new_contract('AssetKey', AssetKey) new_contract('CourseKey', CourseKey) new_contract('datetime', datetime) new_contract('basestring', basestring) +new_contract('long', long) new_contract('AssetElement', lambda x: isinstance(x, etree._Element) and x.tag == "asset") # pylint: disable=protected-access, no-member new_contract('AssetsElement', lambda x: isinstance(x, etree._Element) and x.tag == "assets") # pylint: disable=protected-access, no-member @@ -54,8 +55,8 @@ class AssetMetadata(object): locked='bool|None', contenttype='basestring|None', thumbnail='basestring|None', fields='dict|None', curr_version='basestring|None', prev_version='basestring|None', - created_by='int|None', created_by_email='basestring|None', created_on='datetime|None', - edited_by='int|None', edited_by_email='basestring|None', edited_on='datetime|None') + created_by='int|long|None', created_by_email='basestring|None', created_on='datetime|None', + edited_by='int|long|None', edited_by_email='basestring|None', edited_on='datetime|None') def __init__(self, asset_id, pathname=None, internal_name=None, locked=None, contenttype=None, diff --git a/common/lib/xmodule/xmodule/modulestore/mixed.py b/common/lib/xmodule/xmodule/modulestore/mixed.py index 0ce363c483..24e68ea143 100644 --- a/common/lib/xmodule/xmodule/modulestore/mixed.py +++ b/common/lib/xmodule/xmodule/modulestore/mixed.py @@ -27,6 +27,7 @@ new_contract('CourseKey', CourseKey) new_contract('AssetKey', AssetKey) new_contract('AssetMetadata', AssetMetadata) new_contract('LibraryLocator', LibraryLocator) +new_contract('long', long) log = logging.getLogger(__name__) @@ -351,14 +352,14 @@ class MixedModuleStore(ModuleStoreDraftAndPublished, ModuleStoreWriteBase): store = self._get_modulestore_for_courseid(course_key) return store.delete_course(course_key, user_id) - @contract(asset_metadata='AssetMetadata', user_id=int, import_only=bool) + @contract(asset_metadata='AssetMetadata', user_id='int|long', import_only=bool) def save_asset_metadata(self, asset_metadata, user_id, import_only=False): """ Saves the asset metadata for a particular course's asset. Args: asset_metadata (AssetMetadata): data about the course asset data - user_id (int): user ID saving the asset metadata + user_id (int|long): user ID saving the asset metadata import_only (bool): True if importing without editing, False if editing Returns: @@ -367,7 +368,7 @@ class MixedModuleStore(ModuleStoreDraftAndPublished, ModuleStoreWriteBase): store = self._get_modulestore_for_courseid(asset_metadata.asset_id.course_key) return store.save_asset_metadata(asset_metadata, user_id, import_only) - @contract(asset_metadata_list='list(AssetMetadata)', user_id=int, import_only=bool) + @contract(asset_metadata_list='list(AssetMetadata)', user_id='int|long', import_only=bool) def save_asset_metadata_list(self, asset_metadata_list, user_id, import_only=False): """ Saves the asset metadata for each asset in a list of asset metadata. @@ -375,7 +376,7 @@ class MixedModuleStore(ModuleStoreDraftAndPublished, ModuleStoreWriteBase): Args: asset_metadata_list (list(AssetMetadata)): list of data about several course assets - user_id (int): user ID saving the asset metadata + user_id (int|long): user ID saving the asset metadata import_only (bool): True if importing without editing, False if editing Returns: @@ -424,13 +425,14 @@ class MixedModuleStore(ModuleStoreDraftAndPublished, ModuleStoreWriteBase): store = self._get_modulestore_for_courseid(course_key) return store.get_all_asset_metadata(course_key, asset_type, start, maxresults, sort, **kwargs) - @contract(asset_key='AssetKey') + @contract(asset_key='AssetKey', user_id='int|long') def delete_asset_metadata(self, asset_key, user_id): """ Deletes a single asset's metadata. Arguments: asset_id (AssetKey): locator containing original asset filename + user_id (int_long): user deleting the metadata Returns: Number of asset metadata entries deleted (0 or 1) @@ -438,7 +440,7 @@ class MixedModuleStore(ModuleStoreDraftAndPublished, ModuleStoreWriteBase): store = self._get_modulestore_for_courseid(asset_key.course_key) return store.delete_asset_metadata(asset_key, user_id) - @contract(source_course_key='CourseKey', dest_course_key='CourseKey') + @contract(source_course_key='CourseKey', dest_course_key='CourseKey', user_id='int|long') def copy_all_asset_metadata(self, source_course_key, dest_course_key, user_id): """ Copy all the course assets from source_course_key to dest_course_key. @@ -446,6 +448,7 @@ class MixedModuleStore(ModuleStoreDraftAndPublished, ModuleStoreWriteBase): Arguments: source_course_key (CourseKey): identifier of course to copy from dest_course_key (CourseKey): identifier of course to copy to + user_id (int|long): user copying the asset metadata """ source_store = self._get_modulestore_for_courseid(source_course_key) dest_store = self._get_modulestore_for_courseid(dest_course_key) @@ -463,7 +466,7 @@ class MixedModuleStore(ModuleStoreDraftAndPublished, ModuleStoreWriteBase): # Courses in the same modulestore can be handled by the modulestore itself. source_store.copy_all_asset_metadata(source_course_key, dest_course_key, user_id) - @contract(asset_key='AssetKey', attr=str) + @contract(asset_key='AssetKey', attr=str, user_id='int|long') def set_asset_metadata_attr(self, asset_key, attr, value, user_id): """ Add/set the given attr on the asset at the given location. Value can be any type which pymongo accepts. @@ -472,6 +475,7 @@ class MixedModuleStore(ModuleStoreDraftAndPublished, ModuleStoreWriteBase): asset_key (AssetKey): asset identifier attr (str): which attribute to set value: the value to set it to (any type pymongo accepts such as datetime, number, string) + user_id: (int|long): user setting the attribute Raises: NotFoundError if no such item exists @@ -480,7 +484,7 @@ class MixedModuleStore(ModuleStoreDraftAndPublished, ModuleStoreWriteBase): store = self._get_modulestore_for_courseid(asset_key.course_key) return store.set_asset_metadata_attrs(asset_key, {attr: value}, user_id) - @contract(asset_key='AssetKey', attr_dict=dict) + @contract(asset_key='AssetKey', attr_dict=dict, user_id='int|long') def set_asset_metadata_attrs(self, asset_key, attr_dict, user_id): """ Add/set the given dict of attrs on the asset at the given location. Value can be any type which pymongo accepts. @@ -488,6 +492,7 @@ class MixedModuleStore(ModuleStoreDraftAndPublished, ModuleStoreWriteBase): Arguments: asset_key (AssetKey): asset identifier attr_dict (dict): attribute/value pairs to set + user_id: (int|long): user setting the attributes Raises: NotFoundError if no such item exists diff --git a/common/lib/xmodule/xmodule/modulestore/mongo/base.py b/common/lib/xmodule/xmodule/modulestore/mongo/base.py index f417086274..5753e49b67 100644 --- a/common/lib/xmodule/xmodule/modulestore/mongo/base.py +++ b/common/lib/xmodule/xmodule/modulestore/mongo/base.py @@ -57,6 +57,7 @@ log = logging.getLogger(__name__) new_contract('CourseKey', CourseKey) new_contract('AssetKey', AssetKey) new_contract('AssetMetadata', AssetMetadata) +new_contract('long', long) # sort order that returns DRAFT items first SORT_REVISION_FAVOR_DRAFT = ('_id.revision', pymongo.DESCENDING) @@ -1517,14 +1518,14 @@ class MongoModuleStore(ModuleStoreDraftAndPublished, ModuleStoreWriteBase, Mongo """ return 'assets.{}'.format(asset_type) - @contract(asset_metadata_list='list(AssetMetadata)', user_id=int) + @contract(asset_metadata_list='list(AssetMetadata)', user_id='int|long') def _save_asset_metadata_list(self, asset_metadata_list, user_id, import_only): """ Internal; saves the info for a particular course's asset. Arguments: asset_metadata_list (list(AssetMetadata)): list of data about several course assets - user_id (int): user ID saving the asset metadata + user_id (int|long): user ID saving the asset metadata import_only (bool): True if edited_on/by data should remain unchanged. """ course_assets = self._find_course_assets(asset_metadata_list[0].asset_id.course_key) @@ -1563,14 +1564,14 @@ class MongoModuleStore(ModuleStoreDraftAndPublished, ModuleStoreWriteBase, Mongo ) return True - @contract(asset_metadata='AssetMetadata', user_id=int) + @contract(asset_metadata='AssetMetadata', user_id='int|long') def save_asset_metadata(self, asset_metadata, user_id, import_only=False): """ Saves the info for a particular course's asset. Arguments: asset_metadata (AssetMetadata): data about the course asset data - user_id (int): user ID saving the asset metadata + user_id (int|long): user ID saving the asset metadata import_only (bool): True if importing without editing, False if editing Returns: @@ -1578,7 +1579,7 @@ class MongoModuleStore(ModuleStoreDraftAndPublished, ModuleStoreWriteBase, Mongo """ return self._save_asset_metadata_list([asset_metadata, ], user_id, import_only) - @contract(asset_metadata_list='list(AssetMetadata)', user_id=int) + @contract(asset_metadata_list='list(AssetMetadata)', user_id='int|long') def save_asset_metadata_list(self, asset_metadata_list, user_id, import_only=False): """ Saves the asset metadata for each asset in a list of asset metadata. @@ -1586,7 +1587,7 @@ class MongoModuleStore(ModuleStoreDraftAndPublished, ModuleStoreWriteBase, Mongo Args: asset_metadata (AssetMetadata): data about the course asset data - user_id (int): user ID saving the asset metadata + user_id (int|long): user ID saving the asset metadata import_only (bool): True if importing without editing, False if editing Returns: @@ -1594,7 +1595,7 @@ class MongoModuleStore(ModuleStoreDraftAndPublished, ModuleStoreWriteBase, Mongo """ return self._save_asset_metadata_list(asset_metadata_list, user_id, import_only) - @contract(source_course_key='CourseKey', dest_course_key='CourseKey') + @contract(source_course_key='CourseKey', dest_course_key='CourseKey', user_id='int|long') def copy_all_asset_metadata(self, source_course_key, dest_course_key, user_id): """ Copy all the course assets from source_course_key to dest_course_key. @@ -1613,7 +1614,7 @@ class MongoModuleStore(ModuleStoreDraftAndPublished, ModuleStoreWriteBase, Mongo # Update the document. self.asset_collection.insert(dest_assets) - @contract(asset_key='AssetKey', attr_dict=dict) + @contract(asset_key='AssetKey', attr_dict=dict, user_id='int|long') def set_asset_metadata_attrs(self, asset_key, attr_dict, user_id): """ Add/set the given dict of attrs on the asset at the given location. Value can be any type which pymongo accepts. @@ -1644,7 +1645,7 @@ class MongoModuleStore(ModuleStoreDraftAndPublished, ModuleStoreWriteBase, Mongo {"$set": {self._make_mongo_asset_key(asset_key.asset_type): all_assets}} ) - @contract(asset_key='AssetKey') + @contract(asset_key='AssetKey', user_id='int|long') def delete_asset_metadata(self, asset_key, user_id): """ Internal; deletes a single asset's metadata. @@ -1670,7 +1671,7 @@ class MongoModuleStore(ModuleStoreDraftAndPublished, ModuleStoreWriteBase, Mongo return 1 # pylint: disable=unused-argument - @contract(course_key='CourseKey') + @contract(course_key='CourseKey', user_id='int|long') def delete_all_asset_metadata(self, course_key, user_id): """ Delete all of the assets which use this course_key as an identifier. diff --git a/common/lib/xmodule/xmodule/modulestore/tests/test_assetstore.py b/common/lib/xmodule/xmodule/modulestore/tests/test_assetstore.py index 7e9bfc747f..6152cd59f9 100644 --- a/common/lib/xmodule/xmodule/modulestore/tests/test_assetstore.py +++ b/common/lib/xmodule/xmodule/modulestore/tests/test_assetstore.py @@ -25,6 +25,7 @@ class AssetStoreTestData(object): """ now = datetime.now(pytz.utc) user_id = 144 + user_id_long = long(user_id) user_email = "me@example.com" asset_fields = ( @@ -33,10 +34,10 @@ class AssetStoreTestData(object): 'curr_version', 'prev_version' ) all_asset_data = ( - ('pic1.jpg', 'EKMND332DDBK', 'pix/archive', False, user_id, user_email, now, user_id, user_email, now, '14', '13'), + ('pic1.jpg', 'EKMND332DDBK', 'pix/archive', False, user_id_long, user_email, now, user_id_long, user_email, now, '14', '13'), ('shout.ogg', 'KFMDONSKF39K', 'sounds', True, user_id, user_email, now, user_id, user_email, now, '1', None), ('code.tgz', 'ZZB2333YBDMW', 'exercises/14', False, user_id * 2, user_email, now, user_id * 2, user_email, now, 'AB', 'AA'), - ('dog.png', 'PUPY4242X', 'pictures/animals', True, user_id * 3, user_email, now, user_id * 3, user_email, now, '5', '4'), + ('dog.png', 'PUPY4242X', 'pictures/animals', True, user_id_long * 3, user_email, now, user_id_long * 3, user_email, now, '5', '4'), ('not_here.txt', 'JJJCCC747', '/dev/null', False, user_id * 4, user_email, now, user_id * 4, user_email, now, '50', '49'), ('asset.txt', 'JJJCCC747858', '/dev/null', False, user_id * 4, user_email, now, user_id * 4, user_email, now, '50', '49'), ('roman_history.pdf', 'JASDUNSADK', 'texts/italy', True, user_id * 7, user_email, now, user_id * 7, user_email, now, '1.1', '1.01'),