Skip to content

Commit 3f38d20

Browse files
committed
Merge branch 'dcreager/dont-have-a-cow' into dcreager/alist-for-live-bds
* dcreager/dont-have-a-cow: [red-knot] unify LoopState and saved_break_states (#16406) [`pylint`] Also reports `case np.nan`/`case math.nan` (`PLW0177`) (#16378) [FURB156] Do not consider docstring(s) (#16391) Use `is_none_or` in `stdlib-module-shadowing` (#16402) [red-knot] Upgrade salsa to include `AtomicPtr` perf improvement (#16398) [red-knot] Fix file watching for new non-project files (#16395) document MSRV policy (#16384) [red-knot] fix non-callable reporting for unions (#16387) bump MSRV to 1.83 (#16294) Avoid unnecessary info at non-trace server log level (#16389) Expand `ruff.configuration` to allow inline config (#16296) Start detecting version-related syntax errors in the parser (#16090)
2 parents d26b0fd + 35c413b commit 3f38d20

File tree

84 files changed

+1035
-247
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

84 files changed

+1035
-247
lines changed

Cargo.lock

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

Cargo.toml

+2-2
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ resolver = "2"
44

55
[workspace.package]
66
edition = "2021"
7-
rust-version = "1.80"
7+
rust-version = "1.83"
88
homepage = "https://docs.astral.sh/ruff"
99
documentation = "https://docs.astral.sh/ruff"
1010
repository = "https://github.com/astral-sh/ruff"
@@ -125,7 +125,7 @@ rayon = { version = "1.10.0" }
125125
regex = { version = "1.10.2" }
126126
rustc-hash = { version = "2.0.0" }
127127
# When updating salsa, make sure to also update the revision in `fuzz/Cargo.toml`
128-
salsa = { git = "https://github.com/salsa-rs/salsa.git", rev = "687251fb50b4893dc373a7e2609ceaefb8accbe7" }
128+
salsa = { git = "https://github.com/salsa-rs/salsa.git", rev = "99be5d9917c3dd88e19735a82ef6bf39ba84bd7e" }
129129
schemars = { version = "0.8.16" }
130130
seahash = { version = "4.1.0" }
131131
serde = { version = "1.0.197", features = ["derive"] }

crates/red_knot/tests/file_watching.rs

+43
Original file line numberDiff line numberDiff line change
@@ -462,6 +462,41 @@ fn new_ignored_file() -> anyhow::Result<()> {
462462
Ok(())
463463
}
464464

465+
#[test]
466+
fn new_non_project_file() -> anyhow::Result<()> {
467+
let mut case = setup_with_options([("bar.py", "")], |context| {
468+
Some(Options {
469+
environment: Some(EnvironmentOptions {
470+
extra_paths: Some(vec![RelativePathBuf::cli(
471+
context.join_root_path("site_packages"),
472+
)]),
473+
..EnvironmentOptions::default()
474+
}),
475+
..Options::default()
476+
})
477+
})?;
478+
479+
let bar_path = case.project_path("bar.py");
480+
let bar_file = case.system_file(&bar_path).unwrap();
481+
482+
assert_eq!(&case.collect_project_files(), &[bar_file]);
483+
484+
// Add a file to site packages
485+
let black_path = case.root_path().join("site_packages/black.py");
486+
std::fs::write(black_path.as_std_path(), "print('Hello')")?;
487+
488+
let changes = case.stop_watch(event_for_file("black.py"));
489+
490+
case.apply_changes(changes);
491+
492+
assert!(case.system_file(&black_path).is_ok());
493+
494+
// The file should not have been added to the project files
495+
assert_eq!(&case.collect_project_files(), &[bar_file]);
496+
497+
Ok(())
498+
}
499+
465500
#[test]
466501
fn changed_file() -> anyhow::Result<()> {
467502
let foo_source = "print('Hello, world!')";
@@ -1075,6 +1110,7 @@ fn hard_links_in_project() -> anyhow::Result<()> {
10751110

10761111
assert_eq!(source_text(case.db(), foo).as_str(), "print('Version 1')");
10771112
assert_eq!(source_text(case.db(), bar).as_str(), "print('Version 1')");
1113+
assert_eq!(case.collect_project_files(), &[bar, foo]);
10781114

10791115
// Write to the hard link target.
10801116
update_file(foo_path, "print('Version 2')").context("Failed to update foo.py")?;
@@ -1354,6 +1390,8 @@ mod unix {
13541390
);
13551391
assert_eq!(baz.file().path(case.db()).as_system_path(), Some(&*bar_baz));
13561392

1393+
assert_eq!(case.collect_project_files(), &[patched_bar_baz_file]);
1394+
13571395
// Write to the symlink target.
13581396
update_file(&patched_bar_baz, "def baz(): print('Version 2')")
13591397
.context("Failed to update bar/baz.py")?;
@@ -1389,6 +1427,7 @@ mod unix {
13891427
bar_baz_text = bar_baz_text.as_str()
13901428
);
13911429

1430+
assert_eq!(case.collect_project_files(), &[patched_bar_baz_file]);
13921431
Ok(())
13931432
}
13941433

@@ -1469,6 +1508,8 @@ mod unix {
14691508
Some(&*baz_original)
14701509
);
14711510

1511+
assert_eq!(case.collect_project_files(), &[]);
1512+
14721513
// Write to the symlink target.
14731514
update_file(&baz_original, "def baz(): print('Version 2')")
14741515
.context("Failed to update bar/baz.py")?;
@@ -1494,6 +1535,8 @@ mod unix {
14941535
"def baz(): print('Version 2')"
14951536
);
14961537

1538+
assert_eq!(case.collect_project_files(), &[]);
1539+
14971540
Ok(())
14981541
}
14991542
}

