Skip to content

impl Detect editable installs and auto re-analyze on changes. #2207#2646

Open
asukaminato0721 wants to merge 1 commit intofacebook:mainfrom
asukaminato0721:2207-editable
Open

impl Detect editable installs and auto re-analyze on changes. #2207#2646
asukaminato0721 wants to merge 1 commit intofacebook:mainfrom
asukaminato0721:2207-editable

Conversation

@asukaminato0721
Copy link
Contributor

Summary

Fixes part of #2207

Added a shared editable-install detector (direct_url.json, .pth, .egg-link) with caching and tests, and wired LSP “source vs third-party” logic to use it.

Extended LSP watch patterns to include editable source roots plus editable metadata files, and rewatch/invalidate when those metadata files change.

Cleared editable-path cache on watch events (LSP + CLI watch) so changes pick up new editable roots.

Test Plan

add test

@meta-cla meta-cla bot added the cla signed label Mar 4, 2026
@asukaminato0721 asukaminato0721 marked this pull request as ready for review March 4, 2026 16:18
Copilot AI review requested due to automatic review settings March 4, 2026 16:18
@asukaminato0721 asukaminato0721 marked this pull request as draft March 4, 2026 16:18
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds first-class support for detecting Python editable installs and using that information to (a) classify “source vs third-party” correctly in the LSP and (b) expand/refresh file watching so editable source roots are re-analyzed when editable-install metadata changes.

Changes:

  • Introduces pyrefly_util::editable_install to detect editable installs via direct_url.json (PEP 610), .pth, and .egg-link, with caching + unit tests.
  • Switches LSP “third-party vs source” logic to use the shared editable detector.
  • Extends watcher patterns and invalidation to clear the editable-path cache and re-watch when editable metadata changes.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
pyrefly/lib/state/state.rs Clears editable-install cache on watcher events when editable metadata changes.
pyrefly/lib/state/lsp.rs Removes local editable detection/cache and uses shared util API for editable source roots.
pyrefly/lib/lsp/non_wasm/server.rs Forces re-watch and clears cache when editable metadata changes.
crates/pyrefly_util/src/lib.rs Exposes new editable_install module.
crates/pyrefly_util/src/editable_install.rs Implements shared editable-install detection + cache + tests.
crates/pyrefly_config/src/config.rs Adds editable roots + editable metadata files to watch patterns.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

You can also share your feedback on Copilot code review. Take the survey.

Comment on lines +3370 to +3372
if editable_metadata_changed {
clear_editable_source_paths_cache();
}
Copy link

Copilot AI Mar 4, 2026

Choose a reason for hiding this comment

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

did_change_watched_files clears the editable-path cache here, and Transaction::invalidate_events also clears the same cache when editable metadata changes. This causes redundant global mutex locking/clearing on every editable-metadata event. Consider centralizing the cache clear in one place (e.g., reorder to invalidate first so the transaction clears before setup_file_watcher_if_necessary, or make invalidate_events optionally skip clearing when already done).

Copilot uses AI. Check for mistakes.
Comment on lines +937 to +941
result.insert(WatchPattern::root(root.dupe(), "**/*.pth".to_owned()));
result.insert(WatchPattern::root(root.dupe(), "**/*.egg-link".to_owned()));
result.insert(WatchPattern::root(
root,
"**/*.dist-info/direct_url.json".to_owned(),
Copy link

Copilot AI Mar 4, 2026

Choose a reason for hiding this comment

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

The new watcher globs for editable metadata are very broad (**/*.pth / **/*.egg-link) under each site-packages root. Python only considers .pth/.egg-link files at the site-packages root, so watching recursively can add unnecessary watcher load/noise in large environments. Consider narrowing these patterns (e.g., *.pth / *.egg-link, and similarly limiting direct_url.json to the expected top-level *.dist-info/direct_url.json locations) to reduce watcher overhead.

Suggested change
result.insert(WatchPattern::root(root.dupe(), "**/*.pth".to_owned()));
result.insert(WatchPattern::root(root.dupe(), "**/*.egg-link".to_owned()));
result.insert(WatchPattern::root(
root,
"**/*.dist-info/direct_url.json".to_owned(),
result.insert(WatchPattern::root(root.dupe(), "*.pth".to_owned()));
result.insert(WatchPattern::root(root.dupe(), "*.egg-link".to_owned()));
result.insert(WatchPattern::root(
root,
"*.dist-info/direct_url.json".to_owned(),

Copilot uses AI. Check for mistakes.
Comment on lines +919 to +943
let site_packages: Vec<PathBuf> = config.site_package_path().cloned().collect();
let editable_paths = get_editable_source_paths(&site_packages);

config
.search_path()
.chain(config.site_package_path())
.cloned()
.chain(site_packages.iter().cloned())
.chain(editable_paths.iter().cloned())
.cartesian_product(PYTHON_EXTENSIONS.iter().chain(COMPILED_FILE_SUFFIXES))
.for_each(|(s, suffix)| {
result.insert(WatchPattern::root(
InternedPath::from_path(s),
InternedPath::from_path(&s),
format!("**/*.{suffix}"),
));
});

for site_package_path in &site_packages {
let root = InternedPath::from_path(site_package_path);
result.insert(WatchPattern::root(root.dupe(), "**/*.pth".to_owned()));
result.insert(WatchPattern::root(root.dupe(), "**/*.egg-link".to_owned()));
result.insert(WatchPattern::root(
root,
"**/*.dist-info/direct_url.json".to_owned(),
));
}
Copy link

Copilot AI Mar 4, 2026

Choose a reason for hiding this comment

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

ConfigFile::get_paths_to_watch now depends on editable install detection (editable source roots + editable metadata files), but there are no unit tests covering this function’s output even though this file has extensive config-related tests. Adding a focused test that constructs a temp site-packages with direct_url.json / .pth / .egg-link and asserts the returned WatchPatterns include the editable roots + metadata globs would help prevent regressions.

Copilot uses AI. Check for mistakes.
@github-actions

This comment has been minimized.

@github-actions
Copy link

github-actions bot commented Mar 5, 2026

According to mypy_primer, this change doesn't affect type check results on a corpus of open source code. ✅

@asukaminato0721 asukaminato0721 marked this pull request as ready for review March 5, 2026 03:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants