@@ -1,3 +1,7 @@
|
||||
"""
|
||||
Provide names as exported by older mongo.py module
|
||||
"""
|
||||
|
||||
from xmodule.modulestore.mongo.base import MongoModuleStore, MongoKeyValueStore, MongoUsage
|
||||
|
||||
# Backwards compatibility for prod systems that refererence
|
||||
|
||||
@@ -1,3 +1,17 @@
|
||||
"""
|
||||
Modulestore backed by Mongodb.
|
||||
|
||||
Stores individual XModules as single documents with the following
|
||||
structure:
|
||||
|
||||
{
|
||||
'_id': <location.as_dict>,
|
||||
'metadata': <dict containing all Scope.settings fields>
|
||||
'definition': <dict containing all Scope.content fields>
|
||||
'definition.children': <list of all child location.url()s>
|
||||
}
|
||||
"""
|
||||
|
||||
import pymongo
|
||||
import sys
|
||||
import logging
|
||||
@@ -19,8 +33,7 @@ from xblock.runtime import DbModel, KeyValueStore, InvalidScopeError
|
||||
from xblock.core import Scope
|
||||
|
||||
from xmodule.modulestore import ModuleStoreBase, Location, namedtuple_to_son
|
||||
from xmodule.modulestore.exceptions import (ItemNotFoundError,
|
||||
DuplicateItemError)
|
||||
from xmodule.modulestore.exceptions import ItemNotFoundError, DuplicateItemError
|
||||
from xmodule.modulestore.inheritance import own_metadata, INHERITABLE_METADATA, inherit_metadata
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
@@ -32,6 +45,7 @@ log = logging.getLogger(__name__)
|
||||
|
||||
def get_course_id_no_run(location):
|
||||
'''
|
||||
Return the first two components of the course_id for this location (org/course)
|
||||
'''
|
||||
return "/".join([location.org, location.course])
|
||||
|
||||
@@ -615,6 +629,9 @@ class MongoModuleStore(ModuleStoreBase):
|
||||
return item
|
||||
|
||||
def fire_updated_modulestore_signal(self, course_id, location):
|
||||
"""
|
||||
Send a signal using `self.modulestore_update_signal`, if that has been set
|
||||
"""
|
||||
if self.modulestore_update_signal is not None:
|
||||
self.modulestore_update_signal.send(self, modulestore=self, course_id=course_id,
|
||||
location=location)
|
||||
@@ -758,5 +775,3 @@ class MongoModuleStore(ModuleStoreBase):
|
||||
are loaded on demand, rather than up front
|
||||
"""
|
||||
return {}
|
||||
|
||||
|
||||
|
||||
@@ -1,3 +1,11 @@
|
||||
"""
|
||||
A ModuleStore that knows about a special version 'draft'. Modules
|
||||
marked as 'draft' are read in preference to modules without the 'draft'
|
||||
version by this ModuleStore (so, access to i4x://org/course/cat/name
|
||||
returns the i4x://org/course/cat/name@draft object if that exists,
|
||||
and otherwise returns i4x://org/course/cat/name).
|
||||
"""
|
||||
|
||||
from datetime import datetime
|
||||
|
||||
from xmodule.modulestore import Location, namedtuple_to_son
|
||||
@@ -217,7 +225,6 @@ class DraftModuleStore(MongoModuleStore):
|
||||
|
||||
def _query_children_for_cache_children(self, items):
|
||||
# first get non-draft in a round-trip
|
||||
queried_children = []
|
||||
to_process_non_drafts = super(DraftModuleStore, self)._query_children_for_cache_children(items)
|
||||
|
||||
to_process_dict = {}
|
||||
@@ -243,7 +250,6 @@ 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
|
||||
for key, value in to_process_dict.iteritems():
|
||||
queried_children.append(value)
|
||||
queried_children = to_process_dict.values()
|
||||
|
||||
return queried_children
|
||||
|
||||
@@ -1,13 +1,23 @@
|
||||
"""
|
||||
Methods for exporting course data to XML
|
||||
"""
|
||||
|
||||
import logging
|
||||
from xmodule.modulestore import Location
|
||||
from xmodule.modulestore.inheritance import own_metadata
|
||||
from fs.osfs import OSFS
|
||||
from json import dumps
|
||||
import json
|
||||
from json.encoder import JSONEncoder
|
||||
import datetime
|
||||
|
||||
|
||||
class EdxJSONEncoder(json.JSONEncoder):
|
||||
"""
|
||||
Custom JSONEncoder that handles `Location` and `datetime.datetime` objects.
|
||||
|
||||
`Location`s are encoded as their url string form, and `datetime`s as
|
||||
ISO date strings
|
||||
"""
|
||||
def default(self, obj):
|
||||
if isinstance(obj, Location):
|
||||
return obj.url()
|
||||
@@ -22,7 +32,19 @@ class EdxJSONEncoder(json.JSONEncoder):
|
||||
else:
|
||||
return super(EdxJSONEncoder, self).default(obj)
|
||||
|
||||
|
||||
def export_to_xml(modulestore, contentstore, course_location, root_dir, course_dir, draft_modulestore=None):
|
||||
"""
|
||||
Export all modules from `modulestore` and content from `contentstore` as xml to `root_dir`.
|
||||
|
||||
`modulestore`: A `ModuleStore` object that is the source of the modules to export
|
||||
`contentstore`: A `ContentStore` object that is the source of the content to export
|
||||
`course_location`: The `Location` of the `CourseModuleDescriptor` to export
|
||||
`root_dir`: The directory to write the exported xml to
|
||||
`course_dir`: The name of the directory inside `root_dir` to write the course content to
|
||||
`draft_modulestore`: An optional `DraftModuleStore` that contains draft content, which will be exported
|
||||
alongside the public content in the course.
|
||||
"""
|
||||
|
||||
course = modulestore.get_item(course_location)
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Tests for xmodule.util.date_utils
|
||||
"""Tests for xmodule.util.date_utils"""
|
||||
|
||||
from nose.tools import assert_equals, assert_false
|
||||
from xmodule.util.date_utils import get_default_time_display, almost_same_datetime
|
||||
@@ -19,6 +19,7 @@ def test_get_default_time_display():
|
||||
"Mar 12, 1992 at 15:03",
|
||||
get_default_time_display(test_time, False))
|
||||
|
||||
|
||||
def test_get_default_time_display_notz():
|
||||
test_time = datetime(1992, 3, 12, 15, 3, 30)
|
||||
assert_equals(
|
||||
@@ -31,8 +32,10 @@ def test_get_default_time_display_notz():
|
||||
"Mar 12, 1992 at 15:03",
|
||||
get_default_time_display(test_time, False))
|
||||
|
||||
|
||||
# pylint: disable=W0232
|
||||
class NamelessTZ(tzinfo):
|
||||
"""Static timezone for testing"""
|
||||
|
||||
def utcoffset(self, _dt):
|
||||
return timedelta(hours=-3)
|
||||
@@ -40,6 +43,7 @@ class NamelessTZ(tzinfo):
|
||||
def dst(self, _dt):
|
||||
return timedelta(0)
|
||||
|
||||
|
||||
def test_get_default_time_display_no_tzname():
|
||||
assert_equals("", get_default_time_display(None))
|
||||
test_time = datetime(1992, 3, 12, 15, 3, 30, tzinfo=NamelessTZ())
|
||||
@@ -53,6 +57,7 @@ def test_get_default_time_display_no_tzname():
|
||||
"Mar 12, 1992 at 15:03",
|
||||
get_default_time_display(test_time, False))
|
||||
|
||||
|
||||
def test_almost_same_datetime():
|
||||
assert almost_same_datetime(
|
||||
datetime(2013, 5, 3, 10, 20, 30),
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
"""
|
||||
Tests of XML export
|
||||
"""
|
||||
|
||||
import unittest
|
||||
import pytz
|
||||
|
||||
from datetime import datetime, timedelta, tzinfo
|
||||
from fs.osfs import OSFS
|
||||
from mock import Mock
|
||||
from path import path
|
||||
from tempfile import mkdtemp
|
||||
import shutil
|
||||
@@ -136,19 +139,22 @@ class RoundTripTestCase(unittest.TestCase):
|
||||
|
||||
|
||||
class TestEdxJsonEncoder(unittest.TestCase):
|
||||
"""
|
||||
Tests for xml_exporter.EdxJSONEncoder
|
||||
"""
|
||||
def setUp(self):
|
||||
self.encoder = EdxJSONEncoder()
|
||||
|
||||
class OffsetTZ(tzinfo):
|
||||
"""A timezone with non-None utcoffset"""
|
||||
def utcoffset(self, dt):
|
||||
def utcoffset(self, _dt):
|
||||
return timedelta(hours=4)
|
||||
|
||||
self.offset_tz = OffsetTZ()
|
||||
|
||||
class NullTZ(tzinfo):
|
||||
"""A timezone with None as its utcoffset"""
|
||||
def utcoffset(self, dt):
|
||||
def utcoffset(self, _dt):
|
||||
return None
|
||||
self.null_utc_tz = NullTZ()
|
||||
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
"""
|
||||
Convenience methods for working with datetime objects
|
||||
"""
|
||||
|
||||
import datetime
|
||||
def get_default_time_display(dt, show_timezone=True):
|
||||
"""
|
||||
|
||||
Reference in New Issue
Block a user