-
Notifications
You must be signed in to change notification settings - Fork 373
feat(init): support --import with --format pyproject
#4134
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -12,3 +12,5 @@ pytest-temp | |
| /vendor | ||
| *.conda | ||
| *.local.* | ||
| .history | ||
| /__* | ||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -61,7 +61,7 @@ pub struct Args { | |||||
| pub env_file: Option<PathBuf>, | ||||||
|
|
||||||
| /// The manifest format to create. | ||||||
| #[arg(long, conflicts_with_all = ["ENVIRONMENT_FILE", "pyproject_toml"], ignore_case = true)] | ||||||
| #[arg(long, conflicts_with_all = ["pyproject_toml"], ignore_case = true)] | ||||||
| pub format: Option<ManifestFormat>, | ||||||
|
|
||||||
| /// Create a pyproject.toml manifest instead of a pixi.toml manifest | ||||||
|
|
@@ -301,15 +301,37 @@ pub async fn execute(args: Args) -> miette::Result<()> { | |||||
| args.platforms.clone() | ||||||
| }; | ||||||
|
|
||||||
| // Dialog with user to create a 'pyproject.toml' or 'pixi.toml' manifest | ||||||
| // If nothing is defined but there is a `pyproject.toml` file, ask the user. | ||||||
| let pyproject = if !pixi_manifest_path.is_file() | ||||||
| && args.format.is_none() | ||||||
| && !args.pyproject_toml | ||||||
| && pyproject_manifest_path.is_file() | ||||||
| { | ||||||
| eprintln!( | ||||||
| "\nA '{}' file already exists.\n", | ||||||
| console::style(consts::PYPROJECT_MANIFEST).bold() | ||||||
| ); | ||||||
|
|
||||||
| dialoguer::Confirm::new() | ||||||
| .with_prompt(format!( | ||||||
| "Do you want to extend it with the '{}' configuration?", | ||||||
| console::style("[tool.pixi]").bold().green() | ||||||
| )) | ||||||
| .default(false) | ||||||
| .show_default(true) | ||||||
| .interact() | ||||||
| .into_diagnostic()? | ||||||
| } else { | ||||||
| args.format == Some(ManifestFormat::Pyproject) || args.pyproject_toml | ||||||
| }; | ||||||
|
|
||||||
| let index_url = &(config.pypi_config.index_url); | ||||||
| let extra_index_urls = &(config.pypi_config.extra_index_urls); | ||||||
|
|
||||||
| // Create a 'pixi.toml' manifest and populate it by importing a conda | ||||||
| // environment file | ||||||
| if let Some(env_file_path) = args.env_file { | ||||||
| // Check if the 'pixi.toml' file doesn't already exist. We don't want to | ||||||
| // overwrite it. | ||||||
| if pixi_manifest_path.is_file() { | ||||||
| miette::bail!("{} already exists", consts::WORKSPACE_MANIFEST); | ||||||
| } | ||||||
|
|
||||||
| let env_file = CondaEnvFile::from_path(&env_file_path)?; | ||||||
| let name = env_file | ||||||
| .name() | ||||||
|
|
@@ -320,68 +342,97 @@ pub async fn execute(args: Args) -> miette::Result<()> { | |||||
| // TODO: Improve this: | ||||||
| // - Use .condarc as channel config | ||||||
| let (conda_deps, pypi_deps, channels) = env_file.to_manifest(&config)?; | ||||||
| let rendered_workspace_template = render_workspace( | ||||||
| &env, | ||||||
| name, | ||||||
| version, | ||||||
| author.as_ref(), | ||||||
| channels, | ||||||
| &platforms, | ||||||
| None, | ||||||
| &vec![], | ||||||
| config.s3_options, | ||||||
| Some(&env_vars), | ||||||
| ); | ||||||
| let mut workspace = | ||||||
| WorkspaceMut::from_template(pixi_manifest_path, rendered_workspace_template)?; | ||||||
| workspace.add_specs( | ||||||
| conda_deps, | ||||||
| pypi_deps, | ||||||
| &[] as &[Platform], | ||||||
| &FeatureName::default(), | ||||||
| )?; | ||||||
| let workspace = workspace.save().await.into_diagnostic()?; | ||||||
|
|
||||||
| eprintln!( | ||||||
| "{}Created {}", | ||||||
| console::style(console::Emoji("✔ ", "")).green(), | ||||||
| // Canonicalize the path to make it more readable, but if it fails just use the path as | ||||||
| // is. | ||||||
| workspace.workspace.provenance.path.display() | ||||||
| ); | ||||||
| } else { | ||||||
| let channels = if let Some(channels) = args.channels { | ||||||
| channels | ||||||
| if pyproject { | ||||||
| // Python package names cannot contain '-', so we replace them with '_' | ||||||
| let pypi_package_name = PackageName::from_str(&name) | ||||||
| .map(|name| name.as_dist_info_name().to_string()) | ||||||
| .unwrap_or_else(|_| name.clone()); | ||||||
|
|
||||||
| let rv = env | ||||||
| .render_named_str( | ||||||
| consts::PYPROJECT_MANIFEST, | ||||||
| NEW_PYROJECT_TEMPLATE, | ||||||
| context! { | ||||||
| name, | ||||||
| pypi_package_name, | ||||||
| version, | ||||||
| author, | ||||||
| channels, | ||||||
| platforms, | ||||||
| index_url => index_url.as_ref(), | ||||||
| extra_index_urls => &extra_index_urls, | ||||||
| s3 => relevant_s3_options(config.s3_options, channels), | ||||||
| }, | ||||||
| ) | ||||||
| .expect("should be able to render the template"); | ||||||
| save_manifest_file(&pyproject_manifest_path, rv)?; | ||||||
|
|
||||||
| let src_dir = dir.join("src").join(pypi_package_name); | ||||||
| tokio::fs::create_dir_all(&src_dir) | ||||||
| .await | ||||||
| .into_diagnostic() | ||||||
| .wrap_err_with(|| format!("Could not create directory {}.", src_dir.display()))?; | ||||||
|
|
||||||
| let init_file = src_dir.join("__init__.py"); | ||||||
| match OpenOptions::new() | ||||||
| .write(true) | ||||||
| .create_new(true) | ||||||
| .open(&init_file) | ||||||
| .await | ||||||
| { | ||||||
| Ok(_) => (), | ||||||
| Err(e) if e.kind() == ErrorKind::AlreadyExists => { | ||||||
| // If the file already exists, do nothing | ||||||
| } | ||||||
| Err(e) => { | ||||||
| return Err(e).into_diagnostic().wrap_err_with(|| { | ||||||
| format!("Could not create file {}.", init_file.display()) | ||||||
| }); | ||||||
| } | ||||||
| }; | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. have I missed something, or does the |
||||||
| } else { | ||||||
| config.default_channels().to_vec() | ||||||
| }; | ||||||
| // Check if the 'pixi.toml' file doesn't already exist. We don't want to | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
| // overwrite it. | ||||||
| if pixi_manifest_path.is_file() { | ||||||
| miette::bail!("{} already exists", consts::WORKSPACE_MANIFEST); | ||||||
| } | ||||||
|
|
||||||
| let index_url = config.pypi_config.index_url; | ||||||
| let extra_index_urls = config.pypi_config.extra_index_urls; | ||||||
| let rendered_workspace_template = render_workspace( | ||||||
| &env, | ||||||
| name, | ||||||
| version, | ||||||
| author.as_ref(), | ||||||
| channels, | ||||||
| &platforms, | ||||||
| None, | ||||||
| &vec![], | ||||||
| config.s3_options, | ||||||
| Some(&env_vars), | ||||||
| ); | ||||||
| let mut workspace = | ||||||
| WorkspaceMut::from_template(pixi_manifest_path, rendered_workspace_template)?; | ||||||
| workspace.add_specs( | ||||||
| conda_deps, | ||||||
| pypi_deps, | ||||||
| &[] as &[Platform], | ||||||
| &FeatureName::default(), | ||||||
| )?; | ||||||
| let workspace = workspace.save().await.into_diagnostic()?; | ||||||
|
|
||||||
| // Dialog with user to create a 'pyproject.toml' or 'pixi.toml' manifest | ||||||
| // If nothing is defined but there is a `pyproject.toml` file, ask the user. | ||||||
| let pyproject = if !pixi_manifest_path.is_file() | ||||||
| && args.format.is_none() | ||||||
| && !args.pyproject_toml | ||||||
| && pyproject_manifest_path.is_file() | ||||||
| { | ||||||
| eprintln!( | ||||||
| "\nA '{}' file already exists.\n", | ||||||
| console::style(consts::PYPROJECT_MANIFEST).bold() | ||||||
| "{}Created {}", | ||||||
| console::style(console::Emoji("✔ ", "")).green(), | ||||||
| // Canonicalize the path to make it more readable, but if it fails just use the path as | ||||||
| // is. | ||||||
| workspace.workspace.provenance.path.display() | ||||||
|
Comment on lines
423
to
+428
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think we want to include this in the |
||||||
| ); | ||||||
|
|
||||||
| dialoguer::Confirm::new() | ||||||
| .with_prompt(format!( | ||||||
| "Do you want to extend it with the '{}' configuration?", | ||||||
| console::style("[tool.pixi]").bold().green() | ||||||
| )) | ||||||
| .default(false) | ||||||
| .show_default(true) | ||||||
| .interact() | ||||||
| .into_diagnostic()? | ||||||
| } | ||||||
| } else { | ||||||
| let channels = if let Some(channels) = args.channels { | ||||||
| channels | ||||||
| } else { | ||||||
| args.format == Some(ManifestFormat::Pyproject) || args.pyproject_toml | ||||||
| config.default_channels().to_vec() | ||||||
| }; | ||||||
|
|
||||||
| // Inject a tool.pixi.workspace section into an existing pyproject.toml file if | ||||||
|
|
@@ -449,7 +500,7 @@ pub async fn execute(args: Args) -> miette::Result<()> { | |||||
| } | ||||||
| } | ||||||
|
|
||||||
| // Create a 'pyproject.toml' manifest | ||||||
| // Create a 'pyproject.toml' manifest | ||||||
| } else if pyproject { | ||||||
| // Python package names cannot contain '-', so we replace them with '_' | ||||||
| let pypi_package_name = PackageName::from_str(&default_name) | ||||||
|
|
@@ -521,7 +572,7 @@ pub async fn execute(args: Args) -> miette::Result<()> { | |||||
| channels, | ||||||
| &platforms, | ||||||
| index_url.as_ref(), | ||||||
| &extra_index_urls, | ||||||
| extra_index_urls, | ||||||
| config.s3_options, | ||||||
| None, | ||||||
| ); | ||||||
|
|
||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what does
rvstand for?