Skip to content

Commit

Permalink
Fallback to toolchain for dev commands
Browse files Browse the repository at this point in the history
  • Loading branch information
cnpryer committed Nov 30, 2023
1 parent f7c4c64 commit 30f49c6
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 99 deletions.
73 changes: 27 additions & 46 deletions crates/huak-package-manager/src/ops/format.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::{Config, Dependency, HuakResult, InstallOptions};
use crate::{Config, Dependency, Error, HuakResult, InstallOptions, PythonEnvironment};
use std::{process::Command, str::FromStr};

use super::add_venv_to_command;
Expand All @@ -9,56 +9,37 @@ pub struct FormatOptions {
pub install_options: InstallOptions,
}

/// Format the current project with ruff.
///
/// If the current environment already has ruff installed we'll use that.
/// If ruff isn't found in the current project's environment we try to use
/// ruff from an intalled toolchain. If a toolchain isn't keyed for the project

Check warning on line 16 in crates/huak-package-manager/src/ops/format.rs

View workflow job for this annotation

GitHub Actions / Spell check

"intalled" should be "installed".
/// we key the current project with the latest toolchain.
pub fn format_project(config: &Config, options: &FormatOptions) -> HuakResult<()> {
let workspace = config.workspace();
let mut manifest = workspace.current_local_manifest()?;
let python_env = workspace.resolve_python_environment()?;

// Install `ruff` it isn't already installed.
let format_deps = [Dependency::from_str("ruff")?];

let new_format_deps = format_deps
.iter()
.filter(|dep| !python_env.contains_module(dep.name()).unwrap_or_default())
.collect::<Vec<_>>();

if !new_format_deps.is_empty() {
python_env.install_packages(&new_format_deps, &options.install_options, config)?;
}

// Add the installed `ruff` package to the manifest file if not already there.
let new_format_deps = format_deps
.iter()
.filter(|dep| {
!manifest
.manifest_data()
.contains_project_dependency_any(dep.name())
})
.map(Dependency::name)
.collect::<Vec<_>>();

if !new_format_deps.is_empty() {
for pkg in python_env
.installed_packages()?
.iter()
.filter(|pkg| new_format_deps.contains(&pkg.name()))
{
manifest
.manifest_data_mut()
.add_project_optional_dependency(&pkg.to_string(), "dev");
let ws = config.workspace();
// TODO(cnpryer): We can technically do this without a current Python environment if we use toolchains.
let py_env = match ws.current_python_environment() {
Ok(it) if it.contains_module("ruff")? => it,
_ => {
match ws.resolve_local_toolchain(None) {
Ok(it) => PythonEnvironment::new(it.root().join(".venv"))?,
Err(Error::ToolchainNotFound) => {
// Create a toolchain and return the Python environment it uses (with ruff installed)
todo!()
}
Err(e) => return Err(e),
}
}
}

manifest.write_file()?;
};

// Run `ruff` for formatting imports and the rest of the Python code in the workspace.
// NOTE: This needs to be refactored https://github.com/cnpryer/huak/issues/784, https://github.com/cnpryer/huak/issues/718
let mut terminal = config.terminal();
let mut cmd = Command::new(python_env.python_path());
let mut ruff_cmd = Command::new(python_env.python_path());
let mut cmd = Command::new(py_env.python_path());
let mut ruff_cmd = Command::new(py_env.python_path());
let mut ruff_args = vec!["-m", "ruff", "check", ".", "--select", "I", "--fix"];
add_venv_to_command(&mut cmd, &python_env)?;
add_venv_to_command(&mut ruff_cmd, &python_env)?;
add_venv_to_command(&mut cmd, &py_env)?;
add_venv_to_command(&mut ruff_cmd, &py_env)?;
let mut args = vec!["-m", "ruff", "format", "."];
if let Some(v) = options.values.as_ref() {
args.extend(v.iter().map(String::as_str));
Expand All @@ -69,9 +50,9 @@ pub fn format_project(config: &Config, options: &FormatOptions) -> HuakResult<()
ruff_args.retain(|item| *item != "--fix");
}
}
ruff_cmd.args(ruff_args).current_dir(workspace.root());
ruff_cmd.args(ruff_args).current_dir(ws.root());
terminal.run_command(&mut ruff_cmd)?;
cmd.args(args).current_dir(workspace.root());
cmd.args(args).current_dir(ws.root());
terminal.run_command(&mut cmd)
}

