Skip to content

Commit 9002604

Browse files
authored
[ty] Use python version and path from Python extension (#19012)
1 parent 26f736b commit 9002604

File tree

22 files changed

+344
-99
lines changed

22 files changed

+344
-99
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/ty/src/lib.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -121,17 +121,17 @@ fn run_check(args: CheckCommand) -> anyhow::Result<ExitStatus> {
121121
None => ProjectMetadata::discover(&project_path, &system)?,
122122
};
123123

124-
let options = args.into_options();
125-
project_metadata.apply_options(options.clone());
126124
project_metadata.apply_configuration_files(&system)?;
127125

126+
let project_options_overrides = ProjectOptionsOverrides::new(config_file, args.into_options());
127+
project_metadata.apply_overrides(&project_options_overrides);
128+
128129
let mut db = ProjectDatabase::new(project_metadata, system)?;
129130

130131
if !check_paths.is_empty() {
131132
db.project().set_included_paths(&mut db, check_paths);
132133
}
133134

134-
let project_options_overrides = ProjectOptionsOverrides::new(config_file, options);
135135
let (main_loop, main_loop_cancellation_token) =
136136
MainLoop::new(project_options_overrides, printer);
137137

crates/ty_project/src/db.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use std::panic::{AssertUnwindSafe, RefUnwindSafe};
33
use std::sync::Arc;
44
use std::{cmp, fmt};
55

6+
pub use self::changes::ChangeResult;
67
use crate::metadata::settings::file_settings;
78
use crate::{DEFAULT_LINT_REGISTRY, DummyReporter};
89
use crate::{ProgressReporter, Project, ProjectMetadata};

crates/ty_project/src/db/changes.rs

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,6 @@ impl ProjectDatabase {
4141
let project_root = project.root(self).to_path_buf();
4242
let config_file_override =
4343
project_options_overrides.and_then(|options| options.config_file_override.clone());
44-
let options =
45-
project_options_overrides.map(|project_options| project_options.options.clone());
4644
let program = Program::get(self);
4745
let custom_stdlib_versions_path = program
4846
.custom_stdlib_search_path(self)
@@ -218,16 +216,16 @@ impl ProjectDatabase {
218216
};
219217
match new_project_metadata {
220218
Ok(mut metadata) => {
221-
if let Some(cli_options) = options {
222-
metadata.apply_options(cli_options);
223-
}
224-
225219
if let Err(error) = metadata.apply_configuration_files(self.system()) {
226220
tracing::error!(
227221
"Failed to apply configuration files, continuing without applying them: {error}"
228222
);
229223
}
230224

225+
if let Some(overrides) = project_options_overrides {
226+
metadata.apply_overrides(overrides);
227+
}
228+
231229
match metadata.to_program_settings(self.system(), self.vendored()) {
232230
Ok(program_settings) => {
233231
let program = Program::get(self);

crates/ty_project/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use crate::glob::{GlobFilterCheckMode, IncludeResult};
22
use crate::metadata::options::{OptionDiagnostic, ToSettingsError};
33
use crate::walk::{ProjectFilesFilter, ProjectFilesWalker};
4-
pub use db::{CheckMode, Db, ProjectDatabase, SalsaMemoryDump};
4+
pub use db::{ChangeResult, CheckMode, Db, ProjectDatabase, SalsaMemoryDump};
55
use files::{Index, Indexed, IndexedFiles};
66
use metadata::settings::Settings;
77
pub use metadata::{ProjectMetadata, ProjectMetadataError};

crates/ty_project/src/metadata.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use thiserror::Error;
77
use ty_python_semantic::ProgramSettings;
88

99
use crate::combine::Combine;
10+
use crate::metadata::options::ProjectOptionsOverrides;
1011
use crate::metadata::pyproject::{Project, PyProject, PyProjectError, ResolveRequiresPythonError};
1112
use crate::metadata::value::ValueSource;
1213
pub use options::Options;
@@ -276,6 +277,10 @@ impl ProjectMetadata {
276277
.to_program_settings(self.root(), self.name(), system, vendored)
277278
}
278279

280+
pub fn apply_overrides(&mut self, overrides: &ProjectOptionsOverrides) {
281+
self.options = overrides.apply_to(std::mem::take(&mut self.options));
282+
}
283+
279284
/// Combine the project options with the CLI options where the CLI options take precedence.
280285
pub fn apply_options(&mut self, options: Options) {
281286
self.options = options.combine(std::mem::take(&mut self.options));

crates/ty_project/src/metadata/options.rs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,9 @@ impl Options {
121121
ValueSource::File(path) => PythonVersionSource::ConfigFile(
122122
PythonVersionFileSource::new(path.clone(), ranged_version.range()),
123123
),
124+
ValueSource::PythonVSCodeExtension => {
125+
PythonVersionSource::PythonVSCodeExtension
126+
}
124127
},
125128
});
126129

@@ -140,6 +143,7 @@ impl Options {
140143
ValueSource::File(path) => {
141144
SysPrefixPathOrigin::ConfigFileSetting(path.clone(), python_path.range())
142145
}
146+
ValueSource::PythonVSCodeExtension => SysPrefixPathOrigin::PythonVSCodeExtension,
143147
};
144148

145149
Some(PythonEnvironment::new(
@@ -702,6 +706,10 @@ impl Rules {
702706
let lint_source = match source {
703707
ValueSource::File(_) => LintSource::File,
704708
ValueSource::Cli => LintSource::Cli,
709+
710+
ValueSource::PythonVSCodeExtension => {
711+
unreachable!("Can't configure rules from the Python VSCode extension")
712+
}
705713
};
706714
if let Ok(severity) = Severity::try_from(**level) {
707715
selection.enable(lint, severity, lint_source);
@@ -854,6 +862,7 @@ fn build_include_filter(
854862
Severity::Info,
855863
"The pattern was specified on the CLI",
856864
)),
865+
ValueSource::PythonVSCodeExtension => unreachable!("Can't configure includes from the Python VSCode extension"),
857866
}
858867
})?;
859868
}
@@ -936,6 +945,9 @@ fn build_exclude_filter(
936945
Severity::Info,
937946
"The pattern was specified on the CLI",
938947
)),
948+
ValueSource::PythonVSCodeExtension => unreachable!(
949+
"Can't configure excludes from the Python VSCode extension"
950+
)
939951
}
940952
})?;
941953
}
@@ -1497,8 +1509,11 @@ impl OptionDiagnostic {
14971509
/// This is a wrapper for options that actually get loaded from configuration files
14981510
/// and the CLI, which also includes a `config_file_override` option that overrides
14991511
/// default configuration discovery with an explicitly-provided path to a configuration file
1512+
#[derive(Debug, Default, PartialEq, Eq, Clone)]
15001513
pub struct ProjectOptionsOverrides {
15011514
pub config_file_override: Option<SystemPathBuf>,
1515+
pub fallback_python_version: Option<RangedValue<PythonVersion>>,
1516+
pub fallback_python: Option<RelativePathBuf>,
15021517
pub options: Options,
15031518
}
15041519

@@ -1507,8 +1522,22 @@ impl ProjectOptionsOverrides {
15071522
Self {
15081523
config_file_override,
15091524
options,
1525+
..Self::default()
15101526
}
15111527
}
1528+
1529+
pub fn apply_to(&self, options: Options) -> Options {
1530+
let mut combined = self.options.clone().combine(options);
1531+
1532+
// Set the fallback python version and path if set
1533+
combined.environment.combine_with(Some(EnvironmentOptions {
1534+
python_version: self.fallback_python_version.clone(),
1535+
python: self.fallback_python.clone(),
1536+
..EnvironmentOptions::default()
1537+
}));
1538+
1539+
combined
1540+
}
15121541
}
15131542

