Skip to content

Commit 33bf78a

Browse files
Bump rattler for new lockfile support, fail on pypi packages (#22)
Co-authored-by: Pavel Zwerschke <pavel.zwerschke@quantco.com>
1 parent 4beda28 commit 33bf78a

File tree

10 files changed

+1089
-300
lines changed

10 files changed

+1089
-300
lines changed

Cargo.lock

+603-278
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[package]
22
name = "conda-deny"
33
description = "A CLI tool to check your project's dependencies for license compliance."
4-
version = "0.3.2"
4+
version = "0.3.3"
55
edition = "2021"
66

77
[features]
@@ -29,8 +29,8 @@ regex = "1.11.1"
2929
spdx = "0.10.7"
3030
colored = "2.1.0"
3131
async-trait = "0.1.83"
32-
rattler_conda_types = "0.28.3"
33-
rattler_lock = "0.22.28"
32+
rattler_conda_types = "0.29.3"
33+
rattler_lock = "0.22.32"
3434
anyhow = "1.0.93"
3535
clap-verbosity-flag = "3.0.1"
3636
env_logger = "0.11.5"

src/cli.rs

+4
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,10 @@ pub enum Commands {
3636

3737
#[arg(short, long, action = ArgAction::SetTrue)]
3838
osi: bool,
39+
40+
/// Ignore when encountering pypi packages instead of failing.
41+
#[arg(long, action = ArgAction::SetTrue)]
42+
ignore_pypi: bool,
3943
},
4044
List {},
4145
}

src/lib.rs

+6-3
Original file line numberDiff line numberDiff line change
@@ -19,26 +19,29 @@ use log::debug;
1919
use crate::conda_deny_config::CondaDenyConfig;
2020
use crate::license_info::LicenseInfos;
2121

22+
// todo: refactor this
2223
pub type CliInput<'a> = (
2324
&'a CondaDenyConfig,
2425
&'a Vec<String>,
2526
&'a Vec<String>,
2627
&'a Vec<String>,
2728
&'a Vec<String>,
2829
bool,
30+
bool,
2931
);
3032
pub type CheckOutput = (Vec<LicenseInfo>, Vec<LicenseInfo>);
3133

