Skip to content

Commit d2012ab

Browse files
committed
Added detection of lowest ipynb containing dir as project directory in zips
1 parent a5e4a73 commit d2012ab

File tree

3 files changed

+71
-2
lines changed

3 files changed

+71
-2
lines changed

plugins/python3/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ serde_json = "1"
2020
sha2 = "0.9"
2121
thiserror = "1"
2222
walkdir = "2"
23+
zip = "0.5"
2324

2425
[dev-dependencies]
2526
simple_logger = "1"

plugins/python3/src/plugin.rs

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use rand::Rng;
99
use sha2::Sha256;
1010
use std::collections::{HashMap, HashSet};
1111
use std::env;
12-
use std::io::BufReader;
12+
use std::io::{BufReader, Read, Seek};
1313
use std::path::{Path, PathBuf};
1414
use std::time::Duration;
1515
use tmc_langs_framework::{
@@ -23,6 +23,7 @@ use tmc_langs_util::{
2323
parse_util,
2424
};
2525
use walkdir::WalkDir;
26+
use zip::ZipArchive;
2627

2728
pub struct Python3Plugin {}
2829

@@ -406,6 +407,52 @@ impl LanguagePlugin for Python3Plugin {
406407
},
407408
)(i)
408409
}
410+
411+
fn find_project_dir_in_zip<R: Read + Seek>(
412+
zip_archive: &mut ZipArchive<R>,
413+
) -> Result<PathBuf, TmcError> {
414+
let mut lowest_ipynb_dir = None::<PathBuf>;
415+
416+
for i in 0..zip_archive.len() {
417+
// zips don't necessarily contain entries for intermediate directories,
418+
// so we need to check every path for src
419+
let file = zip_archive.by_index(i)?;
420+
let file_path = Path::new(file.name());
421+
422+
if file_path.components().any(|c| c.as_os_str() == "src") {
423+
let path: PathBuf = file_path
424+
.components()
425+
.take_while(|c| c.as_os_str() != "src")
426+
.collect();
427+
428+
if path.components().any(|p| p.as_os_str() == "__MACOSX") {
429+
continue;
430+
}
431+
return Ok(path);
432+
}
433+
434+
if file_path
435+
.extension()
436+
.map(|ext| ext == "ipynb")
437+
.unwrap_or_default()
438+
{
439+
let parent = file_path.parent().unwrap_or(Path::new("./"));
440+
if let Some(lowest_ipynb_dir) = lowest_ipynb_dir.as_mut() {
441+
if lowest_ipynb_dir.components().count() > parent.components().count() {
442+
*lowest_ipynb_dir = parent.to_path_buf();
443+
}
444+
} else {
445+
lowest_ipynb_dir = Some(parent.to_path_buf());
446+
}
447+
}
448+
}
449+
450+
if let Some(lowest_ipynb_dir) = lowest_ipynb_dir {
451+
Ok(lowest_ipynb_dir)
452+
} else {
453+
Err(TmcError::NoProjectDirInZip)
454+
}
455+
}
409456
}
410457

411458
#[cfg(test)]

tmc-langs-plugins/src/tmc_zip.rs

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,8 @@ where
175175

176176
// TODO: make more robust, use language plugins?
177177
fn find_project_dir<R: Read + Seek>(zip_archive: &mut ZipArchive<R>) -> Result<PathBuf, TmcError> {
178+
let mut lowest_ipynb_dir = None::<PathBuf>;
179+
178180
for i in 0..zip_archive.len() {
179181
let file = zip_archive.by_index(i)?;
180182
let file_path = Path::new(file.name());
@@ -209,8 +211,27 @@ fn find_project_dir<R: Read + Seek>(zip_archive: &mut ZipArchive<R>) -> Result<P
209211
log::debug!("found project dir {}", parent.display());
210212
return Ok(parent.to_path_buf());
211213
}
214+
215+
if file_path
216+
.extension()
217+
.map(|ext| ext == "ipynb")
218+
.unwrap_or_default()
219+
{
220+
let parent = file_path.parent().unwrap_or(Path::new("./"));
221+
if let Some(lowest_ipynb_dir) = lowest_ipynb_dir.as_mut() {
222+
if lowest_ipynb_dir.components().count() > parent.components().count() {
223+
*lowest_ipynb_dir = parent.to_path_buf();
224+
}
225+
} else {
226+
lowest_ipynb_dir = Some(parent.to_path_buf());
227+
}
228+
}
229+
}
230+
if let Some(lowest_ipynb_dir) = lowest_ipynb_dir {
231+
Ok(lowest_ipynb_dir)
232+
} else {
233+
Err(TmcError::NoProjectDirInZip)
212234
}
213-
Err(TmcError::NoProjectDirInZip)
214235
}
215236

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

0 commit comments

Comments
 (0)