15141543
trait OrDefault {

crates/ty_project/src/metadata/value.rs

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,17 @@ pub enum ValueSource {
2727
/// The value comes from a CLI argument, while it's left open if specified using a short argument,
2828
/// long argument (`--extra-paths`) or `--config key=value`.
2929
Cli,
30+
31+
/// The value comes from an LSP client configuration.
32+
PythonVSCodeExtension,
3033
}
3134

3235
impl ValueSource {
3336
pub fn file(&self) -> Option<&SystemPath> {
3437
match self {
3538
ValueSource::File(path) => Some(&**path),
3639
ValueSource::Cli => None,
40+
ValueSource::PythonVSCodeExtension => None,
3741
}
3842
}
3943

@@ -105,6 +109,14 @@ impl<T> RangedValue<T> {
105109
Self::with_range(value, ValueSource::Cli, TextRange::default())
106110
}
107111

112+
pub fn python_extension(value: T) -> Self {
113+
Self::with_range(
114+
value,
115+
ValueSource::PythonVSCodeExtension,
116+
TextRange::default(),
117+
)
118+
}
119+
108120
pub fn with_range(value: T, source: ValueSource, range: TextRange) -> Self {
109121
Self {
110122
value,
@@ -327,6 +339,10 @@ impl RelativePathBuf {
327339
Self::new(path, ValueSource::Cli)
328340
}
329341

342+
pub fn python_extension(path: impl AsRef<SystemPath>) -> Self {
343+
Self::new(path, ValueSource::PythonVSCodeExtension)
344+
}
345+
330346
/// Returns the relative path as specified by the user.
331347
pub fn path(&self) -> &SystemPath {
332348
&self.0
@@ -354,7 +370,7 @@ impl RelativePathBuf {
354370
pub fn absolute(&self, project_root: &SystemPath, system: &dyn System) -> SystemPathBuf {
355371
let relative_to = match &self.0.source {
356372
ValueSource::File(_) => project_root,
357-
ValueSource::Cli => system.current_directory(),
373+
ValueSource::Cli | ValueSource::PythonVSCodeExtension => system.current_directory(),
358374
};
359375

360376
SystemPath::absolute(&self.0, relative_to)
@@ -409,7 +425,7 @@ impl RelativeGlobPattern {
409425
) -> Result<AbsolutePortableGlobPattern, PortableGlobError> {
410426
let relative_to = match &self.0.source {
411427
ValueSource::File(_) => project_root,
412-
ValueSource::Cli => system.current_directory(),
428+
ValueSource::Cli | ValueSource::PythonVSCodeExtension => system.current_directory(),
413429
};
414430

415431
let pattern = PortableGlobPattern::parse(&self.0, kind)?;

crates/ty_python_semantic/src/program.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,9 @@ pub enum PythonVersionSource {
113113
/// long argument (`--extra-paths`) or `--config key=value`.
114114
Cli,
115115

116+
/// The value comes from the Python VS Code extension (the selected interpreter).
117+
PythonVSCodeExtension,
118+
116119
/// We fell back to a default value because the value was not specified via the CLI or a config file.
117120
#[default]
118121
Default,

crates/ty_python_semantic/src/site_packages.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1065,6 +1065,8 @@ pub enum SysPrefixPathOrigin {
10651065
ConfigFileSetting(Arc<SystemPathBuf>, Option<TextRange>),
10661066
/// The `sys.prefix` path came from a `--python` CLI flag
10671067
PythonCliFlag,
1068+
/// The selected interpreter in the VS Code's Python extension.
1069+
PythonVSCodeExtension,
10681070
/// The `sys.prefix` path came from the `VIRTUAL_ENV` environment variable
10691071
VirtualEnvVar,
10701072
/// The `sys.prefix` path came from the `CONDA_PREFIX` environment variable
@@ -1086,6 +1088,7 @@ impl SysPrefixPathOrigin {
10861088
Self::LocalVenv | Self::VirtualEnvVar => true,
10871089
Self::ConfigFileSetting(..)
10881090
| Self::PythonCliFlag
1091+
| Self::PythonVSCodeExtension
10891092
| Self::DerivedFromPyvenvCfg
10901093
| Self::CondaPrefixVar => false,
10911094
}
@@ -1097,7 +1100,9 @@ impl SysPrefixPathOrigin {
10971100
/// the `sys.prefix` directory, e.g. the `--python` CLI flag.
10981101
pub(crate) const fn must_point_directly_to_sys_prefix(&self) -> bool {
10991102
match self {
1100-
Self::PythonCliFlag | Self::ConfigFileSetting(..) => false,
1103+
Self::PythonCliFlag | Self::ConfigFileSetting(..) | Self::PythonVSCodeExtension => {
1104+
false
1105+
}
11011106
Self::VirtualEnvVar
11021107
| Self::CondaPrefixVar
11031108
| Self::DerivedFromPyvenvCfg
@@ -1115,6 +1120,9 @@ impl std::fmt::Display for SysPrefixPathOrigin {
11151120
Self::CondaPrefixVar => f.write_str("`CONDA_PREFIX` environment variable"),
11161121
Self::DerivedFromPyvenvCfg => f.write_str("derived `sys.prefix` path"),
11171122
Self::LocalVenv => f.write_str("local virtual environment"),
1123+
Self::PythonVSCodeExtension => {
1124+
f.write_str("selected interpreter in the VS Code Python extension")
1125+
}
11181126
}
11191127
}
11201128
}

0 commit comments

Comments
 (0)