@@ -6,7 +6,7 @@ use crate::python_test_result::PythonTestResult;
66use lazy_static:: lazy_static;
77use std:: collections:: { HashMap , HashSet } ;
88use std:: env;
9- use std:: io:: BufReader ;
9+ use std:: io:: { BufReader , Read , Seek } ;
1010use std:: path:: { Path , PathBuf } ;
1111use std:: time:: Duration ;
1212use tmc_langs_framework:: {
@@ -17,6 +17,7 @@ use tmc_langs_framework::{
1717 file_util,
1818 nom:: { branch, bytes, character, combinator, sequence, IResult } ,
1919 plugin:: LanguagePlugin ,
20+ zip:: ZipArchive ,
2021 TmcError , TmcProjectYml ,
2122} ;
2223use walkdir:: WalkDir ;
@@ -366,6 +367,52 @@ impl LanguagePlugin for Python3Plugin {
366367 str:: trim,
367368 ) ( i)
368369 }
370+
371+ fn find_project_dir_in_zip < R : Read + Seek > (
372+ zip_archive : & mut ZipArchive < R > ,
373+ ) -> Result < PathBuf , TmcError > {
374+ let mut lowest_ipynb_dir = None :: < PathBuf > ;
375+
376+ for i in 0 ..zip_archive. len ( ) {
377+ // zips don't necessarily contain entries for intermediate directories,
378+ // so we need to check every path for src
379+ let file = zip_archive. by_index ( i) ?;
380+ let file_path = Path :: new ( file. name ( ) ) ;
381+
382+ if file_path. components ( ) . any ( |c| c. as_os_str ( ) == "src" ) {
383+ let path: PathBuf = file_path
384+ . components ( )
385+ . take_while ( |c| c. as_os_str ( ) != "src" )
386+ . collect ( ) ;
387+
388+ if path. components ( ) . any ( |p| p. as_os_str ( ) == "__MACOSX" ) {
389+ continue ;
390+ }
391+ return Ok ( path) ;
392+ }
393+
394+ if file_path
395+ . extension ( )
396+ . map ( |ext| ext == "ipynb" )
397+ . unwrap_or_default ( )
398+ {
399+ let parent = file_path. parent ( ) . unwrap_or ( Path :: new ( "./" ) ) ;
400+ if let Some ( lowest_ipynb_dir) = lowest_ipynb_dir. as_mut ( ) {
401+ if lowest_ipynb_dir. components ( ) . count ( ) > parent. components ( ) . count ( ) {
402+ * lowest_ipynb_dir = parent. to_path_buf ( ) ;
403+ }
404+ } else {
405+ lowest_ipynb_dir = Some ( parent. to_path_buf ( ) ) ;
406+ }
407+ }
408+ }
409+
410+ if let Some ( lowest_ipynb_dir) = lowest_ipynb_dir {
411+ Ok ( lowest_ipynb_dir)
412+ } else {
413+ Err ( TmcError :: NoProjectDirInZip )
414+ }
415+ }
369416}
370417
371418#[ cfg( test) ]
0 commit comments