Skip to content

Conversation

@maxmynter
Copy link
Contributor

Closes #16903

Summary

Check if the current working directory exist. If not, provide an error instead of panicking.

Fixed a stale comment in resolve_default_files.

Test Plan

I added a test to the resolve_files.rs.

Manual testing follows steps of #16903 :

  • Terminal 1
mkdir tmp
cd tmp
  • Terminal 2
rm -rf tmp
  • Terminal 1
ruff check

Open Issues / Questions to Reviewer

All tests pass when executed with cargo nextest run.

However, with cargo test the parallelization makes the other tests fail as we change the pwd.

Serial execution with cargo test seems to require another dependency or some workarounds.

Do you think an additional dependency or test complexity is worth testing this small edge case, do you have another implementation idea, or should i rather remove the test?


P.S.: I'm currently participating in a batch at the Recurse Center and would love to contribute more for the next six weeks to improve my Rust. Let me know if you're open to mentoring/reviewing and/or if you have specific areas where help would be most valued.

to reflect function behavior.
otherwise ruff panics if the working directory does not exist.
This test works when executed with nexttest but has interactions with
other `resolve_files` tests when
executed.
@ntBre ntBre added the bug Something isn't working label Mar 29, 2025
Copy link
Contributor

@ntBre ntBre left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for working on this! I took a look at this earlier in the week, and I was wondering how to go about testing it too.

I think if you move the new integration test to its own file, it will be built and run separately by cargo test and avoid the parallelization issues you ran into. Then you can also skip saving the original_dir and restoring it since the test should be run on its own.

Alternatively, we could possibly skip testing this to avoid changing the cwd at all, which feels a little scary. What do you think @MichaReiser?

) -> Result<PyprojectConfig> {
// Ensure directory exists before proceeding
if std::env::current_dir().is_err() {
return Err(anyhow!("Working directory does not exist"));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we could use bail! here instead of Err(anyhow!(...)).

I also think we might as well do something like this:

let Ok(cwd) = std::env::current_dir() else {
    bail!("Working directory does not exist");
};

instead of using path_dedot::CWD below, which is just a LazyLock around std::env::current_dir. That makes it a bit more clear what this check is for, I think.

We may also want to move this check into the if config_arguments.isolated check if that's the only place CWD is used.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree on your proposal for rewriting. It makes the intentions of the check clear and we can get rid of the comment.

path_dedot::CWD is used a couple of times throughout the function so I will keep it outside of the if clause.

let temp_path = temp_dir.path().to_path_buf();
let original_dir = std::env::current_dir().unwrap();
std::env::set_current_dir(&temp_path).unwrap();
std::mem::drop(temp_dir);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: I would just use drop directly without qualifying it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree that it reads nicer.
I will also just import from std::env so we can use directory operations without qualifiers.

Comment on lines 113 to 115
insta::with_settings!({
filters => TEST_FILTERS.to_vec()
},
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think you actually need these filters and could leave them out. Paths only cause problems when they appear in the snapshot output.

@github-actions
Copy link
Contributor

github-actions bot commented Mar 29, 2025

ruff-ecosystem results

Linter (stable)

✅ ecosystem check detected no linter changes.

Linter (preview)

✅ ecosystem check detected no linter changes.

to have the test binary is built and run seperately.

This is necessary as changing the working directory
within the tests likely breaks other tests executed
in parallel by changing the working directory.

Also trim down the test logic a bit. "--no-cache" is
redundant.

Use imports instead of qualifiers for readability.
This is already achieved by having the test in a dedicated file.
Use bail! and let else since it communicates the
intent more clearly.
@maxmynter
Copy link
Contributor Author

Having the test in a dedicated file now works for both cargo test and cargo nextest.

@maxmynter maxmynter requested a review from ntBre March 30, 2025 03:03
config_arguments: &ConfigArguments,
stdin_filename: Option<&Path>,
) -> Result<PyprojectConfig> {
let Ok(_cwd) = std::env::current_dir() else {
Copy link
Member

@MichaReiser MichaReiser Mar 30, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It feels off that the path isn't used here. I think we should change the code to call cwd.parse_dot() and use it instead of &path_dedot::CWD below

Edit: This is the same as what @ntBre was proposing

set_current_dir(&temp_path).unwrap();
drop(temp_dir);

assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME)).arg("check"), @r###"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree with @ntBre that changing the working directory is problematic. Let's only override the current working directory for the spanned CLI command.

Suggested change
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME)).arg("check"), @r###"
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME)).arg("check").current_dir(&temp_path), @r###"

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I tried current_dir when I looked at this, and it caused a different panic in the Command invocation, separate from the one we're trying to test. But it would be good to double check, and maybe I missed something.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, the assert_cmd_snapshot or current_dir calls an unwrap() somewhere. The test fails with:

