INCR-226 run modernize on common/lib/xmodule/xmodule/modulestore/mong… (#20431)
* INCR-226 run modernize on common/lib/xmodule/xmodule/modulestore/mongo, split_mongo, and perf_tests * fix pep8 error
This commit is contained in:
committed by
Michael Youngstrom
parent
7688581acc
commit
ba993c5937
@@ -2,8 +2,9 @@
|
||||
Provide names as exported by older mongo.py module
|
||||
"""
|
||||
|
||||
from xmodule.modulestore.mongo.base import MongoModuleStore, MongoKeyValueStore
|
||||
from __future__ import absolute_import
|
||||
|
||||
from xmodule.modulestore.mongo.base import MongoKeyValueStore, MongoModuleStore
|
||||
# Backwards compatibility for prod systems that refererence
|
||||
# xmodule.modulestore.mongo.DraftMongoModuleStore
|
||||
from xmodule.modulestore.mongo.draft import DraftModuleStore as DraftMongoModuleStore
|
||||
|
||||
@@ -11,47 +11,48 @@ structure:
|
||||
'definition.children': <list of all child text_type(location)s>
|
||||
}
|
||||
"""
|
||||
import six
|
||||
from __future__ import absolute_import
|
||||
|
||||
import copy
|
||||
from datetime import datetime
|
||||
from importlib import import_module
|
||||
import logging
|
||||
import pymongo
|
||||
import re
|
||||
import sys
|
||||
from datetime import datetime
|
||||
from importlib import import_module
|
||||
from uuid import uuid4
|
||||
|
||||
import pymongo
|
||||
import six
|
||||
from bson.son import SON
|
||||
from contracts import contract, new_contract
|
||||
from fs.osfs import OSFS
|
||||
from mongodb_proxy import autoretry_read
|
||||
from opaque_keys.edx.keys import UsageKey, CourseKey, AssetKey
|
||||
from opaque_keys.edx.keys import AssetKey, CourseKey, UsageKey
|
||||
from opaque_keys.edx.locator import BlockUsageLocator, CourseLocator, LibraryLocator
|
||||
from path import Path as path
|
||||
from pytz import UTC
|
||||
from xblock.core import XBlock
|
||||
from xblock.exceptions import InvalidScopeError
|
||||
from xblock.fields import Scope, ScopeIds, Reference, ReferenceList, ReferenceValueDict
|
||||
from xblock.fields import Reference, ReferenceList, ReferenceValueDict, Scope, ScopeIds
|
||||
from xblock.runtime import KvsFieldData
|
||||
|
||||
from xmodule.assetstore import AssetMetadata, CourseAssetsFromStorage
|
||||
from xmodule.course_module import CourseSummary
|
||||
from xmodule.error_module import ErrorDescriptor
|
||||
from xmodule.errortracker import null_error_tracker, exc_info_to_str
|
||||
from xmodule.errortracker import exc_info_to_str, null_error_tracker
|
||||
from xmodule.exceptions import HeartbeatFailure
|
||||
from xmodule.mako_module import MakoDescriptorSystem
|
||||
from xmodule.mongo_utils import connect_to_mongodb, create_collection_index
|
||||
from xmodule.modulestore import ModuleStoreWriteBase, ModuleStoreEnum, BulkOperationsMixin, BulkOpsRecord
|
||||
from xmodule.modulestore.draft_and_published import ModuleStoreDraftAndPublished, DIRECT_ONLY_CATEGORIES
|
||||
from xmodule.modulestore import BulkOperationsMixin, BulkOpsRecord, ModuleStoreEnum, ModuleStoreWriteBase
|
||||
from xmodule.modulestore.draft_and_published import DIRECT_ONLY_CATEGORIES, ModuleStoreDraftAndPublished
|
||||
from xmodule.modulestore.edit_info import EditInfoRuntimeMixin
|
||||
from xmodule.modulestore.exceptions import ItemNotFoundError, DuplicateCourseError, ReferentialIntegrityError
|
||||
from xmodule.modulestore.inheritance import InheritanceMixin, inherit_metadata, InheritanceKeyValueStore
|
||||
from xmodule.partitions.partitions_service import PartitionService
|
||||
from xmodule.modulestore.xml import CourseLocationManager
|
||||
from xmodule.modulestore.exceptions import DuplicateCourseError, ItemNotFoundError, ReferentialIntegrityError
|
||||
from xmodule.modulestore.inheritance import InheritanceKeyValueStore, InheritanceMixin, inherit_metadata
|
||||
from xmodule.modulestore.store_utilities import DETACHED_XBLOCK_TYPES
|
||||
from xmodule.modulestore.xml import CourseLocationManager
|
||||
from xmodule.mongo_utils import connect_to_mongodb, create_collection_index
|
||||
from xmodule.partitions.partitions_service import PartitionService
|
||||
from xmodule.services import SettingsService
|
||||
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
new_contract('CourseKey', CourseKey)
|
||||
@@ -183,10 +184,10 @@ class CachingDescriptorSystem(MakoDescriptorSystem, EditInfoRuntimeMixin):
|
||||
def __repr__(self):
|
||||
return "CachingDescriptorSystem{!r}".format((
|
||||
self.modulestore,
|
||||
unicode(self.course_id),
|
||||
[unicode(key) for key in self.module_data.keys()],
|
||||
six.text_type(self.course_id),
|
||||
[six.text_type(key) for key in self.module_data.keys()],
|
||||
self.default_class,
|
||||
[unicode(key) for key in self.cached_metadata.keys()],
|
||||
[six.text_type(key) for key in self.cached_metadata.keys()],
|
||||
))
|
||||
|
||||
def __init__(self, modulestore, course_key, module_data, default_class, cached_metadata, **kwargs):
|
||||
@@ -265,7 +266,7 @@ class CachingDescriptorSystem(MakoDescriptorSystem, EditInfoRuntimeMixin):
|
||||
parent = None
|
||||
if self.cached_metadata is not None:
|
||||
# fish the parent out of here if it's available
|
||||
parent_url = self.cached_metadata.get(unicode(location), {}).get('parent', {}).get(
|
||||
parent_url = self.cached_metadata.get(six.text_type(location), {}).get('parent', {}).get(
|
||||
ModuleStoreEnum.Branch.published_only if location.branch is None
|
||||
else ModuleStoreEnum.Branch.draft_preferred
|
||||
)
|
||||
@@ -281,7 +282,7 @@ class CachingDescriptorSystem(MakoDescriptorSystem, EditInfoRuntimeMixin):
|
||||
)
|
||||
|
||||
data = definition.get('data', {})
|
||||
if isinstance(data, basestring):
|
||||
if isinstance(data, six.string_types):
|
||||
data = {'data': data}
|
||||
|
||||
mixed_class = self.mixologist.mix(class_)
|
||||
@@ -305,7 +306,7 @@ class CachingDescriptorSystem(MakoDescriptorSystem, EditInfoRuntimeMixin):
|
||||
|
||||
# Convert the serialized fields values in self.cached_metadata
|
||||
# to python values
|
||||
metadata_to_inherit = self.cached_metadata.get(unicode(non_draft_loc), {})
|
||||
metadata_to_inherit = self.cached_metadata.get(six.text_type(non_draft_loc), {})
|
||||
inherit_metadata(module, metadata_to_inherit)
|
||||
|
||||
module._edit_info = json_data.get('edit_info')
|
||||
@@ -351,7 +352,7 @@ class CachingDescriptorSystem(MakoDescriptorSystem, EditInfoRuntimeMixin):
|
||||
:param jsonfields: a dict of the jsonified version of the fields
|
||||
"""
|
||||
result = {}
|
||||
for field_name, value in jsonfields.iteritems():
|
||||
for field_name, value in six.iteritems(jsonfields):
|
||||
field = class_.fields.get(field_name)
|
||||
if field is None:
|
||||
continue
|
||||
@@ -365,7 +366,7 @@ class CachingDescriptorSystem(MakoDescriptorSystem, EditInfoRuntimeMixin):
|
||||
]
|
||||
elif isinstance(field, ReferenceValueDict):
|
||||
result[field_name] = {
|
||||
key: self._convert_reference_to_key(subvalue) for key, subvalue in value.iteritems()
|
||||
key: self._convert_reference_to_key(subvalue) for key, subvalue in six.iteritems(value)
|
||||
}
|
||||
else:
|
||||
result[field_name] = value
|
||||
@@ -516,17 +517,17 @@ class ParentLocationCache(dict):
|
||||
"""
|
||||
# pylint: disable=missing-docstring
|
||||
|
||||
@contract(key=unicode)
|
||||
@contract(key=six.text_type)
|
||||
def has(self, key):
|
||||
return key in self
|
||||
|
||||
@contract(key=unicode, value="BlockUsageLocator | None")
|
||||
@contract(key=six.text_type, value="BlockUsageLocator | None")
|
||||
def set(self, key, value):
|
||||
self[key] = value
|
||||
|
||||
@contract(value="BlockUsageLocator")
|
||||
def delete_by_value(self, value):
|
||||
keys_to_delete = [k for k, v in self.iteritems() if v == value]
|
||||
keys_to_delete = [k for k, v in six.iteritems(self) if v == value]
|
||||
for key in keys_to_delete:
|
||||
del self[key]
|
||||
|
||||
@@ -720,7 +721,7 @@ class MongoModuleStore(ModuleStoreDraftAndPublished, ModuleStoreWriteBase, Mongo
|
||||
# manually pick it apart b/c the db has tag and we want as_published revision regardless
|
||||
location = as_published(BlockUsageLocator._from_deprecated_son(result['_id'], course_id.run))
|
||||
|
||||
location_url = unicode(location)
|
||||
location_url = six.text_type(location)
|
||||
if location_url in results_by_url:
|
||||
# found either draft or live to complement the other revision
|
||||
# FIXME this is wrong. If the child was moved in draft from one parent to the other, it will
|
||||
@@ -777,12 +778,12 @@ class MongoModuleStore(ModuleStoreDraftAndPublished, ModuleStoreWriteBase, Mongo
|
||||
course_id = self.fill_in_run(course_id)
|
||||
if not force_refresh:
|
||||
# see if we are first in the request cache (if present)
|
||||
if self.request_cache is not None and unicode(course_id) in self.request_cache.data.get('metadata_inheritance', {}):
|
||||
return self.request_cache.data['metadata_inheritance'][unicode(course_id)]
|
||||
if self.request_cache is not None and six.text_type(course_id) in self.request_cache.data.get('metadata_inheritance', {}):
|
||||
return self.request_cache.data['metadata_inheritance'][six.text_type(course_id)]
|
||||
|
||||
# then look in any caching subsystem (e.g. memcached)
|
||||
if self.metadata_inheritance_cache_subsystem is not None:
|
||||
tree = self.metadata_inheritance_cache_subsystem.get(unicode(course_id), {})
|
||||
tree = self.metadata_inheritance_cache_subsystem.get(six.text_type(course_id), {})
|
||||
else:
|
||||
logging.warning(
|
||||
'Running MongoModuleStore without a metadata_inheritance_cache_subsystem. This is \
|
||||
@@ -795,7 +796,7 @@ class MongoModuleStore(ModuleStoreDraftAndPublished, ModuleStoreWriteBase, Mongo
|
||||
|
||||
# now write out computed tree to caching subsystem (e.g. memcached), if available
|
||||
if self.metadata_inheritance_cache_subsystem is not None:
|
||||
self.metadata_inheritance_cache_subsystem.set(unicode(course_id), tree)
|
||||
self.metadata_inheritance_cache_subsystem.set(six.text_type(course_id), tree)
|
||||
|
||||
# now populate a request_cache, if available. NOTE, we are outside of the
|
||||
# scope of the above if: statement so that after a memcache hit, it'll get
|
||||
@@ -805,7 +806,7 @@ class MongoModuleStore(ModuleStoreDraftAndPublished, ModuleStoreWriteBase, Mongo
|
||||
# defined
|
||||
if 'metadata_inheritance' not in self.request_cache.data:
|
||||
self.request_cache.data['metadata_inheritance'] = {}
|
||||
self.request_cache.data['metadata_inheritance'][unicode(course_id)] = tree
|
||||
self.request_cache.data['metadata_inheritance'][six.text_type(course_id)] = tree
|
||||
|
||||
return tree
|
||||
|
||||
@@ -1022,7 +1023,7 @@ class MongoModuleStore(ModuleStoreDraftAndPublished, ModuleStoreWriteBase, Mongo
|
||||
for course_key in course_keys:
|
||||
course_query = {
|
||||
'_id.{}'.format(value_attr): getattr(course_key, key_attr)
|
||||
for key_attr, value_attr in {'org': 'org', 'course': 'course', 'run': 'name'}.iteritems()
|
||||
for key_attr, value_attr in six.iteritems({'org': 'org', 'course': 'course', 'run': 'name'})
|
||||
}
|
||||
course_query.update(query)
|
||||
course_queries.append(course_query)
|
||||
@@ -1148,8 +1149,8 @@ class MongoModuleStore(ModuleStoreDraftAndPublished, ModuleStoreWriteBase, Mongo
|
||||
location = course_key.make_usage_key('course', course_key.run)
|
||||
if ignore_case:
|
||||
course_query = location.to_deprecated_son('_id.')
|
||||
for key in course_query.iterkeys():
|
||||
if isinstance(course_query[key], basestring):
|
||||
for key in six.iterkeys(course_query):
|
||||
if isinstance(course_query[key], six.string_types):
|
||||
course_query[key] = re.compile(r"(?i)^{}$".format(course_query[key]))
|
||||
else:
|
||||
course_query = {'_id': location.to_deprecated_son()}
|
||||
@@ -1273,9 +1274,9 @@ class MongoModuleStore(ModuleStoreDraftAndPublished, ModuleStoreWriteBase, Mongo
|
||||
qualifier_value = {'$in': qualifier_value}
|
||||
query['_id.' + field] = qualifier_value
|
||||
|
||||
for key, value in (settings or {}).iteritems():
|
||||
for key, value in six.iteritems((settings or {})):
|
||||
query['metadata.' + key] = value
|
||||
for key, value in (content or {}).iteritems():
|
||||
for key, value in six.iteritems((content or {})):
|
||||
query['definition.data.' + key] = value
|
||||
if 'children' in qualifiers:
|
||||
query['definition.children'] = qualifiers.pop('children')
|
||||
@@ -1395,7 +1396,7 @@ class MongoModuleStore(ModuleStoreDraftAndPublished, ModuleStoreWriteBase, Mongo
|
||||
for_parent=kwargs.get('for_parent'),
|
||||
)
|
||||
if fields is not None:
|
||||
for key, value in fields.iteritems():
|
||||
for key, value in six.iteritems(fields):
|
||||
setattr(xmodule, key, value)
|
||||
# decache any pending field settings from init
|
||||
xmodule.save()
|
||||
@@ -1551,7 +1552,7 @@ class MongoModuleStore(ModuleStoreDraftAndPublished, ModuleStoreWriteBase, Mongo
|
||||
parent_cache = self._get_parent_cache(self.get_branch_setting())
|
||||
parent_cache.delete_by_value(xblock.location)
|
||||
for child in xblock.children:
|
||||
parent_cache.set(unicode(child), xblock.location)
|
||||
parent_cache.set(six.text_type(child), xblock.location)
|
||||
|
||||
self._update_single_item(xblock.scope_ids.usage_id, payload, allow_not_found=allow_not_found)
|
||||
|
||||
@@ -1585,19 +1586,19 @@ class MongoModuleStore(ModuleStoreDraftAndPublished, ModuleStoreWriteBase, Mongo
|
||||
:param jsonfields: a dict of the jsonified version of the fields
|
||||
"""
|
||||
jsonfields = {}
|
||||
for field_name, field in xblock.fields.iteritems():
|
||||
for field_name, field in six.iteritems(xblock.fields):
|
||||
if field.scope == scope and field.is_set_on(xblock):
|
||||
if field.scope == Scope.parent:
|
||||
continue
|
||||
elif isinstance(field, Reference):
|
||||
jsonfields[field_name] = unicode(field.read_from(xblock))
|
||||
jsonfields[field_name] = six.text_type(field.read_from(xblock))
|
||||
elif isinstance(field, ReferenceList):
|
||||
jsonfields[field_name] = [
|
||||
unicode(ele) for ele in field.read_from(xblock)
|
||||
six.text_type(ele) for ele in field.read_from(xblock)
|
||||
]
|
||||
elif isinstance(field, ReferenceValueDict):
|
||||
jsonfields[field_name] = {
|
||||
key: unicode(subvalue) for key, subvalue in field.read_from(xblock).iteritems()
|
||||
key: six.text_type(subvalue) for key, subvalue in six.iteritems(field.read_from(xblock))
|
||||
}
|
||||
else:
|
||||
jsonfields[field_name] = field.read_json(xblock)
|
||||
@@ -1648,19 +1649,19 @@ class MongoModuleStore(ModuleStoreDraftAndPublished, ModuleStoreWriteBase, Mongo
|
||||
or revision == ModuleStoreEnum.RevisionOption.draft_preferred
|
||||
|
||||
parent_cache = self._get_parent_cache(self.get_branch_setting())
|
||||
if parent_cache.has(unicode(location)):
|
||||
return parent_cache.get(unicode(location))
|
||||
if parent_cache.has(six.text_type(location)):
|
||||
return parent_cache.get(six.text_type(location))
|
||||
|
||||
# create a query with tag, org, course, and the children field set to the given location
|
||||
query = self._course_key_to_son(location.course_key)
|
||||
query['definition.children'] = unicode(location)
|
||||
query['definition.children'] = six.text_type(location)
|
||||
|
||||
# if only looking for the PUBLISHED parent, set the revision in the query to None
|
||||
if revision == ModuleStoreEnum.RevisionOption.published_only:
|
||||
query['_id.revision'] = MongoRevisionKey.published
|
||||
|
||||
def cache_and_return(parent_loc): # pylint:disable=missing-docstring
|
||||
parent_cache.set(unicode(location), parent_loc)
|
||||
parent_cache.set(six.text_type(location), parent_loc)
|
||||
return parent_loc
|
||||
|
||||
# query the collection, sorting by DRAFT first
|
||||
@@ -1753,7 +1754,7 @@ class MongoModuleStore(ModuleStoreDraftAndPublished, ModuleStoreWriteBase, Mongo
|
||||
if item['_id']['category'] != 'course':
|
||||
# It would be nice to change this method to return UsageKeys instead of the deprecated string.
|
||||
item_locs.add(
|
||||
unicode(as_published(BlockUsageLocator._from_deprecated_son(item['_id'], course_key.run)))
|
||||
six.text_type(as_published(BlockUsageLocator._from_deprecated_son(item['_id'], course_key.run)))
|
||||
)
|
||||
all_reachable = all_reachable.union(item.get('definition', {}).get('children', []))
|
||||
item_locs -= all_reachable
|
||||
@@ -1811,7 +1812,7 @@ class MongoModuleStore(ModuleStoreDraftAndPublished, ModuleStoreWriteBase, Mongo
|
||||
else:
|
||||
# Complete course key, so query for asset metadata.
|
||||
course_assets = self.asset_collection.find_one(
|
||||
{'course_id': unicode(course_key)},
|
||||
{'course_id': six.text_type(course_key)},
|
||||
)
|
||||
|
||||
doc_id = None if course_assets is None else course_assets['_id']
|
||||
@@ -1821,7 +1822,7 @@ class MongoModuleStore(ModuleStoreDraftAndPublished, ModuleStoreWriteBase, Mongo
|
||||
raise ItemNotFoundError(course_key)
|
||||
else:
|
||||
# Course exists, so create matching assets document.
|
||||
course_assets = {'course_id': unicode(course_key), 'assets': {}}
|
||||
course_assets = {'course_id': six.text_type(course_key), 'assets': {}}
|
||||
doc_id = self.asset_collection.insert(course_assets)
|
||||
elif isinstance(course_assets['assets'], list):
|
||||
# This record is in the old course assets format.
|
||||
@@ -1858,7 +1859,7 @@ class MongoModuleStore(ModuleStoreDraftAndPublished, ModuleStoreWriteBase, Mongo
|
||||
|
||||
# Build an update set with potentially multiple embedded fields.
|
||||
updates_by_type = {}
|
||||
for asset_type, assets in assets_by_type.iteritems():
|
||||
for asset_type, assets in six.iteritems(assets_by_type):
|
||||
updates_by_type[self._make_mongo_asset_key(asset_type)] = list(assets)
|
||||
|
||||
# Update the document.
|
||||
@@ -1911,8 +1912,8 @@ class MongoModuleStore(ModuleStoreDraftAndPublished, ModuleStoreWriteBase, Mongo
|
||||
dest_course_key (CourseKey): identifier of course to copy to
|
||||
"""
|
||||
source_assets = self._find_course_assets(source_course_key)
|
||||
dest_assets = {'assets': source_assets.asset_md.copy(), 'course_id': unicode(dest_course_key)}
|
||||
self.asset_collection.remove({'course_id': unicode(dest_course_key)})
|
||||
dest_assets = {'assets': source_assets.asset_md.copy(), 'course_id': six.text_type(dest_course_key)}
|
||||
self.asset_collection.remove({'course_id': six.text_type(dest_course_key)})
|
||||
# Update the document.
|
||||
self.asset_collection.insert(dest_assets)
|
||||
|
||||
|
||||
@@ -6,24 +6,35 @@ returns the i4x://org/course/cat/name@draft object if that exists,
|
||||
and otherwise returns i4x://org/course/cat/name).
|
||||
"""
|
||||
|
||||
import pymongo
|
||||
from __future__ import absolute_import
|
||||
|
||||
import logging
|
||||
|
||||
import pymongo
|
||||
import six
|
||||
from opaque_keys.edx.keys import UsageKey
|
||||
from opaque_keys.edx.locator import BlockUsageLocator
|
||||
from six import text_type
|
||||
from openedx.core.lib.cache_utils import request_cached
|
||||
from xblock.core import XBlock
|
||||
|
||||
from openedx.core.lib.cache_utils import request_cached
|
||||
from xmodule.exceptions import InvalidVersionError
|
||||
from xmodule.modulestore import ModuleStoreEnum
|
||||
from xmodule.modulestore.draft_and_published import DIRECT_ONLY_CATEGORIES, UnsupportedRevisionError
|
||||
from xmodule.modulestore.exceptions import (
|
||||
ItemNotFoundError, DuplicateItemError, DuplicateCourseError, InvalidBranchSetting
|
||||
DuplicateCourseError,
|
||||
DuplicateItemError,
|
||||
InvalidBranchSetting,
|
||||
ItemNotFoundError
|
||||
)
|
||||
from xmodule.modulestore.mongo.base import (
|
||||
MongoModuleStore, MongoRevisionKey, as_draft, as_published, SORT_REVISION_FAVOR_DRAFT
|
||||
SORT_REVISION_FAVOR_DRAFT,
|
||||
MongoModuleStore,
|
||||
MongoRevisionKey,
|
||||
as_draft,
|
||||
as_published
|
||||
)
|
||||
from xmodule.modulestore.store_utilities import rewrite_nonportable_content_links
|
||||
from xmodule.modulestore.draft_and_published import UnsupportedRevisionError, DIRECT_ONLY_CATEGORIES
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
@@ -207,7 +218,7 @@ class DraftModuleStore(MongoModuleStore):
|
||||
)
|
||||
else:
|
||||
# update fields on existing course
|
||||
for key, value in fields.iteritems():
|
||||
for key, value in six.iteritems(fields):
|
||||
setattr(new_course, key, value)
|
||||
self.update_item(new_course, user_id)
|
||||
|
||||
@@ -232,7 +243,7 @@ class DraftModuleStore(MongoModuleStore):
|
||||
|
||||
log.info("Cloning module %s to %s....", original_loc, module.location)
|
||||
|
||||
if 'data' in module.fields and module.fields['data'].is_set_on(module) and isinstance(module.data, basestring):
|
||||
if 'data' in module.fields and module.fields['data'].is_set_on(module) and isinstance(module.data, six.string_types):
|
||||
module.data = rewrite_nonportable_content_links(
|
||||
original_loc.course_key, dest_course_id, module.data
|
||||
)
|
||||
@@ -653,7 +664,7 @@ class DraftModuleStore(MongoModuleStore):
|
||||
|
||||
@request_cached(
|
||||
# use the XBlock's location value in the cache key
|
||||
arg_map_function=lambda arg: unicode(arg.location if isinstance(arg, XBlock) else arg),
|
||||
arg_map_function=lambda arg: six.text_type(arg.location if isinstance(arg, XBlock) else arg),
|
||||
# use this store's request_cache
|
||||
request_cache_getter=lambda args, kwargs: args[1],
|
||||
)
|
||||
@@ -847,7 +858,7 @@ class DraftModuleStore(MongoModuleStore):
|
||||
try:
|
||||
source_item = self.get_item(item_location)
|
||||
except ItemNotFoundError:
|
||||
log.error('Unable to find the item %s', unicode(item_location))
|
||||
log.error('Unable to find the item %s', six.text_type(item_location))
|
||||
return
|
||||
|
||||
if source_item.parent and source_item.parent.block_id != original_parent_location.block_id:
|
||||
@@ -886,7 +897,7 @@ class DraftModuleStore(MongoModuleStore):
|
||||
to_process_dict[draft_as_non_draft_loc] = draft
|
||||
|
||||
# convert the dict - which is used for look ups - back into a list
|
||||
queried_children = to_process_dict.values()
|
||||
queried_children = list(to_process_dict.values())
|
||||
|
||||
return queried_children
|
||||
|
||||
|
||||
@@ -4,13 +4,16 @@
|
||||
"""
|
||||
Generates fake XML for asset metadata.
|
||||
"""
|
||||
from __future__ import print_function
|
||||
from __future__ import absolute_import, print_function
|
||||
|
||||
import random
|
||||
from lxml import etree
|
||||
from datetime import datetime, timedelta
|
||||
from xmodule.assetstore import AssetMetadata
|
||||
|
||||
from lxml import etree
|
||||
from opaque_keys.edx.keys import CourseKey
|
||||
from six.moves import range
|
||||
|
||||
from xmodule.assetstore import AssetMetadata
|
||||
|
||||
try:
|
||||
import click
|
||||
@@ -52,7 +55,7 @@ def filename():
|
||||
Fake a filename.
|
||||
"""
|
||||
fname = u''
|
||||
for __ in xrange(random.randint(10, 30)):
|
||||
for __ in range(random.randint(10, 30)):
|
||||
fname += random.choice(NAME_CHARS_W_UNICODE)
|
||||
fname += random.choice(('.jpg', '.pdf', '.png', '.txt'))
|
||||
return fname
|
||||
@@ -63,8 +66,8 @@ def pathname():
|
||||
Fake a pathname.
|
||||
"""
|
||||
pname = u''
|
||||
for __ in xrange(random.randint(2, 3)):
|
||||
for __ in xrange(random.randint(5, 10)):
|
||||
for __ in range(random.randint(2, 3)):
|
||||
for __ in range(random.randint(5, 10)):
|
||||
pname += random.choice(NAME_CHARS)
|
||||
pname += '/'
|
||||
return pname
|
||||
@@ -149,7 +152,7 @@ def generate_random_asset_md():
|
||||
return AssetMetadata(
|
||||
asset_key,
|
||||
pathname=pathname(),
|
||||
internal_name=str([filename() for __ in xrange(10)]),
|
||||
internal_name=str([filename() for __ in range(10)]),
|
||||
locked=locked(),
|
||||
contenttype=contenttype(),
|
||||
thumbnail=filename(),
|
||||
@@ -170,7 +173,7 @@ def make_asset_md(amount):
|
||||
Make a number of fake AssetMetadata objects.
|
||||
"""
|
||||
all_asset_md = []
|
||||
for __ in xrange(amount):
|
||||
for __ in range(amount):
|
||||
all_asset_md.append(generate_random_asset_md())
|
||||
return all_asset_md
|
||||
|
||||
|
||||
@@ -4,11 +4,13 @@ Reads the data generated by performance tests and generates a savable
|
||||
report which can be viewed over time to examine the performance effects of code changes on
|
||||
various parts of the system.
|
||||
"""
|
||||
from __future__ import print_function
|
||||
from __future__ import absolute_import, print_function
|
||||
|
||||
import sqlite3
|
||||
from lxml.builder import E
|
||||
|
||||
import lxml.html
|
||||
from lxml.builder import E
|
||||
|
||||
try:
|
||||
import click
|
||||
except ImportError:
|
||||
|
||||
@@ -1,26 +1,25 @@
|
||||
"""
|
||||
Performance test for asset metadata in the modulestore.
|
||||
"""
|
||||
from path import Path as path
|
||||
import unittest
|
||||
from tempfile import mkdtemp
|
||||
import itertools
|
||||
from shutil import rmtree
|
||||
from bson.code import Code
|
||||
from __future__ import absolute_import
|
||||
|
||||
import datetime
|
||||
import itertools
|
||||
import unittest
|
||||
from shutil import rmtree
|
||||
from tempfile import mkdtemp
|
||||
|
||||
import ddt
|
||||
import pytest
|
||||
from bson.code import Code
|
||||
from path import Path as path
|
||||
|
||||
from xmodule.assetstore import AssetMetadata
|
||||
from xmodule.modulestore import ModuleStoreEnum
|
||||
from xmodule.modulestore.xml_importer import import_course_from_xml
|
||||
from xmodule.modulestore.perf_tests.generate_asset_xml import ASSET_XSD_FILE, make_asset_xml, validate_xml
|
||||
from xmodule.modulestore.tests.utils import MODULESTORE_SETUPS, SHORT_NAME_MAP, TEST_DATA_DIR
|
||||
from xmodule.modulestore.xml_exporter import export_course_to_xml
|
||||
from xmodule.modulestore.tests.utils import (
|
||||
MODULESTORE_SETUPS,
|
||||
SHORT_NAME_MAP,
|
||||
TEST_DATA_DIR,
|
||||
)
|
||||
from xmodule.modulestore.perf_tests.generate_asset_xml import make_asset_xml, validate_xml, ASSET_XSD_FILE
|
||||
from xmodule.modulestore.xml_importer import import_course_from_xml
|
||||
|
||||
# Number of assets saved in the modulestore per test run.
|
||||
ASSET_AMOUNT_PER_TEST = (0, 1, 10, 100, 1000, 10000)
|
||||
|
||||
@@ -2,8 +2,11 @@
|
||||
General utilities
|
||||
"""
|
||||
|
||||
from __future__ import absolute_import
|
||||
|
||||
from collections import namedtuple
|
||||
from contracts import contract, check
|
||||
|
||||
from contracts import check, contract
|
||||
from opaque_keys.edx.locator import BlockUsageLocator
|
||||
|
||||
|
||||
|
||||
@@ -1,25 +1,28 @@
|
||||
import sys
|
||||
import logging
|
||||
from __future__ import absolute_import
|
||||
|
||||
import logging
|
||||
import sys
|
||||
|
||||
import six
|
||||
from contracts import contract, new_contract
|
||||
from fs.osfs import OSFS
|
||||
from lazy import lazy
|
||||
from xblock.runtime import KvsFieldData, KeyValueStore
|
||||
from xblock.fields import ScopeIds
|
||||
from opaque_keys.edx.locator import BlockUsageLocator, CourseLocator, DefinitionLocator, LibraryLocator, LocalId
|
||||
from xblock.core import XBlock
|
||||
from opaque_keys.edx.locator import BlockUsageLocator, LocalId, CourseLocator, LibraryLocator, DefinitionLocator
|
||||
from xblock.fields import ScopeIds
|
||||
from xblock.runtime import KeyValueStore, KvsFieldData
|
||||
|
||||
from xmodule.library_tools import LibraryToolsService
|
||||
from xmodule.mako_module import MakoDescriptorSystem
|
||||
from xmodule.error_module import ErrorDescriptor
|
||||
from xmodule.errortracker import exc_info_to_str
|
||||
from xmodule.library_tools import LibraryToolsService
|
||||
from xmodule.mako_module import MakoDescriptorSystem
|
||||
from xmodule.modulestore import BlockData
|
||||
from xmodule.modulestore.edit_info import EditInfoRuntimeMixin
|
||||
from xmodule.modulestore.exceptions import ItemNotFoundError
|
||||
from xmodule.modulestore.inheritance import inheriting_field_data, InheritanceMixin
|
||||
from xmodule.modulestore.inheritance import InheritanceMixin, inheriting_field_data
|
||||
from xmodule.modulestore.split_mongo import BlockKey, CourseEnvelope
|
||||
from xmodule.modulestore.split_mongo.id_manager import SplitMongoIdManager
|
||||
from xmodule.modulestore.split_mongo.definition_lazy_loader import DefinitionLazyLoader
|
||||
from xmodule.modulestore.split_mongo.id_manager import SplitMongoIdManager
|
||||
from xmodule.modulestore.split_mongo.split_mongo_kvs import SplitMongoKVS
|
||||
from xmodule.x_module import XModuleMixin
|
||||
|
||||
@@ -88,7 +91,7 @@ class CachingDescriptorSystem(MakoDescriptorSystem, EditInfoRuntimeMixin):
|
||||
@contract(returns="dict(BlockKey: BlockKey)")
|
||||
def _parent_map(self):
|
||||
parent_map = {}
|
||||
for block_key, block in self.course_entry.structure['blocks'].iteritems():
|
||||
for block_key, block in six.iteritems(self.course_entry.structure['blocks']):
|
||||
for child in block.fields.get('children', []):
|
||||
parent_map[child] = block_key
|
||||
return parent_map
|
||||
@@ -382,7 +385,7 @@ class CachingDescriptorSystem(MakoDescriptorSystem, EditInfoRuntimeMixin):
|
||||
new_aside = super(CachingDescriptorSystem, self).get_aside_of_type(block, aside_type)
|
||||
new_aside._field_data = block._field_data # pylint: disable=protected-access
|
||||
|
||||
for key, _ in new_aside.fields.iteritems():
|
||||
for key, _ in six.iteritems(new_aside.fields):
|
||||
if isinstance(key, KeyValueStore.Key) and block._field_data.has(new_aside, key): # pylint: disable=protected-access
|
||||
try:
|
||||
value = block._field_data.get(new_aside, key) # pylint: disable=protected-access
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
from opaque_keys.edx.locator import DefinitionLocator
|
||||
from __future__ import absolute_import
|
||||
|
||||
import copy
|
||||
|
||||
from opaque_keys.edx.locator import DefinitionLocator
|
||||
|
||||
|
||||
class DefinitionLazyLoader(object):
|
||||
"""
|
||||
|
||||
@@ -3,9 +3,12 @@ An implementation of IdReader and IdGenerator that manages ids for the SplitMong
|
||||
mechanism.
|
||||
"""
|
||||
|
||||
from opaque_keys.edx.locator import LocalId, DefinitionLocator
|
||||
from xmodule.x_module import OpaqueKeyReader, AsideKeyGenerator
|
||||
from __future__ import absolute_import
|
||||
|
||||
from opaque_keys.edx.locator import DefinitionLocator, LocalId
|
||||
|
||||
from xmodule.modulestore.split_mongo import BlockKey
|
||||
from xmodule.x_module import AsideKeyGenerator, OpaqueKeyReader
|
||||
|
||||
|
||||
# TODO: Migrate split_mongo to use this class for all key mapping/creation.
|
||||
|
||||
@@ -1,35 +1,36 @@
|
||||
"""
|
||||
Segregation of pymongo functions from the data modeling mechanisms for split modulestore.
|
||||
"""
|
||||
from __future__ import absolute_import
|
||||
|
||||
import datetime
|
||||
import cPickle as pickle
|
||||
import logging
|
||||
import math
|
||||
import zlib
|
||||
import pymongo
|
||||
import pytz
|
||||
import re
|
||||
import zlib
|
||||
from contextlib import contextmanager
|
||||
from time import time
|
||||
|
||||
import pymongo
|
||||
import pytz
|
||||
import six
|
||||
import six.moves.cPickle as pickle
|
||||
from contracts import check, new_contract
|
||||
from mongodb_proxy import autoretry_read
|
||||
# Import this just to export it
|
||||
from pymongo.errors import DuplicateKeyError # pylint: disable=unused-import
|
||||
|
||||
from xmodule.exceptions import HeartbeatFailure
|
||||
from xmodule.modulestore import BlockData
|
||||
from xmodule.modulestore.split_mongo import BlockKey
|
||||
from xmodule.mongo_utils import connect_to_mongodb, create_collection_index
|
||||
|
||||
try:
|
||||
from django.core.cache import caches, InvalidCacheBackendError
|
||||
DJANGO_AVAILABLE = True
|
||||
except ImportError:
|
||||
DJANGO_AVAILABLE = False
|
||||
|
||||
import logging
|
||||
|
||||
from contracts import check, new_contract
|
||||
from mongodb_proxy import autoretry_read
|
||||
from xmodule.exceptions import HeartbeatFailure
|
||||
from xmodule.modulestore import BlockData
|
||||
from xmodule.modulestore.split_mongo import BlockKey
|
||||
from xmodule.mongo_utils import connect_to_mongodb, create_collection_index
|
||||
|
||||
|
||||
new_contract('BlockData', BlockData)
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
@@ -82,7 +83,7 @@ class Tagger(object):
|
||||
**kwargs: Each keyword is treated as a tag name, and the
|
||||
value of the argument is the tag value.
|
||||
"""
|
||||
self.added_tags.extend(kwargs.items())
|
||||
self.added_tags.extend(list(kwargs.items()))
|
||||
|
||||
@property
|
||||
def tags(self):
|
||||
@@ -187,14 +188,14 @@ def structure_to_mongo(structure, course_context=None):
|
||||
|
||||
check('BlockKey', structure['root'])
|
||||
check('dict(BlockKey: BlockData)', structure['blocks'])
|
||||
for block in structure['blocks'].itervalues():
|
||||
for block in six.itervalues(structure['blocks']):
|
||||
if 'children' in block.fields:
|
||||
check('list(BlockKey)', block.fields['children'])
|
||||
|
||||
new_structure = dict(structure)
|
||||
new_structure['blocks'] = []
|
||||
|
||||
for block_key, block in structure['blocks'].iteritems():
|
||||
for block_key, block in six.iteritems(structure['blocks']):
|
||||
new_block = dict(block.to_storable())
|
||||
new_block.setdefault('block_type', block_key.type)
|
||||
new_block['block_id'] = block_key.id
|
||||
@@ -311,7 +312,7 @@ class MongoConnection(object):
|
||||
if doc is None:
|
||||
log.warning(
|
||||
"doc was None when attempting to retrieve structure for item with key %s",
|
||||
unicode(key)
|
||||
six.text_type(key)
|
||||
)
|
||||
return None
|
||||
tagger_find_one.measure("blocks", len(doc['blocks']))
|
||||
@@ -459,7 +460,7 @@ class MongoConnection(object):
|
||||
query['versions.{}'.format(branch)] = {'$exists': True}
|
||||
|
||||
if search_targets:
|
||||
for key, value in search_targets.iteritems():
|
||||
for key, value in six.iteritems(search_targets):
|
||||
query['search_targets.{}'.format(key)] = value
|
||||
|
||||
if org_target:
|
||||
|
||||
@@ -53,47 +53,63 @@ Representation:
|
||||
*** 'original_version': definition_id of the root of the previous version relation on this
|
||||
definition. Acts as a pseudo-object identifier.
|
||||
"""
|
||||
from __future__ import absolute_import
|
||||
|
||||
import copy
|
||||
import datetime
|
||||
import hashlib
|
||||
import logging
|
||||
import six
|
||||
|
||||
from contracts import contract, new_contract
|
||||
from collections import defaultdict
|
||||
from importlib import import_module
|
||||
from mongodb_proxy import autoretry_read
|
||||
from path import Path as path
|
||||
from pytz import UTC
|
||||
from bson.objectid import ObjectId
|
||||
from types import NoneType
|
||||
|
||||
from xblock.core import XBlock
|
||||
from xblock.fields import Scope, Reference, ReferenceList, ReferenceValueDict
|
||||
from xmodule.course_module import CourseSummary
|
||||
from xmodule.library_content_module import LibrarySummary
|
||||
from xmodule.errortracker import null_error_tracker
|
||||
import six
|
||||
from bson.objectid import ObjectId
|
||||
from ccx_keys.locator import CCXBlockUsageLocator, CCXLocator
|
||||
from contracts import contract, new_contract
|
||||
from mongodb_proxy import autoretry_read
|
||||
from opaque_keys.edx.keys import CourseKey
|
||||
from opaque_keys.edx.locator import (
|
||||
BlockUsageLocator, DefinitionLocator, CourseLocator, LibraryLocator, VersionTree, LocalId,
|
||||
BlockUsageLocator,
|
||||
CourseLocator,
|
||||
DefinitionLocator,
|
||||
LibraryLocator,
|
||||
LocalId,
|
||||
VersionTree
|
||||
)
|
||||
from ccx_keys.locator import CCXLocator, CCXBlockUsageLocator
|
||||
from xmodule.modulestore.exceptions import InsufficientSpecificationError, VersionConflictError, DuplicateItemError, \
|
||||
DuplicateCourseError, MultipleCourseBlocksFound
|
||||
from path import Path as path
|
||||
from pytz import UTC
|
||||
from xblock.core import XBlock
|
||||
from xblock.fields import Reference, ReferenceList, ReferenceValueDict, Scope
|
||||
|
||||
from xmodule.assetstore import AssetMetadata
|
||||
from xmodule.course_module import CourseSummary
|
||||
from xmodule.error_module import ErrorDescriptor
|
||||
from xmodule.errortracker import null_error_tracker
|
||||
from xmodule.library_content_module import LibrarySummary
|
||||
from xmodule.modulestore import (
|
||||
inheritance, ModuleStoreWriteBase, ModuleStoreEnum,
|
||||
BulkOpsRecord, BulkOperationsMixin, SortedAssetList, BlockData
|
||||
BlockData,
|
||||
BulkOperationsMixin,
|
||||
BulkOpsRecord,
|
||||
ModuleStoreEnum,
|
||||
ModuleStoreWriteBase,
|
||||
SortedAssetList,
|
||||
inheritance
|
||||
)
|
||||
from xmodule.modulestore.exceptions import (
|
||||
DuplicateCourseError,
|
||||
DuplicateItemError,
|
||||
InsufficientSpecificationError,
|
||||
MultipleCourseBlocksFound,
|
||||
VersionConflictError
|
||||
)
|
||||
from xmodule.modulestore.split_mongo import BlockKey, CourseEnvelope
|
||||
from xmodule.modulestore.split_mongo.mongo_connection import DuplicateKeyError, MongoConnection
|
||||
from xmodule.modulestore.store_utilities import DETACHED_XBLOCK_TYPES
|
||||
from xmodule.partitions.partitions_service import PartitionService
|
||||
|
||||
from ..exceptions import ItemNotFoundError
|
||||
from .caching_descriptor_system import CachingDescriptorSystem
|
||||
from xmodule.partitions.partitions_service import PartitionService
|
||||
from xmodule.modulestore.split_mongo.mongo_connection import MongoConnection, DuplicateKeyError
|
||||
from xmodule.modulestore.split_mongo import BlockKey, CourseEnvelope
|
||||
from xmodule.modulestore.store_utilities import DETACHED_XBLOCK_TYPES
|
||||
from xmodule.error_module import ErrorDescriptor
|
||||
from collections import defaultdict
|
||||
from types import NoneType
|
||||
from xmodule.assetstore import AssetMetadata
|
||||
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
@@ -152,7 +168,7 @@ class SplitBulkWriteRecord(BulkOpsRecord):
|
||||
# If there was no index in the database to start with, then all branches
|
||||
# are dirty by definition
|
||||
if self.initial_index is None:
|
||||
return self.index.get('versions', {}).keys()
|
||||
return list(self.index.get('versions', {}).keys())
|
||||
|
||||
# Return branches whose ids differ between self.index and self.initial_index
|
||||
return [
|
||||
@@ -247,7 +263,7 @@ class SplitBulkWriteMixin(BulkOperationsMixin):
|
||||
dirty = False
|
||||
|
||||
# If the content is dirty, then update the database
|
||||
for _id in bulk_write_record.structures.viewkeys() - bulk_write_record.structures_in_db:
|
||||
for _id in six.viewkeys(bulk_write_record.structures) - bulk_write_record.structures_in_db:
|
||||
dirty = True
|
||||
|
||||
try:
|
||||
@@ -258,7 +274,7 @@ class SplitBulkWriteMixin(BulkOperationsMixin):
|
||||
# append only, so if it's already been written, we can just keep going.
|
||||
log.debug("Attempted to insert duplicate structure %s", _id)
|
||||
|
||||
for _id in bulk_write_record.definitions.viewkeys() - bulk_write_record.definitions_in_db:
|
||||
for _id in six.viewkeys(bulk_write_record.definitions) - bulk_write_record.definitions_in_db:
|
||||
dirty = True
|
||||
|
||||
try:
|
||||
@@ -439,7 +455,7 @@ class SplitBulkWriteMixin(BulkOperationsMixin):
|
||||
defs_from_db = list(self.db_connection.get_definitions(list(ids), course_key))
|
||||
defs_dict = {d.get('_id'): d for d in defs_from_db}
|
||||
# Add the retrieved definitions to the cache.
|
||||
bulk_write_record.definitions_in_db.update(defs_dict.iterkeys())
|
||||
bulk_write_record.definitions_in_db.update(six.iterkeys(defs_dict))
|
||||
bulk_write_record.definitions.update(defs_dict)
|
||||
definitions.extend(defs_from_db)
|
||||
return definitions
|
||||
@@ -555,7 +571,7 @@ class SplitBulkWriteMixin(BulkOperationsMixin):
|
||||
'search_targets' not in record.index or
|
||||
field not in record.index['search_targets'] or
|
||||
record.index['search_targets'][field] != value
|
||||
for field, value in search_targets.iteritems()
|
||||
for field, value in six.iteritems(search_targets)
|
||||
):
|
||||
continue
|
||||
# if we've specified a filter by org,
|
||||
@@ -789,14 +805,14 @@ class SplitMongoModuleStore(SplitBulkWriteMixin, ModuleStoreWriteBase):
|
||||
course_key,
|
||||
[
|
||||
block.definition
|
||||
for block in new_module_data.itervalues()
|
||||
for block in six.itervalues(new_module_data)
|
||||
]
|
||||
)
|
||||
# Turn definitions into a map.
|
||||
definitions = {definition['_id']: definition
|
||||
for definition in descendent_definitions}
|
||||
|
||||
for block in new_module_data.itervalues():
|
||||
for block in six.itervalues(new_module_data):
|
||||
if block.definition in definitions:
|
||||
definition = definitions[block.definition]
|
||||
# convert_fields gets done later in the runtime's xblock_from_json
|
||||
@@ -1281,7 +1297,7 @@ class SplitMongoModuleStore(SplitBulkWriteMixin, ModuleStoreWriteBase):
|
||||
# odd case where we don't search just confirm
|
||||
block_name = qualifiers.pop('name')
|
||||
block_ids = []
|
||||
for block_id, block in course.structure['blocks'].iteritems():
|
||||
for block_id, block in six.iteritems(course.structure['blocks']):
|
||||
# Don't do an in comparison blindly; first check to make sure
|
||||
# that the name qualifier we're looking at isn't a plain string;
|
||||
# if it is a string, then it should match exactly. If it's other
|
||||
@@ -1312,7 +1328,7 @@ class SplitMongoModuleStore(SplitBulkWriteMixin, ModuleStoreWriteBase):
|
||||
path_cache = {}
|
||||
parents_cache = self.build_block_key_to_parents_mapping(course.structure)
|
||||
|
||||
for block_id, value in course.structure['blocks'].iteritems():
|
||||
for block_id, value in six.iteritems(course.structure['blocks']):
|
||||
if _block_matches_all(value):
|
||||
if not include_orphans:
|
||||
if ( # pylint: disable=bad-continuation
|
||||
@@ -1338,7 +1354,7 @@ class SplitMongoModuleStore(SplitBulkWriteMixin, ModuleStoreWriteBase):
|
||||
:return dict: a dictionary containing mapping of block_keys against their parents.
|
||||
"""
|
||||
children_to_parents = defaultdict(list)
|
||||
for parent_key, value in structure['blocks'].iteritems():
|
||||
for parent_key, value in six.iteritems(structure['blocks']):
|
||||
for child_key in value.fields.get('children', []):
|
||||
children_to_parents[child_key].append(parent_key)
|
||||
|
||||
@@ -1430,7 +1446,7 @@ class SplitMongoModuleStore(SplitBulkWriteMixin, ModuleStoreWriteBase):
|
||||
items = set(course.structure['blocks'].keys())
|
||||
items.remove(course.structure['root'])
|
||||
blocks = course.structure['blocks']
|
||||
for block_id, block_data in blocks.iteritems():
|
||||
for block_id, block_data in six.iteritems(blocks):
|
||||
items.difference_update(BlockKey(*child) for child in block_data.fields.get('children', []))
|
||||
if block_data.block_type in detached_categories:
|
||||
items.discard(block_id)
|
||||
@@ -1583,7 +1599,7 @@ class SplitMongoModuleStore(SplitBulkWriteMixin, ModuleStoreWriteBase):
|
||||
elif len(possible_roots) == 0:
|
||||
return None
|
||||
# convert the results value sets to locators
|
||||
for k, versions in result.iteritems():
|
||||
for k, versions in six.iteritems(result):
|
||||
result[k] = [
|
||||
block_locator.for_version(version)
|
||||
for version in versions
|
||||
@@ -1648,10 +1664,10 @@ class SplitMongoModuleStore(SplitBulkWriteMixin, ModuleStoreWriteBase):
|
||||
:param user_id: request.user
|
||||
"""
|
||||
def needs_saved():
|
||||
for key, value in new_def_data.iteritems():
|
||||
for key, value in six.iteritems(new_def_data):
|
||||
if key not in old_definition['fields'] or value != old_definition['fields'][key]:
|
||||
return True
|
||||
for key, value in old_definition.get('fields', {}).iteritems():
|
||||
for key, value in six.iteritems(old_definition.get('fields', {})):
|
||||
if key not in new_def_data:
|
||||
return True
|
||||
|
||||
@@ -2094,7 +2110,7 @@ class SplitMongoModuleStore(SplitBulkWriteMixin, ModuleStoreWriteBase):
|
||||
with self.bulk_operations(course_key):
|
||||
if allow_not_found and isinstance(block_key.id, (LocalId, NoneType)):
|
||||
fields = {}
|
||||
for subfields in partitioned_fields.itervalues():
|
||||
for subfields in six.itervalues(partitioned_fields):
|
||||
fields.update(subfields)
|
||||
return self.create_item(
|
||||
user_id, course_key, block_key.type, fields=fields, asides=asides, force=force
|
||||
@@ -2107,7 +2123,7 @@ class SplitMongoModuleStore(SplitBulkWriteMixin, ModuleStoreWriteBase):
|
||||
if original_entry is None:
|
||||
if allow_not_found:
|
||||
fields = {}
|
||||
for subfields in partitioned_fields.itervalues():
|
||||
for subfields in six.itervalues(partitioned_fields):
|
||||
fields.update(subfields)
|
||||
return self.create_item(user_id, course_key, block_key.type, block_id=block_key.id, fields=fields,
|
||||
asides=asides, force=force)
|
||||
@@ -2238,7 +2254,7 @@ class SplitMongoModuleStore(SplitBulkWriteMixin, ModuleStoreWriteBase):
|
||||
BlockData(**json_data),
|
||||
**kwargs
|
||||
)
|
||||
for field_name, value in (fields or {}).iteritems():
|
||||
for field_name, value in six.iteritems((fields or {})):
|
||||
setattr(new_block, field_name, value)
|
||||
|
||||
if parent_xblock is not None:
|
||||
@@ -2359,13 +2375,13 @@ class SplitMongoModuleStore(SplitBulkWriteMixin, ModuleStoreWriteBase):
|
||||
:param settings:
|
||||
:param original_fields:
|
||||
"""
|
||||
original_keys = original_fields.keys()
|
||||
original_keys = list(original_fields.keys())
|
||||
if 'children' in original_keys:
|
||||
original_keys.remove('children')
|
||||
if len(settings) != len(original_keys):
|
||||
return True
|
||||
else:
|
||||
new_keys = settings.keys()
|
||||
new_keys = list(settings.keys())
|
||||
for key in original_keys:
|
||||
if key not in new_keys or original_fields[key] != settings[key]:
|
||||
return True
|
||||
@@ -2578,7 +2594,7 @@ class SplitMongoModuleStore(SplitBulkWriteMixin, ModuleStoreWriteBase):
|
||||
# Compute a new block ID. This new block ID must be consistent when this
|
||||
# method is called with the same (source_key, dest_structure) pair
|
||||
unique_data = "{}:{}:{}".format(
|
||||
unicode(hashable_source_id).encode("utf-8"),
|
||||
six.text_type(hashable_source_id).encode("utf-8"),
|
||||
block_key.id,
|
||||
new_parent_block_key.id,
|
||||
)
|
||||
@@ -2618,7 +2634,7 @@ class SplitMongoModuleStore(SplitBulkWriteMixin, ModuleStoreWriteBase):
|
||||
# Setting it to the source_block_info structure version here breaks split_draft's has_changes() method.
|
||||
new_block_info.edit_info.edited_by = user_id
|
||||
new_block_info.edit_info.edited_on = datetime.datetime.now(UTC)
|
||||
new_block_info.edit_info.original_usage = unicode(usage_key.replace(branch=None, version_guid=None))
|
||||
new_block_info.edit_info.original_usage = six.text_type(usage_key.replace(branch=None, version_guid=None))
|
||||
new_block_info.edit_info.original_usage_version = source_block_info.edit_info.update_version
|
||||
dest_structure['blocks'][new_block_key] = new_block_info
|
||||
|
||||
@@ -2711,7 +2727,7 @@ class SplitMongoModuleStore(SplitBulkWriteMixin, ModuleStoreWriteBase):
|
||||
"""
|
||||
# create mapping from each child's key to its parents' keys
|
||||
child_parent_map = defaultdict(set)
|
||||
for block_key, block_data in blocks.iteritems():
|
||||
for block_key, block_data in six.iteritems(blocks):
|
||||
for child in block_data.fields.get('children', []):
|
||||
child_parent_map[BlockKey(*child)].add(block_key)
|
||||
|
||||
@@ -2890,7 +2906,7 @@ class SplitMongoModuleStore(SplitBulkWriteMixin, ModuleStoreWriteBase):
|
||||
course_key, asset_metadata_list, course_assets, user_id, import_only
|
||||
)
|
||||
|
||||
for asset_type, assets in assets_by_type.iteritems():
|
||||
for asset_type, assets in six.iteritems(assets_by_type):
|
||||
new_structure['assets'][asset_type] = list(assets)
|
||||
|
||||
# update index if appropriate and structures
|
||||
@@ -2999,7 +3015,7 @@ class SplitMongoModuleStore(SplitBulkWriteMixin, ModuleStoreWriteBase):
|
||||
original_structure = self._lookup_course(course_locator).structure
|
||||
index_entry = self._get_index_if_valid(course_locator)
|
||||
new_structure = self.version_structure(course_locator, original_structure, user_id)
|
||||
for block in new_structure['blocks'].itervalues():
|
||||
for block in six.itervalues(new_structure['blocks']):
|
||||
if 'children' in block.fields:
|
||||
block.fields['children'] = [
|
||||
block_id for block_id in block.fields['children']
|
||||
@@ -3042,7 +3058,7 @@ class SplitMongoModuleStore(SplitBulkWriteMixin, ModuleStoreWriteBase):
|
||||
xblock_class = self.mixologist.mix(xblock_class)
|
||||
# Make a shallow copy, so that we aren't manipulating a cached field dictionary
|
||||
output_fields = dict(jsonfields)
|
||||
for field_name, value in output_fields.iteritems():
|
||||
for field_name, value in six.iteritems(output_fields):
|
||||
if value:
|
||||
try:
|
||||
field = xblock_class.fields.get(field_name)
|
||||
@@ -3053,7 +3069,7 @@ class SplitMongoModuleStore(SplitBulkWriteMixin, ModuleStoreWriteBase):
|
||||
elif isinstance(field, ReferenceList):
|
||||
output_fields[field_name] = [robust_usage_key(ele) for ele in value]
|
||||
elif isinstance(field, ReferenceValueDict):
|
||||
for key, subvalue in value.iteritems():
|
||||
for key, subvalue in six.iteritems(value):
|
||||
value[key] = robust_usage_key(subvalue)
|
||||
return output_fields
|
||||
|
||||
@@ -3102,7 +3118,7 @@ class SplitMongoModuleStore(SplitBulkWriteMixin, ModuleStoreWriteBase):
|
||||
:param fields: a dictionary of fields and values usually only those explicitly set and already
|
||||
ready for persisting (e.g., references converted to block_ids)
|
||||
"""
|
||||
for field_name, field_value in fields.iteritems():
|
||||
for field_name, field_value in six.iteritems(fields):
|
||||
if field_name in self.SEARCH_TARGET_DICT:
|
||||
index_entry.setdefault('search_targets', {})[field_name] = field_value
|
||||
|
||||
@@ -3126,7 +3142,7 @@ class SplitMongoModuleStore(SplitBulkWriteMixin, ModuleStoreWriteBase):
|
||||
# explicitly_set_fields_by_scope converts to json; so, avoiding it
|
||||
# the existing partition_fields_by_scope works on a dict not an xblock
|
||||
result = defaultdict(dict)
|
||||
for field in xblock.fields.itervalues():
|
||||
for field in six.itervalues(xblock.fields):
|
||||
if field.is_set_on(xblock):
|
||||
result[field.scope][field.name] = field.read_from(xblock)
|
||||
return result
|
||||
@@ -3149,13 +3165,13 @@ class SplitMongoModuleStore(SplitBulkWriteMixin, ModuleStoreWriteBase):
|
||||
Handle client possibly setting field to strings rather than keys to get the block_id
|
||||
"""
|
||||
# perhaps replace by fixing the views or Field Reference*.from_json to return a Key
|
||||
if isinstance(reference, basestring):
|
||||
if isinstance(reference, six.string_types):
|
||||
reference = BlockUsageLocator.from_string(reference)
|
||||
elif isinstance(reference, BlockKey):
|
||||
return reference
|
||||
return BlockKey.from_usage_key(reference)
|
||||
|
||||
for field_name, value in fields.iteritems():
|
||||
for field_name, value in six.iteritems(fields):
|
||||
if value is not None:
|
||||
if isinstance(xblock_class.fields[field_name], Reference):
|
||||
fields[field_name] = reference_block_id(value)
|
||||
@@ -3164,7 +3180,7 @@ class SplitMongoModuleStore(SplitBulkWriteMixin, ModuleStoreWriteBase):
|
||||
reference_block_id(ele) for ele in value
|
||||
]
|
||||
elif isinstance(xblock_class.fields[field_name], ReferenceValueDict):
|
||||
for key, subvalue in value.iteritems():
|
||||
for key, subvalue in six.iteritems(value):
|
||||
value[key] = reference_block_id(subvalue)
|
||||
# should this recurse down dicts and lists just in case they contain datetime?
|
||||
elif not isinstance(value, datetime.datetime): # don't convert datetimes!
|
||||
@@ -3207,7 +3223,7 @@ class SplitMongoModuleStore(SplitBulkWriteMixin, ModuleStoreWriteBase):
|
||||
"""
|
||||
return [
|
||||
parent_block_key
|
||||
for parent_block_key, value in structure['blocks'].iteritems()
|
||||
for parent_block_key, value in six.iteritems(structure['blocks'])
|
||||
if block_key in value.fields.get('children', [])
|
||||
]
|
||||
|
||||
@@ -3279,7 +3295,7 @@ class SplitMongoModuleStore(SplitBulkWriteMixin, ModuleStoreWriteBase):
|
||||
block_defaults=new_block.defaults
|
||||
)
|
||||
# Extend the block's new edit_info with any extra edit_info fields from the source (e.g. original_usage):
|
||||
for key, val in new_block.edit_info.to_storable().iteritems():
|
||||
for key, val in six.iteritems(new_block.edit_info.to_storable()):
|
||||
if getattr(destination_block.edit_info, key) is None:
|
||||
setattr(destination_block.edit_info, key, val)
|
||||
|
||||
@@ -3386,7 +3402,7 @@ class SplitMongoModuleStore(SplitBulkWriteMixin, ModuleStoreWriteBase):
|
||||
result_list.append(aside)
|
||||
|
||||
if tmp_new_asides_data:
|
||||
for _, asd in tmp_new_asides_data.iteritems():
|
||||
for _, asd in six.iteritems(tmp_new_asides_data):
|
||||
result_list.append(asd)
|
||||
updated = True
|
||||
|
||||
|
||||
@@ -2,16 +2,21 @@
|
||||
Module for the dual-branch fall-back Draft->Published Versioning ModuleStore
|
||||
"""
|
||||
|
||||
from xmodule.modulestore.split_mongo.split import SplitMongoModuleStore, EXCLUDE_ALL
|
||||
from __future__ import absolute_import
|
||||
|
||||
from contracts import contract
|
||||
from opaque_keys.edx.locator import CourseLocator, LibraryLocator, LibraryUsageLocator
|
||||
|
||||
from xmodule.exceptions import InvalidVersionError
|
||||
from xmodule.modulestore import ModuleStoreEnum
|
||||
from xmodule.modulestore.exceptions import InsufficientSpecificationError, ItemNotFoundError
|
||||
from xmodule.modulestore.draft_and_published import (
|
||||
ModuleStoreDraftAndPublished, DIRECT_ONLY_CATEGORIES, UnsupportedRevisionError
|
||||
DIRECT_ONLY_CATEGORIES,
|
||||
ModuleStoreDraftAndPublished,
|
||||
UnsupportedRevisionError
|
||||
)
|
||||
from opaque_keys.edx.locator import CourseLocator, LibraryLocator, LibraryUsageLocator
|
||||
from xmodule.modulestore.exceptions import InsufficientSpecificationError, ItemNotFoundError
|
||||
from xmodule.modulestore.split_mongo import BlockKey
|
||||
from contracts import contract
|
||||
from xmodule.modulestore.split_mongo.split import EXCLUDE_ALL, SplitMongoModuleStore
|
||||
|
||||
|
||||
class DraftVersioningModuleStore(SplitMongoModuleStore, ModuleStoreDraftAndPublished):
|
||||
|
||||
@@ -1,12 +1,18 @@
|
||||
from __future__ import absolute_import
|
||||
|
||||
import copy
|
||||
from contracts import contract, new_contract
|
||||
from xblock.fields import Scope
|
||||
from collections import namedtuple
|
||||
from xblock.exceptions import InvalidScopeError
|
||||
from .definition_lazy_loader import DefinitionLazyLoader
|
||||
from xmodule.modulestore.inheritance import InheritanceKeyValueStore
|
||||
|
||||
import six
|
||||
from contracts import contract, new_contract
|
||||
from opaque_keys.edx.locator import BlockUsageLocator
|
||||
from xblock.core import XBlockAside
|
||||
from xblock.exceptions import InvalidScopeError
|
||||
from xblock.fields import Scope
|
||||
|
||||
from xmodule.modulestore.inheritance import InheritanceKeyValueStore
|
||||
|
||||
from .definition_lazy_loader import DefinitionLazyLoader
|
||||
|
||||
# id is a BlockUsageLocator, def_id is the definition's guid
|
||||
SplitMongoKVSid = namedtuple('SplitMongoKVSid', 'id, def_id')
|
||||
@@ -186,7 +192,7 @@ class SplitMongoKVS(InheritanceKeyValueStore):
|
||||
aside_fields_p = persisted_definition.get('aside_fields')
|
||||
if aside_fields_p:
|
||||
aside_fields = self._definition.field_converter(aside_fields_p)
|
||||
for aside_type, fields in aside_fields.iteritems():
|
||||
for aside_type, fields in six.iteritems(aside_fields):
|
||||
self.aside_fields.setdefault(aside_type, {}).update(fields)
|
||||
# do we want to cache any of the edit_info?
|
||||
self._definition = None # already loaded
|
||||
|
||||
Reference in New Issue
Block a user