-
Notifications
You must be signed in to change notification settings - Fork 1
[run] feat: Add Rye support to Python detector #23
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
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 |
|---|---|---|
|
|
@@ -56,6 +56,18 @@ impl CommandValidator for PythonValidator { | |
| } | ||
| } | ||
|
|
||
| // Check [tool.rye.scripts] (Rye) | ||
| if let Some(scripts) = toml_value | ||
| .get("tool") | ||
| .and_then(|t| t.get("rye")) | ||
| .and_then(|p| p.get("scripts")) | ||
| .and_then(|s| s.as_table()) | ||
| { | ||
| if scripts.contains_key(command) { | ||
| return CommandSupport::Supported; | ||
| } | ||
| } | ||
|
|
||
| // Python is extensible - uv run / poetry run can also execute | ||
| // commands from the virtual environment (pytest, mypy, etc.) | ||
| // So we return Unknown to allow fallback behavior | ||
|
|
@@ -64,13 +76,35 @@ impl CommandValidator for PythonValidator { | |
| } | ||
|
|
||
| /// Detect Python package managers | ||
| /// Priority: UV (5) > Poetry (6) > Pipenv (7) > Pip (8) | ||
| /// Priority: UV (5) > Rye (5) > Poetry (6) > Pipenv (7) > Pip (8) | ||
| pub fn detect(dir: &Path) -> Vec<DetectedRunner> { | ||
| let mut runners = Vec::new(); | ||
|
|
||
| let has_pyproject = dir.join("pyproject.toml").exists(); | ||
| let pyproject_path = dir.join("pyproject.toml"); | ||
| let has_pyproject = pyproject_path.exists(); | ||
| let validator: Arc<dyn CommandValidator> = Arc::new(PythonValidator); | ||
|
|
||
| // Determine if it's a Rye project by inspecting pyproject.toml | ||
| let mut is_rye = false; | ||
| if has_pyproject { | ||
| if let Ok(content) = fs::read_to_string(&pyproject_path) { | ||
| if let Ok(toml_value) = toml::from_str::<toml::Value>(&content) { | ||
| is_rye = toml_value.get("tool").and_then(|t| t.get("rye")).is_some(); | ||
|
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.
Detecting Rye whenever any Useful? React with 👍 / 👎. |
||
| } | ||
| } | ||
| } | ||
|
|
||
| // Check for Rye (priority 5) | ||
| if is_rye { | ||
| runners.push(DetectedRunner::with_validator( | ||
| "rye", | ||
| "pyproject.toml", | ||
| Ecosystem::Python, | ||
| 5, | ||
| Arc::clone(&validator), | ||
| )); | ||
| } | ||
|
|
||
| // Check for UV (priority 5) | ||
| let uv_lock = dir.join("uv.lock"); | ||
| if uv_lock.exists() && has_pyproject { | ||
|
|
@@ -150,6 +184,27 @@ mod tests { | |
| assert_eq!(runners[0].name, "uv"); | ||
| } | ||
|
|
||
| #[test] | ||
| fn test_detect_rye() { | ||
| let dir = tempdir().unwrap(); | ||
| let mut file = File::create(dir.path().join("pyproject.toml")).unwrap(); | ||
| writeln!( | ||
| file, | ||
| r#" | ||
| [project] | ||
| name = "example" | ||
|
|
||
| [tool.rye] | ||
| managed = true | ||
| "# | ||
| ) | ||
| .unwrap(); | ||
|
|
||
| let runners = detect(dir.path()); | ||
| assert_eq!(runners.len(), 1); | ||
| assert_eq!(runners[0].name, "rye"); | ||
| } | ||
|
|
||
| #[test] | ||
| fn test_detect_poetry() { | ||
| let dir = tempdir().unwrap(); | ||
|
|
@@ -239,6 +294,38 @@ serve = "example.server:run" | |
| ); | ||
| } | ||
|
|
||
| #[test] | ||
| fn test_python_validator_rye_scripts() { | ||
| let dir = tempdir().unwrap(); | ||
| let mut file = File::create(dir.path().join("pyproject.toml")).unwrap(); | ||
| writeln!( | ||
| file, | ||
| r#" | ||
| [tool.rye] | ||
| managed = true | ||
|
|
||
| [tool.rye.scripts] | ||
| build = "python build.py" | ||
| dev = "python -m http.server" | ||
| "# | ||
| ) | ||
| .unwrap(); | ||
|
|
||
| let validator = PythonValidator; | ||
| assert_eq!( | ||
| validator.supports_command(dir.path(), "build"), | ||
| CommandSupport::Supported | ||
| ); | ||
| assert_eq!( | ||
| validator.supports_command(dir.path(), "dev"), | ||
| CommandSupport::Supported | ||
| ); | ||
| assert_eq!( | ||
| validator.supports_command(dir.path(), "unknown"), | ||
| CommandSupport::Unknown | ||
| ); | ||
| } | ||
|
|
||
| #[test] | ||
| fn test_python_validator_poetry_scripts() { | ||
| let dir = tempdir().unwrap(); | ||
|
|
||
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.
This validator is shared by all Python runners (
uv,poetry,pipenv,pip, andrye), so adding[tool.rye.scripts]as universallySupportedmakes non-Rye runners claim support for Rye-only task definitions.select_runnerprefers supported runners by priority, so a higher-priority non-Rye runner can be selected and then execute a command form it does not actually implement (e.g.,uv run <rye-script>), producing runtime failures.Useful? React with 👍 / 👎.