Skip to content

Commit b858f4c

Browse files
committed
Added detection of lowest ipynb containing dir as project directory in zips
1 parent 94eec1d commit b858f4c

File tree

2 files changed

+70
-2
lines changed

2 files changed

+70
-2
lines changed

plugins/python3/src/plugin.rs

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use crate::python_test_result::PythonTestResult;
66
use lazy_static::lazy_static;
77
use std::collections::{HashMap, HashSet};
88
use std::env;
9-
use std::io::BufReader;
9+
use std::io::{BufReader, Read, Seek};
1010
use std::path::{Path, PathBuf};
1111
use std::time::Duration;
1212
use 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
};
2223
use 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)]

tmc-langs-util/src/task_executor/tmc_zip.rs

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,8 @@ where
170170
}
171171

172172
fn find_project_dir<R: Read + Seek>(zip_archive: &mut ZipArchive<R>) -> Result<PathBuf, TmcError> {
173+
let mut lowest_ipynb_dir = None::<PathBuf>;
174+
173175
for i in 0..zip_archive.len() {
174176
let file = zip_archive.by_index(i)?;
175177
let file_path = Path::new(file.name());
@@ -204,8 +206,27 @@ fn find_project_dir<R: Read + Seek>(zip_archive: &mut ZipArchive<R>) -> Result<P
204206
log::debug!("found project dir {}", parent.display());
205207
return Ok(parent.to_path_buf());
206208
}
209+
210+
if file_path
211+
.extension()
212+
.map(|ext| ext == "ipynb")
213+
.unwrap_or_default()
214+
{
215+
let parent = file_path.parent().unwrap_or(Path::new("./"));
216+
if let Some(lowest_ipynb_dir) = lowest_ipynb_dir.as_mut() {
217+
if lowest_ipynb_dir.components().count() > parent.components().count() {
218+
*lowest_ipynb_dir = parent.to_path_buf();
219+
}
220+
} else {
221+
lowest_ipynb_dir = Some(parent.to_path_buf());
222+
}
223+
}
224+
}
225+
if let Some(lowest_ipynb_dir) = lowest_ipynb_dir {
226+
Ok(lowest_ipynb_dir)
227+
} else {
228+
Err(TmcError::NoProjectDirInZip)
207229
}
208-
Err(TmcError::NoProjectDirInZip)
209230
}
210231

211232
fn contains_tmcnosubmit(entry: &DirEntry) -> bool {

0 commit comments

Comments
 (0)