2626from django .test import RequestFactory
2727from django .utils .text import get_valid_filename
2828from edx_django_utils .monitoring import (
29- set_code_owner_attribute ,
30- set_code_owner_attribute_from_module ,
3129 set_custom_attribute ,
3230 set_custom_attributes_for_course_key ,
3331)
@@ -166,7 +164,6 @@ def clone_instance(instance, field_values):
166164
167165
168166@shared_task
169- @set_code_owner_attribute
170167def rerun_course (source_course_key_string , destination_course_key_string , user_id , fields = None ):
171168 """
172169 Reruns a course in a new celery task.
@@ -262,7 +259,6 @@ def _parse_time(time_isoformat):
262259
263260
264261@shared_task
265- @set_code_owner_attribute
266262def update_search_index (course_id , triggered_time_isoformat ):
267263 """ Updates course search index. """
268264 try :
@@ -293,7 +289,6 @@ def update_search_index(course_id, triggered_time_isoformat):
293289
294290
295291@shared_task
296- @set_code_owner_attribute
297292def update_library_index (library_id , triggered_time_isoformat ):
298293 """ Updates course search index. """
299294 try :
@@ -307,7 +302,6 @@ def update_library_index(library_id, triggered_time_isoformat):
307302
308303
309304@shared_task
310- @set_code_owner_attribute
311305def update_special_exams_and_publish (course_key_str ):
312306 """
313307 Registers special exams for a given course and calls publishing flow.
@@ -368,13 +362,11 @@ def generate_name(cls, arguments_dict):
368362
369363
370364@shared_task (base = CourseExportTask , bind = True )
371- # Note: The decorator @set_code_owner_attribute cannot be used here because the UserTaskMixin
372365# does stack inspection and can't handle additional decorators.
373366def export_olx (self , user_id , course_key_string , language ):
374367 """
375368 Export a course or library to an OLX .tar.gz archive and prepare it for download.
376369 """
377- set_code_owner_attribute_from_module (__name__ )
378370 courselike_key = CourseKey .from_string (course_key_string )
379371
380372 try :
@@ -546,14 +538,12 @@ def sync_discussion_settings(course_key, user):
546538
547539
548540@shared_task (base = CourseImportTask , bind = True )
549- # Note: The decorator @set_code_owner_attribute cannot be used here because the UserTaskMixin
550541# does stack inspection and can't handle additional decorators.
551542# pylint: disable=too-many-statements
552543def import_olx (self , user_id , course_key_string , archive_path , archive_name , language ):
553544 """
554545 Import a course or library from a provided OLX .tar.gz or .zip archive.
555546 """
556- set_code_owner_attribute_from_module (__name__ )
557547 current_step = 'Unpacking'
558548 courselike_key = CourseKey .from_string (course_key_string )
559549 set_custom_attributes_for_course_key (courselike_key )
@@ -789,7 +779,6 @@ def read_chunk():
789779
790780
791781@shared_task
792- @set_code_owner_attribute
793782def update_all_outlines_from_modulestore_task ():
794783 """
795784 Celery task that creates multiple celery tasks - one per learning_sequence course outline
@@ -816,7 +805,6 @@ def update_all_outlines_from_modulestore_task():
816805
817806
818807@shared_task
819- @set_code_owner_attribute
820808def update_outline_from_modulestore_task (course_key_str : str ):
821809 """
822810 Celery task that creates a learning_sequence course outline.
@@ -961,7 +949,6 @@ def _get_users_by_access_level(v1_library_key):
961949
962950
963951@shared_task (time_limit = 30 )
964- @set_code_owner_attribute
965952def delete_v1_library (v1_library_key_string ):
966953 """
967954 Delete a v1 library index by key string.
@@ -987,6 +974,146 @@ def delete_v1_library(v1_library_key_string):
987974 }
988975
989976
977+ @shared_task (time_limit = 30 )
978+ def validate_all_library_source_blocks_ids_for_course (course_key_string , v1_to_v2_lib_map ):
979+ """Search a Modulestore for all library source blocks in a course by querying mongo.
980+ replace all source_library_ids with the corresponding v2 value from the map
981+ """
982+ course_id = CourseKey .from_string (course_key_string )
983+ store = modulestore ()
984+ with store .bulk_operations (course_id ):
985+ visited = []
986+ for branch in [ModuleStoreEnum .BranchName .draft , ModuleStoreEnum .BranchName .published ]:
987+ blocks = store .get_items (
988+ course_id .for_branch (branch ),
989+ settings = {'source_library_id' : {'$exists' : True }}
990+ )
991+ for xblock in blocks :
992+ if xblock .source_library_id not in v1_to_v2_lib_map .values ():
993+ # pylint: disable=broad-except
994+ raise Exception (
995+ f'{ xblock .source_library_id } in { course_id } is not found in mapping. Validation failed'
996+ )
997+ visited .append (xblock .source_library_id )
998+ # return sucess
999+ return visited
1000+
1001+
1002+ @shared_task (time_limit = 30 )
1003+ def replace_all_library_source_blocks_ids_for_course (course_key_string , v1_to_v2_lib_map ): # pylint: disable=useless-return
1004+ """Search a Modulestore for all library source blocks in a course by querying mongo.
1005+ replace all source_library_ids with the corresponding v2 value from the map.
1006+
1007+ This will trigger a publish on the course for every published library source block.
1008+ """
1009+ store = modulestore ()
1010+ course_id = CourseKey .from_string (course_key_string )
1011+
1012+ with store .bulk_operations (course_id ):
1013+ #for branch in [ModuleStoreEnum.BranchName.draft, ModuleStoreEnum.BranchName.published]:
1014+ draft_blocks , published_blocks = [
1015+ store .get_items (
1016+ course_id .for_branch (branch ),
1017+ settings = {'source_library_id' : {'$exists' : True }}
1018+ )
1019+ for branch in [ModuleStoreEnum .BranchName .draft , ModuleStoreEnum .BranchName .published ]
1020+ ]
1021+
1022+ published_dict = {block .location : block for block in published_blocks }
1023+
1024+ for draft_library_source_block in draft_blocks :
1025+ try :
1026+ new_source_id = str (v1_to_v2_lib_map [draft_library_source_block .source_library_id ])
1027+ except KeyError :
1028+ #skip invalid keys
1029+ LOGGER .error (
1030+ 'Key %s not found in mapping. Skipping block for course %s' ,
1031+ str ({draft_library_source_block .source_library_id }),
1032+ str (course_id )
1033+ )
1034+ continue
1035+
1036+ # The publsihed branch should be updated as well as the draft branch
1037+ # This way, if authors "discard changes," they won't be reverted back to the V1 lib.
1038+ # However, we also don't want to publish the draft branch.
1039+ try :
1040+ if published_dict [draft_library_source_block .location ] is not None :
1041+ #temporarily set the published version to be the draft & publish it.
1042+ temp = published_dict [draft_library_source_block .location ]
1043+ temp .source_library_id = new_source_id
1044+ store .update_item (temp , None )
1045+ store .publish (temp .location , None )
1046+ draft_library_source_block .source_library_id = new_source_id
1047+ store .update_item (draft_library_source_block , None )
1048+ except KeyError :
1049+ #Warn, but just update the draft block if no published block for draft block.
1050+ LOGGER .warning (
1051+ 'No matching published block for draft block %s' ,
1052+ str (draft_library_source_block .location )
1053+ )
1054+ draft_library_source_block .source_library_id = new_source_id
1055+ store .update_item (draft_library_source_block , None )
1056+ # return success
1057+ return
1058+
1059+
1060+ @shared_task (time_limit = 30 )
1061+ def undo_all_library_source_blocks_ids_for_course (course_key_string , v1_to_v2_lib_map ): # pylint: disable=useless-return
1062+ """Search a Modulestore for all library source blocks in a course by querying mongo.
1063+ replace all source_library_ids with the corresponding v1 value from the inverted map.
1064+ This is exists to undo changes made previously.
1065+ """
1066+ course_id = CourseKey .from_string (course_key_string )
1067+
1068+ v2_to_v1_lib_map = {v : k for k , v in v1_to_v2_lib_map .items ()}
1069+
1070+ store = modulestore ()
1071+ draft_blocks , published_blocks = [
1072+ store .get_items (
1073+ course_id .for_branch (branch ),
1074+ settings = {'source_library_id' : {'$exists' : True }}
1075+ )
1076+ for branch in [ModuleStoreEnum .BranchName .draft , ModuleStoreEnum .BranchName .published ]
1077+ ]
1078+
1079+ published_dict = {block .location : block for block in published_blocks }
1080+
1081+ for draft_library_source_block in draft_blocks :
1082+ try :
1083+ new_source_id = str (v2_to_v1_lib_map [draft_library_source_block .source_library_id ])
1084+ except KeyError :
1085+ #skip invalid keys
1086+ LOGGER .error (
1087+ 'Key %s not found in mapping. Skipping block for course %s' ,
1088+ str ({draft_library_source_block .source_library_id }),
1089+ str (course_id )
1090+ )
1091+ continue
1092+
1093+ # The publsihed branch should be updated as well as the draft branch
1094+ # This way, if authors "discard changes," they won't be reverted back to the V1 lib.
1095+ # However, we also don't want to publish the draft branch.
1096+ try :
1097+ if published_dict [draft_library_source_block .location ] is not None :
1098+ #temporarily set the published version to be the draft & publish it.
1099+ temp = published_dict [draft_library_source_block .location ]
1100+ temp .source_library_id = new_source_id
1101+ store .update_item (temp , None )
1102+ store .publish (temp .location , None )
1103+ draft_library_source_block .source_library_id = new_source_id
1104+ store .update_item (draft_library_source_block , None )
1105+ except KeyError :
1106+ #Warn, but just update the draft block if no published block for draft block.
1107+ LOGGER .warning (
1108+ 'No matching published block for draft block %s' ,
1109+ str (draft_library_source_block .location )
1110+ )
1111+ draft_library_source_block .source_library_id = new_source_id
1112+ store .update_item (draft_library_source_block , None )
1113+ # return success
1114+ return
1115+
1116+
9901117class CourseLinkCheckTask (UserTask ): # pylint: disable=abstract-method
9911118 """
9921119 Base class for course link check tasks.
@@ -1021,13 +1148,11 @@ def generate_name(cls, arguments_dict):
10211148
10221149
10231150@shared_task (base = CourseLinkCheckTask , bind = True )
1024- # Note: The decorator @set_code_owner_attribute cannot be used here because the UserTaskMixin
10251151# does stack inspection and can't handle additional decorators.
10261152def check_broken_links (self , user_id , course_key_string , language ):
10271153 """
10281154 Checks for broken links in a course and store the results in a file.
10291155 """
1030- set_code_owner_attribute_from_module (__name__ )
10311156 return _check_broken_links (self , user_id , course_key_string , language )
10321157
10331158
@@ -1495,7 +1620,6 @@ def _write_broken_links_to_file(broken_or_locked_urls, broken_links_file):
14951620
14961621
14971622@shared_task
1498- @set_code_owner_attribute
14991623def handle_create_xblock_upstream_link (usage_key ):
15001624 """
15011625 Create upstream link for a single xblock.
@@ -1523,7 +1647,6 @@ def handle_create_xblock_upstream_link(usage_key):
15231647
15241648
15251649@shared_task
1526- @set_code_owner_attribute
15271650def handle_update_xblock_upstream_link (usage_key ):
15281651 """
15291652 Update upstream link for a single xblock.
@@ -1540,7 +1663,6 @@ def handle_update_xblock_upstream_link(usage_key):
15401663
15411664
15421665@shared_task
1543- @set_code_owner_attribute
15441666def create_or_update_upstream_links (
15451667 course_key_str : str ,
15461668 force : bool = False ,
@@ -1581,7 +1703,6 @@ def create_or_update_upstream_links(
15811703
15821704
15831705@shared_task
1584- @set_code_owner_attribute
15851706def handle_unlink_upstream_block (upstream_usage_key_string : str ) -> None :
15861707 """
15871708 Handle updates needed to downstream blocks when the upstream link is severed.
@@ -1601,7 +1722,6 @@ def handle_unlink_upstream_block(upstream_usage_key_string: str) -> None:
16011722
16021723
16031724@shared_task
1604- @set_code_owner_attribute
16051725def handle_unlink_upstream_container (upstream_container_key_string : str ) -> None :
16061726 """
16071727 Handle updates needed to downstream blocks when the upstream link is severed.
@@ -1658,7 +1778,6 @@ def update_course_rerun_links(
16581778 """
16591779 Updates course links to point to the latest re-run.
16601780 """
1661- set_code_owner_attribute_from_module (__name__ )
16621781 return _update_course_rerun_links (
16631782 self , user_id , course_id , action , data , language
16641783 )
@@ -2214,7 +2333,6 @@ def migrate_course_legacy_library_blocks_to_item_bank(
22142333 leaving migrated blocks as drafts.
22152334 """
22162335 ensure_cms ("Legacy library content references may only be executed in CMS" )
2217- set_code_owner_attribute_from_module (__name__ )
22182336 _cancel_old_tasks (course_key , self .status .user , [self .status .task_id ])
22192337 try :
22202338 key = CourseKey .from_string (course_key )
0 commit comments