@@ -25,7 +25,7 @@ def sync_canvas_archive(bucket, key: str, overwrite):
2525 """
2626 Sync a Canvas course archive from S3
2727 """
28- from learning_resources .etl .loaders import load_content_files
28+ from learning_resources .etl .loaders import load_content_files , load_problem_files
2929
3030 course_folder = key .lstrip (settings .CANVAS_COURSE_BUCKET_PREFIX ).split ("/" )[0 ]
3131
@@ -43,8 +43,16 @@ def sync_canvas_archive(bucket, key: str, overwrite):
4343 course_archive_path , run , overwrite = overwrite
4444 ),
4545 )
46+
47+ load_problem_files (
48+ run ,
49+ transform_canvas_problem_files (
50+ course_archive_path , run , overwrite = overwrite
51+ ),
52+ )
4653 run .checksum = checksum
4754 run .save ()
55+
4856 return resource_readable_id , run
4957
5058
@@ -124,6 +132,42 @@ def transform_canvas_content_files(
124132 yield from _process_olx_path (olx_path , run , overwrite = overwrite )
125133
126134
135+ def transform_canvas_problem_files (
136+ course_zipfile : Path , run : LearningResourceRun , * , overwrite
137+ ) -> Generator [dict , None , None ]:
138+ """
139+ Transform problem files from a Canvas course zipfile
140+ """
141+ basedir = course_zipfile .name .split ("." )[0 ]
142+ with (
143+ TemporaryDirectory (prefix = basedir ) as olx_path ,
144+ zipfile .ZipFile (course_zipfile .absolute (), "r" ) as course_archive ,
145+ ):
146+ for member in course_archive .infolist ():
147+ if member .filename .startswith (settings .CANVAS_TUTORBOT_FOLDER ):
148+ course_archive .extract (member , path = olx_path )
149+ log .debug ("processing active problem set file %s" , member .filename )
150+ for file_data in _process_olx_path (olx_path , run , overwrite = overwrite ):
151+ keys_to_keep = [
152+ "run" ,
153+ "content" ,
154+ "archive_checksum" ,
155+ "source_path" ,
156+ "file_extension" ,
157+ ]
158+ problem_file_data = {
159+ key : file_data [key ] for key in keys_to_keep if key in file_data
160+ }
161+ path = file_data ["source_path" ]
162+ path = path [len (settings .CANVAS_TUTORBOT_FOLDER ) :]
163+ path_parts = path .split ("/" )
164+ problem_file_data ["problem_title" ] = path_parts [0 ]
165+
166+ if path_parts [1 ] in ["problem" , "solution" ]:
167+ problem_file_data ["type" ] = path_parts [1 ]
168+ yield problem_file_data
169+
170+
127171def parse_module_meta (course_archive_path : str ) -> dict :
128172 """
129173 Parse module_meta.xml and return publish/active status of resources.
0 commit comments