crates/red_knot_project/src/db/changes.rs

+6-5
Original file line numberDiff line numberDiff line change
@@ -208,11 +208,12 @@ impl ProjectDatabase {
208208
return WalkState::Continue;
209209
}
210210

211-
if entry
212-
.path()
213-
.extension()
214-
.and_then(PySourceType::try_from_extension)
215-
.is_some()
211+
if entry.path().starts_with(&project_path)
212+
&& entry
213+
.path()
214+
.extension()
215+
.and_then(PySourceType::try_from_extension)
216+
.is_some()
216217
{
217218
let mut paths = added_paths.lock().unwrap();
218219

crates/red_knot_project/src/metadata.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -77,10 +77,10 @@ impl ProjectMetadata {
7777
// If the `options` don't specify a python version but the `project.requires-python` field is set,
7878
// use that as a lower bound instead.
7979
if let Some(project) = project {
80-
if !options
80+
if options
8181
.environment
8282
.as_ref()
83-
.is_some_and(|env| env.python_version.is_some())
83+
.is_none_or(|env| env.python_version.is_none())
8484
{
8585
if let Some(requires_python) = project.resolve_requires_python_lower_bound()? {
8686
let mut environment = options.environment.unwrap_or_default();

crates/red_knot_python_semantic/resources/mdtest/call/union.md

+36
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ def _(flag: bool, flag2: bool):
5656
else:
5757
def f() -> int:
5858
return 1
59+
# TODO we should mention all non-callable elements of the union
5960
# error: [call-non-callable] "Object of type `Literal[1]` is not callable"
6061
# revealed: int | Unknown
6162
reveal_type(f())
@@ -108,3 +109,38 @@ def _(flag: bool):
108109
x = f(3)
109110
reveal_type(x) # revealed: Unknown
110111
```
112+
113+
## Union of binding errors
114+
115+
```py
116+
def f1(): ...
117+
def f2(): ...
118+
def _(flag: bool):
119+
if flag:
120+
f = f1
121+
else:
122+
f = f2
123+
124+
# TODO: we should show all errors from the union, not arbitrarily pick one union element
125+
# error: [too-many-positional-arguments] "Too many positional arguments to function `f1`: expected 0, got 1"
126+
x = f(3)
127+
reveal_type(x) # revealed: Unknown
128+
```
129+
130+
## One not-callable, one wrong argument
131+
132+
```py
133+
class C: ...
134+
135+
def f1(): ...
136+
def _(flag: bool):
137+
if flag:
138+
f = f1
139+
else:
140+
f = C()
141+
142+
# TODO: we should either show all union errors here, or prioritize the not-callable error
143+
# error: [too-many-positional-arguments] "Too many positional arguments to function `f1`: expected 0, got 1"
144+
x = f(3)
145+
reveal_type(x) # revealed: Unknown
146+
```

0 commit comments

Comments
 (0)