Skip to content

Commit

Permalink
implement pip_check and do not use run_test.py anymore
Browse files Browse the repository at this point in the history
  • Loading branch information
wolfv committed Jan 5, 2024
1 parent 307a55a commit 5e1e749
Show file tree
Hide file tree
Showing 5 changed files with 62 additions and 49 deletions.
7 changes: 1 addition & 6 deletions examples/rich/recipe.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,8 @@ requirements:

tests:
- python:
imports:
imports:
- rich
- script:
- pip check
requirements:
run:
- pip

about:
homepage: https://github.com/Textualize/rich
Expand Down
2 changes: 1 addition & 1 deletion rust-tests/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -429,7 +429,7 @@ mod tests {
.join("info/tests/1/test_time_dependencies.json")
.exists());

assert!(pkg.join("info/tests/0/run_test.py").exists());
assert!(pkg.join("info/tests/0/python_test.json").exists());
// make sure that the entry point does not exist
assert!(!pkg.join("python-scripts/flask").exists());

Expand Down
64 changes: 40 additions & 24 deletions src/package_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,9 @@ use rattler_shell::{
};

use crate::{
env_vars, index, recipe::parser::CommandsTestRequirements, render::solver::create_environment,
env_vars, index,
recipe::parser::{CommandsTestRequirements, PackageContents, PythonTest},
render::solver::create_environment,
tool_configuration,
};

Expand Down Expand Up @@ -368,19 +370,25 @@ pub async fn run_test(package_file: &Path, config: &TestConfiguration) -> Result