3234
pub fn fetch_license_infos(cli_input: CliInput) -> Result<LicenseInfos> {
33-
let (conda_deny_config, cli_lockfiles, cli_platforms, cli_environments, conda_prefixes, _) =
35+
let (conda_deny_config, cli_lockfiles, cli_platforms, cli_environments, conda_prefixes, _, cli_ignore_pypi) =
3436
cli_input;
3537

3638
if conda_prefixes.is_empty() {
3739
LicenseInfos::get_license_infos_from_config(
3840
conda_deny_config,
3941
cli_lockfiles,
4042
cli_platforms,
41-
cli_environments,
43+
cli_environments,
44+
cli_ignore_pypi,
4245
)
4346
.with_context(|| "Getting license information from config file failed.")
4447
} else {
@@ -55,7 +58,7 @@ pub fn list(cli_input: CliInput) -> Result<()> {
5558
}
5659

5760
pub fn check_license_infos(cli_input: CliInput) -> Result<CheckOutput> {
58-
let (conda_deny_config, _, _, _, _, osi) = cli_input;
61+
let (conda_deny_config, _, _, _, _, osi, _) = cli_input;
5962

6063
let license_infos =
6164
fetch_license_infos(cli_input).with_context(|| "Fetching license information failed.")?;

src/license_info.rs

+9-5
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use crate::{
1212
expression_utils::{check_expression_safety, extract_license_texts, parse_expression},
1313
license_whitelist::ParsedLicenseWhitelist,
1414
list,
15-
pixi_lock::get_package_records_for_pixi_lock,
15+
pixi_lock::get_conda_packages_for_pixi_lock,
1616
CheckOutput,
1717
};
1818

@@ -142,27 +142,30 @@ impl LicenseInfos {
142142
lockfiles: Vec<String>,
143143
platforms: Vec<String>,
144144
environment_specs: Vec<String>,
145+
ignore_pypi: bool,
145146
) -> Result<LicenseInfos> {
146147
let mut license_infos = Vec::new();
147148

148149
let mut package_records = Vec::new();
149150

150151
if lockfiles.is_empty() {
151-
let package_records_for_lockfile = get_package_records_for_pixi_lock(
152+
let package_records_for_lockfile = get_conda_packages_for_pixi_lock(
152153
None,
153154
environment_specs.clone(),
154155
platforms.clone(),
156+
ignore_pypi,
155157
)
156158
.with_context(|| "Failed to get package records for pixi.lock")?;
157159

158160
package_records.extend(package_records_for_lockfile);
159161
} else {
160162
for lockfile in lockfiles {
161163
let path = Path::new(&lockfile);
162-
let package_records_for_lockfile = get_package_records_for_pixi_lock(
164+
let package_records_for_lockfile = get_conda_packages_for_pixi_lock(
163165
Some(path),
164166
environment_specs.clone(),
165167
platforms.clone(),
168+
ignore_pypi,
166169
)
167170
.with_context(|| {
168171
format!("Failed to get package records from lockfile: {}", &lockfile)
@@ -220,6 +223,7 @@ impl LicenseInfos {
220223
cli_lockfiles: &[String],
221224
cli_platforms: &[String],
222225
cli_environments: &[String],
226+
cli_ignore_pypi: bool,
223227
) -> Result<LicenseInfos> {
224228
let mut platforms = config.get_platform_spec().map_or(vec![], |p| p);
225229
let mut lockfiles = config.get_lockfile_spec();
@@ -229,7 +233,7 @@ impl LicenseInfos {
229233
lockfiles.extend(cli_lockfiles.to_owned());
230234
environment_specs.extend(cli_environments.to_owned());
231235

232-
LicenseInfos::from_pixi_lockfiles(lockfiles, platforms, environment_specs)
236+
LicenseInfos::from_pixi_lockfiles(lockfiles, platforms, environment_specs, cli_ignore_pypi)
233237
}
234238

235239
pub fn check(&self, license_whitelist: &ParsedLicenseWhitelist) -> CheckOutput {
@@ -469,7 +473,7 @@ mod tests {
469473
"tests/test_pyproject_toml_files/"
470474
);
471475
let config = CondaDenyConfig::from_path(&test_file_path).expect("Failed to read config");
472-
let license_infos = LicenseInfos::get_license_infos_from_config(&config, &[], &[], &[]);
476+
let license_infos = LicenseInfos::get_license_infos_from_config(&config, &[], &[], &[], false);
473477
assert_eq!(license_infos.unwrap().license_infos.len(), 396);
474478
}
475479
}

src/main.rs

+8
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,12 @@ fn main() -> Result<()> {
1818
_ => false,
1919
};
2020

21+
// todo: add an end-to-end test for this
22+
let ignore_pypi = match cli.command {
23+
Commands::Check { ignore_pypi, .. } => ignore_pypi,
24+
_ => false,
25+
};
26+
2127
let mut config = CondaDenyConfig::empty();
2228

2329
if !osi {
@@ -59,6 +65,7 @@ fn main() -> Result<()> {
5965
&cli_environments,
6066
&conda_prefixes,
6167
osi,
68+
ignore_pypi,
6269
);
6370

6471
debug!("CLI input for platforms: {:?}", cli_platforms);
@@ -73,6 +80,7 @@ fn main() -> Result<()> {
7380
Commands::Check {
7481
include_safe,
7582
osi: _,
83+
ignore_pypi: _
7684
} => {
7785
debug!("Check command called.");
7886

src/pixi_lock.rs

+33-11
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,9 @@ use std::path::Path;
22

33
use anyhow::{Context, Result};
44

5+
use log::warn;
56
use rattler_conda_types::{PackageRecord, Platform};
6-
use rattler_lock::LockFile;
7+
use rattler_lock::{LockFile, LockedPackageRef};
78

89
fn _get_environment_names(pixi_lock_path: &Path) -> Vec<String> {
910
let lock = LockFile::from_path(pixi_lock_path).unwrap();
@@ -14,10 +15,11 @@ fn _get_environment_names(pixi_lock_path: &Path) -> Vec<String> {
1415
environment_names
1516
}
1617

17-
pub fn get_package_records_for_pixi_lock(
18+
pub fn get_conda_packages_for_pixi_lock(
1819
pixi_lock_path: Option<&Path>,
1920
mut environment_spec: Vec<String>,
2021
platform_spec: Vec<String>,
22+
ignore_pypi: bool,
2123
) -> Result<Vec<PackageRecord>> {
2224
let pixi_lock_path = pixi_lock_path.unwrap_or(Path::new("pixi.lock"));
2325

@@ -30,15 +32,25 @@ pub fn get_package_records_for_pixi_lock(
3032

3133
let mut package_records = Vec::new();
3234

35+
// todo: refactor this
3336
if platform_spec.is_empty() {
3437
for environment_name in environment_spec {
3538
if let Some(environment) = lock.environment(&environment_name) {
3639
for platform in environment.platforms() {
3740
if let Some(packages) = environment.packages(platform) {
3841
for package in packages {
39-
if let Some(conda_package) = package.into_conda() {
40-
let package_record = conda_package.package_record();
41-
package_records.push(package_record.to_owned());
42+
match package {
43+
LockedPackageRef::Conda(conda_package) => {
44+
let package_record = conda_package.record();
45+
package_records.push(package_record.to_owned());
46+
}
47+
LockedPackageRef::Pypi(package_data, _) => {
48+
if !ignore_pypi {
49+
return Err(anyhow::anyhow!("Pypi packages are not supported: {}", package_data.name));
50+
} else {
51+
warn!("Ignoring pypi package: {}", package_data.name);
52+
}
53+
}
4254
}
4355
}
4456
}
@@ -52,9 +64,18 @@ pub fn get_package_records_for_pixi_lock(
5264
if let Some(environment) = lock.environment(&environment_name) {
5365
if let Some(packages) = environment.packages(platform) {
5466
for package in packages {
55-
if let Some(conda_package) = package.into_conda() {
56-
let package_record = conda_package.package_record();
57-
package_records.push(package_record.to_owned());
67+
match package {
68+
LockedPackageRef::Conda(conda_package) => {
69+
let package_record = conda_package.record();
70+
package_records.push(package_record.to_owned());
71+
}
72+
LockedPackageRef::Pypi(package_data, _) => {
73+
if !ignore_pypi {
74+
return Err(anyhow::anyhow!("Pypi packages are not supported: {}", package_data.name));
75+
} else {
76+
warn!("Ignoring pypi package: {}", package_data.name);
77+
}
78+
}
5879
}
5980
}
6081
}
@@ -83,17 +104,18 @@ mod tests {
83104
#[test]
84105
fn test_get_packages_for_pixi_lock() {
85106
let path = Path::new("tests/test_pixi_lock_files/valid1_pixi.lock");
86-
let package_records = get_package_records_for_pixi_lock(Some(path), vec![], vec![]);
107+
let package_records = get_conda_packages_for_pixi_lock(Some(path), vec![], vec![], false);
87108
assert_eq!(package_records.unwrap().len(), 758);
88109

89110
let package_records =
90-
get_package_records_for_pixi_lock(Some(path), vec!["lint".to_string()], vec![]);
111+
get_conda_packages_for_pixi_lock(Some(path), vec!["lint".to_string()], vec![], false);
91112
assert_eq!(package_records.unwrap().len(), 219);
92113

93-
let package_records = get_package_records_for_pixi_lock(
114+
let package_records = get_conda_packages_for_pixi_lock(
94115
Some(path),
95116
vec!["lint".to_string()],
96117
vec!["linux-64".to_string()],
118+
false,
97119
);
98120
assert_eq!(package_records.unwrap().len(), 48);
99121
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
[tool.conda-deny]
2+
safe-licenses = [
3+
"Apache-2.0",
4+
"Unlicense",
5+
"WTFPL",
6+
"MIT",
7+
]
8+
ignore-packages = [
9+
{package="_libgcc_mutex"}
10+
]

0 commit comments

Comments
 (0)