[...] called `Result::unwrap()` on an `Err` value: Os { code: 2, kind: NotFound, message: "No such file or directory"

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm I see. Let's add some module level documentation (or at least test level) explaining why this test has to be its own module.

Instead of path_dedot::CWD where appropriate
.unwrap_or(&path_dedot::CWD.as_path()),
)? {
if let Some(pyproject) =
pyproject::find_settings_toml(stdin_filename.as_ref().unwrap_or(&cwd.as_path()))?
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it intentional that you're only using parse_dot in some paths?

I think I'd change the method to

    let Ok(cwd) = std::env::current_dir() else {
        bail!("Working directory does not exist")
    };
		let cwd = cwd.parse_dot()?;

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It was born out of me wrestling with the typechecker, using the previous implementation as reference.
I agree that a more consistent, less verbose usage is preferable.

Is the change in 27a8964 what you had in mind? I'm a bit out of my depth with Cow and the path handling.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That looks right to me. I think we could skip calling parse_dot at all since path_dedot::CWD doesn't:

https://github.com/magiclen/path-dedot/blob/36c197f922d4c8779594ce25b8ffc6cb0315c6a8/src/lib.rs#L329-L330

but I think Micha's point was that we should be consistent one way or the other.

Copy link
Contributor Author

@maxmynter maxmynter Apr 1, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Interesting. I used it because the first line on the path_dedot crate docs say it's purpose is to handle filepaths that contain dots.

But if we only use(d) it as a global variable to access the cwd, I think we can drop it.

Addressed in 98c7711

@maxmynter maxmynter requested a review from MichaReiser March 31, 2025 20:16
Copy link
Contributor

@ntBre ntBre left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for following up on this, it's looking good. Just one more nit to avoid as_ref calls and an idea for fixing Windows CI.

I'll defer to Micha for the final approval, but this looks good to me once CI passes.

.unwrap_or(&path_dedot::CWD.as_path()),
)? {
if let Some(pyproject) =
pyproject::find_settings_toml(stdin_filename.as_ref().unwrap_or(&cwd.as_ref()))?
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: You do need as_ref currently, but stdin_filename is already an Option<&Path>, so you can actually simplify both of these cases (here and below on line 137) to this:

Suggested change
pyproject::find_settings_toml(stdin_filename.as_ref().unwrap_or(&cwd.as_ref()))?
pyproject::find_settings_toml(stdin_filename.unwrap_or(&cwd))?

//! Tests in the same module become flaky under `cargo test`s parallel execution
//! due to in-test working directory manipulation.
#![cfg(not(target_family = "wasm"))]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the Windows CI failure is real. I think Windows will keep the directory around as long as a process is using it. Maybe we need to exclude both wasm and windows targets? I always forget the syntax for this, but I think it's something like this:

Suggested change
#![cfg(not(target_family = "wasm"))]
#![cfg(not(any(target_family = "wasm", target_family = "windows")))]

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll leave the Windows CI failures to you, if that's fine... I don't have access to a Windows machine.

@MichaReiser MichaReiser enabled auto-merge (squash) April 1, 2025 07:12
@MichaReiser MichaReiser added the cli Related to the command-line interface label Apr 1, 2025
@MichaReiser MichaReiser merged commit d0c8eaa into astral-sh:main Apr 1, 2025
22 checks passed
dcreager added a commit that referenced this pull request Apr 1, 2025
* main:
  [red-knot] Add property tests for callable types (#17006)
  [red-knot] Disjointness for callable types (#17094)
  [red-knot] Flatten `Type::Callable` into four `Type` variants (#17126)
  mdtest.py: do a full mdtest run immediately when the script is executed (#17128)
  [red-knot] Fix callable subtyping for standard parameters (#17125)
  [red-knot] Fix more `redundant-cast` false positives (#17119)
  Sync vendored typeshed stubs (#17106)
  [red-knot] support Any as a class in typeshed (#17107)
  Visit `Identifier` node as part of the `SourceOrderVisitor` (#17110)
  [red-knot] Don't infer Todo for quite so many tuple type expressions (#17116)
  CI: Run pre-commit on depot machine (#17120)
  Error instead of `panic!` when running Ruff from a deleted directory (#16903) (#17054)
  Control flow graph: setup (#17064)
  [red-knot] Playground improvements (#17109)
  [red-knot] IDE crate (#17045)
  Update dependency vite to v6.2.4 (#17104)
  [red-knot] Add redundant-cast error (#17100)
  [red-knot] Narrowing on `in tuple[...]` and `in str` (#17059)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working cli Related to the command-line interface

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Panic] ruff crashes when executed from a deleted folder on mac

3 participants