async fn run_python_test(
pkg: &ArchiveIdentifier,
_path: &Path,
path: &Path,
prefix: &Path,
config: &TestConfiguration,
) -> Result<(), TestError> {
// create environment with the test dependencies
let test_file = path.join("python_test.json");
let test: PythonTest = serde_json::from_str(&fs::read_to_string(test_file)?)?;

let match_spec =
MatchSpec::from_str(format!("{}={}={}", pkg.name, pkg.version, pkg.build_string).as_str())
.unwrap();
let mut dependencies = vec![match_spec];
if test.pip_check {
dependencies.push(MatchSpec::from_str("pip").unwrap());
}

let platform = Platform::current();

create_environment(
&[match_spec],
&dependencies,
&platform,
prefix,
&config.channels,
Expand All @@ -389,7 +397,29 @@ async fn run_python_test(
.await
.map_err(TestError::TestEnvironmentSetup)?;

Ok(())
let default_shell = ShellEnum::default();

let mut test_file = tempfile::Builder::new()
.prefix("rattler-test-")
.suffix(".py")
.tempfile()?;

for import in test.imports {
writeln!(test_file, "import {}", import)?;
}

run_in_environment(
default_shell.clone(),
format!("python {}", test_file.path().to_string_lossy()),
path,
prefix,
)?;

if test.pip_check {
run_in_environment(default_shell, "pip check".into(), path, prefix)
} else {
Ok(())
}
}

async fn run_shell_test(
Expand All @@ -398,7 +428,6 @@ async fn run_shell_test(
prefix: &Path,
config: &TestConfiguration,
) -> Result<(), TestError> {
// read the test dependencies
let deps = if path.join("test_time_dependencies.json").exists() {
let test_dep_json = path.join("test_time_dependencies.json");
serde_json::from_str(&fs::read_to_string(test_dep_json)?)?
Expand Down Expand Up @@ -441,21 +470,10 @@ async fn run_shell_test(
path.join("run_test.sh")
};

let contents = fs::read_to_string(&test_file_path)?;
let is_path_ext = |ext: &str| {
test_file_path
.extension()
.map(|s| s.eq(ext))
.unwrap_or_default()
};
let contents = fs::read_to_string(test_file_path)?;

if Platform::current().is_windows() && is_path_ext("bat") {
tracing::info!("Testing commands:");
run_in_environment(default_shell, contents, path, prefix)?;
} else if Platform::current().is_unix() && is_path_ext("sh") {
tracing::info!("Testing commands:");
run_in_environment(default_shell, contents, path, prefix)?;
}
tracing::info!("Testing commands:");
run_in_environment(default_shell, contents, path, prefix)?;

Ok(())
}
Expand All @@ -466,9 +484,7 @@ async fn run_individual_test(
prefix: &Path,
config: &TestConfiguration,
) -> Result<(), TestError> {
// detect which of the test files we have
if path.join("run_test.py").exists() {
// run python test
if path.join("python_test.json").exists() {
run_python_test(pkg, path, prefix, config).await?;
} else if path.join("run_test.sh").exists() || path.join("run_test.bat").exists() {
// run shell test
Expand All @@ -490,7 +506,7 @@ async fn run_individual_test(
/// * `Ok(())` if the test was successful
/// * `Err(TestError::TestFailed)` if the test failed
pub async fn run_package_content_tests(
package_content: &crate::recipe::parser::PackageContents,
package_content: &PackageContents,
paths_json: &PathsJson,
target_platform: &Platform,
) -> Result<(), TestError> {
Expand Down
19 changes: 2 additions & 17 deletions src/packaging.rs
Original file line number Diff line number Diff line change
Expand Up @@ -625,17 +625,6 @@ fn copy_license_files(
let licenses_folder = tmp_dir_path.join("info/licenses/");
fs::create_dir_all(&licenses_folder)?;

for license_glob in license_globs
.iter()
// Only license globs that do not end with '/' or '*'
.filter(|license_glob| !license_glob.ends_with('/') && !license_glob.ends_with('*'))
{
let filepath = licenses_folder.join(license_glob);
if !filepath.exists() {
tracing::warn!(path = %filepath.display(), "File does not exist");
}
}

let copy_dir = crate::source::copy_dir::CopyDir::new(
&output.build_configuration.directories.recipe_dir,
&licenses_folder,
Expand Down Expand Up @@ -828,12 +817,8 @@ fn serialize_python_test(
let folder = tmp_dir_path.join(format!("info/tests/{}", idx));
fs::create_dir_all(&folder)?;

let path = folder.join("run_test.py");
let mut file = File::create(&path)?;

for el in &python_test.imports {
writeln!(file, "import {}", el)?;
}
let path = folder.join("python_test.json");
serde_json::to_writer(&File::create(&path)?, python_test)?;

Ok(vec![path])
}
Expand Down
19 changes: 18 additions & 1 deletion src/recipe/parser/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,11 @@ use super::FlattenErrors;
pub struct CommandsTestRequirements {
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub run: Vec<String>,

#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub build: Vec<String>,
}

#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
pub struct CommandsTestFiles {
// TODO parse as globs
Expand Down Expand Up @@ -51,10 +53,23 @@ impl CommandsTestFiles {
}
}

fn default_pip_check() -> bool {
true
}

fn is_true(value: &bool) -> bool {
*value
}

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct PythonTest {
/// List of imports to test
pub imports: Vec<String>,
/// Wether to run `pip check` or not (default to true)
#[serde(default = "default_pip_check", skip_serializing_if = "is_true")]
pub pip_check: bool,
}

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct DownstreamTest {
pub downstream: String,
Expand Down Expand Up @@ -216,12 +231,14 @@ impl TryConvertNode<TestType> for RenderedMappingNode {
impl TryConvertNode<PythonTest> for RenderedMappingNode {
fn try_convert(&self, name: &str) -> Result<PythonTest, Vec<PartialParsingError>> {
let mut imports = vec![];
let mut pip_check = true;

self.iter()
.map(|(key, value)| {
let key_str = key.as_str();
match key_str {
"imports" => imports = value.try_convert(key_str)?,
"pip_check" => pip_check = value.try_convert(key_str)?,
invalid => Err(vec![_partialerror!(
*key.span(),
ErrorKind::InvalidField(invalid.to_string().into()),
Expand All @@ -240,7 +257,7 @@ impl TryConvertNode<PythonTest> for RenderedMappingNode {
)])?;
}

Ok(PythonTest { imports })
Ok(PythonTest { imports, pip_check })
}
}

Expand Down

0 comments on commit 5e1e749

Please sign in to comment.