From 2bf39667166c2147ee1721fa9c4489b41374dff4 Mon Sep 17 00:00:00 2001 From: Don Mitchell Date: Fri, 9 Jan 2015 16:23:39 -0500 Subject: [PATCH 1/2] Add a fix_not_found command to get rid of dangling children references to blocks. TNL-1141 --- .../management/commands/fix_not_found.py | 27 +++++++++++++++++++ .../xmodule/modulestore/split_migrator.py | 2 +- .../xmodule/modulestore/split_mongo/split.py | 16 ++++++----- .../modulestore/split_mongo/split_draft.py | 10 +++++++ 4 files changed, 48 insertions(+), 7 deletions(-) create mode 100644 cms/djangoapps/contentstore/management/commands/fix_not_found.py diff --git a/cms/djangoapps/contentstore/management/commands/fix_not_found.py b/cms/djangoapps/contentstore/management/commands/fix_not_found.py new file mode 100644 index 0000000000..392a72aa24 --- /dev/null +++ b/cms/djangoapps/contentstore/management/commands/fix_not_found.py @@ -0,0 +1,27 @@ +""" +Script for fixing the item not found errors in a course +""" +from django.core.management.base import BaseCommand, CommandError +from opaque_keys.edx.keys import CourseKey +from xmodule.modulestore.django import modulestore +from xmodule.modulestore import ModuleStoreEnum + +# To run from command line: ./manage.py cms fix_not_found course-v1:org+course+run + + +class Command(BaseCommand): + """Fix a course's item not found errors""" + help = "Fix a course's ItemNotFound errors" + + def handle(self, *args, **options): + "Execute the command" + if len(args) != 1: + raise CommandError("requires 1 argument: ") + + course_key = CourseKey.from_string(args[0]) + # for now only support on split mongo + owning_store = modulestore()._get_modulestore_for_courseid(course_key) + if hasattr(owning_store, 'fix_not_found'): + owning_store.fix_not_found(course_key, ModuleStoreEnum.UserID.mgmt_command) + else: + raise CommandError("The owning modulestore does not support this command.") diff --git a/common/lib/xmodule/xmodule/modulestore/split_migrator.py b/common/lib/xmodule/xmodule/modulestore/split_migrator.py index 8788e0679d..97191258ad 100644 --- a/common/lib/xmodule/xmodule/modulestore/split_migrator.py +++ b/common/lib/xmodule/xmodule/modulestore/split_migrator.py @@ -119,7 +119,7 @@ class SplitMigrator(object): # clean up orphans in published version: in old mongo, parents pointed to the union of their published and draft # children which meant some pointers were to non-existent locations in 'direct' - self.split_modulestore.internal_clean_children(course_version_locator) + self.split_modulestore.fix_not_found(course_version_locator, user_id) def _add_draft_modules_to_course(self, published_course_usage_key, source_course_key, user_id, **kwargs): """ diff --git a/common/lib/xmodule/xmodule/modulestore/split_mongo/split.py b/common/lib/xmodule/xmodule/modulestore/split_mongo/split.py index 5cb62bcf57..3874d8d872 100644 --- a/common/lib/xmodule/xmodule/modulestore/split_mongo/split.py +++ b/common/lib/xmodule/xmodule/modulestore/split_mongo/split.py @@ -2418,22 +2418,26 @@ class SplitMongoModuleStore(SplitBulkWriteMixin, ModuleStoreWriteBase): # update the index entry if appropriate self._update_head(dest_course_key, index_entry, dest_course_key.branch, new_structure['_id']) - def internal_clean_children(self, course_locator): + def fix_not_found(self, course_locator, user_id): """ Only intended for rather low level methods to use. Goes through the children attrs of - each block removing any whose block_id is not a member of the course. Does not generate - a new version of the course but overwrites the existing one. + each block removing any whose block_id is not a member of the course. :param course_locator: the course to clean """ original_structure = self._lookup_course(course_locator).structure - for block in original_structure['blocks'].itervalues(): + 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(): if 'fields' in block and 'children' in block['fields']: block['fields']["children"] = [ block_id for block_id in block['fields']["children"] - if block_id in original_structure['blocks'] + if block_id in new_structure['blocks'] ] - self.update_structure(course_locator, original_structure) + self.update_structure(course_locator, new_structure) + if index_entry is not None: + # update the index entry if appropriate + self._update_head(course_locator, index_entry, course_locator.branch, new_structure['_id']) def convert_references_to_keys(self, course_key, xblock_class, jsonfields, blocks): """ diff --git a/common/lib/xmodule/xmodule/modulestore/split_mongo/split_draft.py b/common/lib/xmodule/xmodule/modulestore/split_mongo/split_draft.py index 11b23295a4..77699fdd59 100644 --- a/common/lib/xmodule/xmodule/modulestore/split_mongo/split_draft.py +++ b/common/lib/xmodule/xmodule/modulestore/split_mongo/split_draft.py @@ -251,6 +251,16 @@ class DraftVersioningModuleStore(SplitMongoModuleStore, ModuleStoreDraftAndPubli course_key = self._map_revision_to_branch(course_key) return super(DraftVersioningModuleStore, self).get_orphans(course_key, **kwargs) + def fix_not_found(self, course_key, user_id): + """ + Fix any children which point to non-existent blocks in the course's published and draft branches + """ + for branch in [ModuleStoreEnum.RevisionOption.published_only, ModuleStoreEnum.RevisionOption.draft_only]: + super(DraftVersioningModuleStore, self).fix_not_found( + self._map_revision_to_branch(course_key, branch), + user_id + ) + def has_changes(self, xblock): """ Checks if the given block has unpublished changes From cc617158886968cf1d75bcd5b6f9cdc0f145ceef Mon Sep 17 00:00:00 2001 From: Sarina Canelake Date: Mon, 12 Jan 2015 09:56:16 -0500 Subject: [PATCH 2/2] fix es translation --- conf/locale/es_419/LC_MESSAGES/django.mo | Bin 415813 -> 415812 bytes conf/locale/es_419/LC_MESSAGES/django.po | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/conf/locale/es_419/LC_MESSAGES/django.mo b/conf/locale/es_419/LC_MESSAGES/django.mo index ae98921775a13ce26d020a5e8360fd6fee434273..3b2149f0dacb376c683d5d7956fe763c2ac95d17 100644 GIT binary patch delta 2155 zcmXZce@vBC9LMoluN1SW3{`ot-yO!}t(z`;;!`rbE zZ@|Ye8@HJq<}P!$xzBtt>4S+0`)%Nm`HI3@+7yqihmG6R!w@*?kIn2(Ea9$t@acolZwbli(N@vE4N?^ypsypjG{)Owdt^G9$7 z=2VBz3vmwpL_ovSSc^*idh2h-0{YM56g+_W*n?X5byVQ*Vj-Tx8XU#NSh?7{`M3qE zFpYKiEv7K9#=ATWR@1neMhhyCc6+eR#ye3bdep@ly}Ei{M<=&X4G71(7|D*wU+`noU!wW!Rj!`b*WD%D+B zihZc7`v!CH2du_nOt8NzNO^Z11I?(rZ$(A86Sd*Xs8sjkN*uyxFuEkn%wAN$U8t0H zqvj3ZEqDsG{x7J5j^V9%1>4x)l`aiax*rv3H!9K-s2b?USvZKw#6?t*{e}uOvMihz zLtRNR>WY$PJu1K^)a&~ws@9&uKpXC$QH*;~ch!fA_F4&2#l(2Bx5% zN6qQxY_kL>@w^N*uL4z5$$H*@ZLov^70W6t#4Xl8fR*&$LKV+N)CVVTxp%i=9qRd$ zs4GgNQvNK?_UkY`=yKQ_8PQ2zezB!;VjX!L+fiBc1^f2lqX;kV?qfYcW>MqZq zQvM@qgP&2w^*bt%F)YV|hVX;ch+3xw6~Ggy8Va`3n5bUVNxLzLy{JD9qweYtR56ZO zKff^yAclHA$1Ft!T463k1z3an;x(XZYZJ15;GUF(J>mPh z0q^5~$54Tdpo;cC)SVXJ8`eYKAI TJ6-ePH+ynsootNzf9L)WFCz#j delta 2156 zcmXZce`u9e9LMoavLiYRMrgtMX%B?j8H0=l-eiE*f>NH0j-K^cPloHy>-UGveG<>tC+&?smqb)!rpA2N&XE zyc0L!G~8)+nSt4D_Ly&0`(WyYeKv5wJZK&=kC?~I_swDRg!z#wmi#50aW4IM(U>Dwldr&(*jMMRB>wk`S(Z7hA?;7g;am+)% zBz!&>=g_YTXm}dyQK{c({cSj#{>yj^?#CQFgqrvRRN$Xr0x#iGoWNRKTzrnjZ7+8xs`^~5bUqdbU4l30{*n;QqC5$zOnc0I1xEGbu zKGb`|cpsid&HpQEqmx*IH?f`dUCFXArTb8k_Msv@j;etnEWk7>6IW41_B$%jXjAxJ z9_mPnP)Af_u0RFYhWdP;Mb+917-+%WH0I$OsIwYGMf?M5qHCytCQt#~K)n}P9%djL z^*mVJ)>4Yt_$I-L5NMSE#eR zfJ*sKs0DsO71tlAKqj#a^H+rz)}yF-Qm6nrP&E|npfOdwsGasm15)oX2Hd+!8L>+!}tb zTdjz4P8&szU4)O)eVy=&6#;W8J=kqdIH>lN^NRgXg4Yo$58W~M+G*Cx*-dm^6nw5 z#blDkb{hKb2T(_G8C4S#n83*T@Wnz@aW;0x(>?KYgkO~3G=3SQ@pNW(XIA@`RL7=Q S-I{|Z`Z5bfS0(*_h5rNdz6gf^ diff --git a/conf/locale/es_419/LC_MESSAGES/django.po b/conf/locale/es_419/LC_MESSAGES/django.po index 5273795133..22cdcce3bf 100644 --- a/conf/locale/es_419/LC_MESSAGES/django.po +++ b/conf/locale/es_419/LC_MESSAGES/django.po @@ -10613,7 +10613,7 @@ msgstr "Gracias por su paciencia mientras se procesa su solicitud." #: lms/templates/dashboard/_dashboard_course_listing.html msgid "Your verification status is good until {date}." -msgstr "Su estado de verificación es bueno hasta {fecha}" +msgstr "Su estado de verificación es bueno hasta {date}" #: lms/templates/dashboard/_dashboard_course_listing.html msgid "Challenge Yourself!"