Expand Down
74 changes: 25 additions & 49 deletions crates/huak-package-manager/src/ops/lint.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use super::add_venv_to_command;
use crate::{Config, Dependency, HuakResult, InstallOptions};
use crate::{Config, Dependency, Error, HuakResult, InstallOptions, PythonEnvironment};
use std::{process::Command, str::FromStr};

pub struct LintOptions {
Expand All @@ -10,74 +10,50 @@ pub struct LintOptions {
}

pub fn lint_project(config: &Config, options: &LintOptions) -> HuakResult<()> {
let workspace = config.workspace();
let mut manifest = workspace.current_local_manifest()?;
let python_env = workspace.resolve_python_environment()?;

// Install `ruff` if it isn't already installed.
let ruff_dep = Dependency::from_str("ruff")?;
let mut lint_deps = vec![ruff_dep.clone()];
if !python_env.contains_module("ruff")? {
python_env.install_packages(&[&ruff_dep], &options.install_options, config)?;
}
let ws = config.workspace();
// TODO(cnpryer): We can technically do this without a current Python environment if we use toolchains.
let py_env = match ws.current_python_environment() {
Ok(it) if it.contains_module("ruff")? => it,
_ => {
match ws.resolve_local_toolchain(None) {
Ok(it) => PythonEnvironment::new(it.root().join(".venv"))?,
Err(Error::ToolchainNotFound) => {
// Create a toolchain and return the Python environment it uses (with ruff installed)
todo!()
}
Err(e) => return Err(e),
}
}
};

let mut terminal = config.terminal();

if options.include_types {
// Install `mypy` if it isn't already installed.
let mypy_dep = Dependency::from_str("mypy")?;
if !python_env.contains_module("mypy")? {
python_env.install_packages(&[&mypy_dep], &options.install_options, config)?;
if !py_env.contains_module("mypy")? {
py_env.install_packages(&[&mypy_dep], &options.install_options, config)?;
}

// Keep track of the fact that `mypy` is a needed lint dep.
lint_deps.push(mypy_dep);

// Run `mypy` excluding the workspace's Python environment directory.
let mut mypy_cmd = Command::new(python_env.python_path());
add_venv_to_command(&mut mypy_cmd, &python_env)?;
let mut mypy_cmd = Command::new(py_env.python_path());
add_venv_to_command(&mut mypy_cmd, &py_env)?;
mypy_cmd
.args(vec!["-m", "mypy", ".", "--exclude", &python_env.name()?])
.current_dir(workspace.root());
.args(vec!["-m", "mypy", ".", "--exclude", &py_env.name()?])
.current_dir(ws.root());
terminal.run_command(&mut mypy_cmd)?;
}

// Run `ruff`.
let mut cmd = Command::new(python_env.python_path());
let mut cmd = Command::new(py_env.python_path());
let mut args = vec!["-m", "ruff", "check", "."];
if let Some(v) = options.values.as_ref() {
args.extend(v.iter().map(String::as_str));
}
add_venv_to_command(&mut cmd, &python_env)?;
cmd.args(args).current_dir(workspace.root());
add_venv_to_command(&mut cmd, &py_env)?;
cmd.args(args).current_dir(ws.root());
terminal.run_command(&mut cmd)?;

// Add installed lint deps (potentially both `mypy` and `ruff`) to manifest file if not already there.
let new_lint_deps = lint_deps
.iter()
.filter(|dep| {
!manifest
.manifest_data()
.contains_project_dependency_any(dep.name())
})
.map(Dependency::name)
.collect::<Vec<_>>();

if !new_lint_deps.is_empty() {
for pkg in python_env
.installed_packages()?
.iter()
.filter(|pkg| new_lint_deps.contains(&pkg.name()))
{
manifest
.manifest_data_mut()
.add_project_optional_dependency(&pkg.to_string(), "dev");
}
}

manifest.manifest_data_mut().formatted();
manifest.write_file()?;

Ok(())
}

Expand Down
5 changes: 1 addition & 4 deletions crates/huak-package-manager/src/workspace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,10 +93,7 @@ impl Workspace {
/// Get the current `PythonEnvironment`. The current `PythonEnvironment` is one
/// found by its configuration file or `Interpreter` nearest baseed on `Config` data.
pub fn current_python_environment(&self) -> HuakResult<PythonEnvironment> {
let toolchain = self.resolve_local_toolchain(None);
let path = toolchain
.map(|it| it.root().join(".venv"))
.or(find_venv_root(&self.config.cwd, &self.root))?;
let path = find_venv_root(&self.config.cwd, &self.root)?;
let py_env = PythonEnvironment::new(path)?;

Ok(py_env)
Expand Down

0 comments on commit 30f49c6

Please sign in to comment.