mirror of
https://github.com/astral-sh/ruff.git
synced 2025-07-07 13:15:06 +00:00
[ty] Document configuration schema (#17950)
This commit is contained in:
parent
f46ed8d410
commit
12ce445ff7
26 changed files with 710 additions and 93 deletions
|
@ -5,6 +5,7 @@ exclude: |
|
||||||
.github/workflows/release.yml|
|
.github/workflows/release.yml|
|
||||||
crates/ty_vendored/vendor/.*|
|
crates/ty_vendored/vendor/.*|
|
||||||
crates/ty_project/resources/.*|
|
crates/ty_project/resources/.*|
|
||||||
|
crates/ty/docs/configuration.md|
|
||||||
crates/ty/docs/rules.md|
|
crates/ty/docs/rules.md|
|
||||||
crates/ruff_benchmark/resources/.*|
|
crates/ruff_benchmark/resources/.*|
|
||||||
crates/ruff_linter/resources/.*|
|
crates/ruff_linter/resources/.*|
|
||||||
|
|
11
Cargo.lock
generated
11
Cargo.lock
generated
|
@ -2583,6 +2583,7 @@ dependencies = [
|
||||||
"ruff_linter",
|
"ruff_linter",
|
||||||
"ruff_macros",
|
"ruff_macros",
|
||||||
"ruff_notebook",
|
"ruff_notebook",
|
||||||
|
"ruff_options_metadata",
|
||||||
"ruff_python_ast",
|
"ruff_python_ast",
|
||||||
"ruff_python_formatter",
|
"ruff_python_formatter",
|
||||||
"ruff_python_parser",
|
"ruff_python_parser",
|
||||||
|
@ -2709,6 +2710,7 @@ dependencies = [
|
||||||
"ruff_formatter",
|
"ruff_formatter",
|
||||||
"ruff_linter",
|
"ruff_linter",
|
||||||
"ruff_notebook",
|
"ruff_notebook",
|
||||||
|
"ruff_options_metadata",
|
||||||
"ruff_python_ast",
|
"ruff_python_ast",
|
||||||
"ruff_python_codegen",
|
"ruff_python_codegen",
|
||||||
"ruff_python_formatter",
|
"ruff_python_formatter",
|
||||||
|
@ -2876,6 +2878,13 @@ dependencies = [
|
||||||
"uuid",
|
"uuid",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ruff_options_metadata"
|
||||||
|
version = "0.0.0"
|
||||||
|
dependencies = [
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ruff_python_ast"
|
name = "ruff_python_ast"
|
||||||
version = "0.0.0"
|
version = "0.0.0"
|
||||||
|
@ -3162,6 +3171,7 @@ dependencies = [
|
||||||
"ruff_graph",
|
"ruff_graph",
|
||||||
"ruff_linter",
|
"ruff_linter",
|
||||||
"ruff_macros",
|
"ruff_macros",
|
||||||
|
"ruff_options_metadata",
|
||||||
"ruff_python_ast",
|
"ruff_python_ast",
|
||||||
"ruff_python_formatter",
|
"ruff_python_formatter",
|
||||||
"ruff_python_semantic",
|
"ruff_python_semantic",
|
||||||
|
@ -4015,6 +4025,7 @@ dependencies = [
|
||||||
"ruff_cache",
|
"ruff_cache",
|
||||||
"ruff_db",
|
"ruff_db",
|
||||||
"ruff_macros",
|
"ruff_macros",
|
||||||
|
"ruff_options_metadata",
|
||||||
"ruff_python_ast",
|
"ruff_python_ast",
|
||||||
"ruff_python_formatter",
|
"ruff_python_formatter",
|
||||||
"ruff_text_size",
|
"ruff_text_size",
|
||||||
|
|
|
@ -23,6 +23,7 @@ ruff_index = { path = "crates/ruff_index" }
|
||||||
ruff_linter = { path = "crates/ruff_linter" }
|
ruff_linter = { path = "crates/ruff_linter" }
|
||||||
ruff_macros = { path = "crates/ruff_macros" }
|
ruff_macros = { path = "crates/ruff_macros" }
|
||||||
ruff_notebook = { path = "crates/ruff_notebook" }
|
ruff_notebook = { path = "crates/ruff_notebook" }
|
||||||
|
ruff_options_metadata = { path = "crates/ruff_options_metadata" }
|
||||||
ruff_python_ast = { path = "crates/ruff_python_ast" }
|
ruff_python_ast = { path = "crates/ruff_python_ast" }
|
||||||
ruff_python_codegen = { path = "crates/ruff_python_codegen" }
|
ruff_python_codegen = { path = "crates/ruff_python_codegen" }
|
||||||
ruff_python_formatter = { path = "crates/ruff_python_formatter" }
|
ruff_python_formatter = { path = "crates/ruff_python_formatter" }
|
||||||
|
@ -182,7 +183,7 @@ wild = { version = "2" }
|
||||||
zip = { version = "0.6.6", default-features = false }
|
zip = { version = "0.6.6", default-features = false }
|
||||||
|
|
||||||
[workspace.metadata.cargo-shear]
|
[workspace.metadata.cargo-shear]
|
||||||
ignored = ["getrandom"]
|
ignored = ["getrandom", "ruff_options_metadata"]
|
||||||
|
|
||||||
|
|
||||||
[workspace.lints.rust]
|
[workspace.lints.rust]
|
||||||
|
|
|
@ -20,6 +20,7 @@ ruff_graph = { workspace = true, features = ["serde", "clap"] }
|
||||||
ruff_linter = { workspace = true, features = ["clap"] }
|
ruff_linter = { workspace = true, features = ["clap"] }
|
||||||
ruff_macros = { workspace = true }
|
ruff_macros = { workspace = true }
|
||||||
ruff_notebook = { workspace = true }
|
ruff_notebook = { workspace = true }
|
||||||
|
ruff_options_metadata = { workspace = true, features = ["serde"] }
|
||||||
ruff_python_ast = { workspace = true }
|
ruff_python_ast = { workspace = true }
|
||||||
ruff_python_formatter = { workspace = true }
|
ruff_python_formatter = { workspace = true }
|
||||||
ruff_python_parser = { workspace = true }
|
ruff_python_parser = { workspace = true }
|
||||||
|
|
|
@ -22,12 +22,12 @@ use ruff_linter::settings::types::{
|
||||||
PythonVersion, UnsafeFixes,
|
PythonVersion, UnsafeFixes,
|
||||||
};
|
};
|
||||||
use ruff_linter::{RuleParser, RuleSelector, RuleSelectorParser};
|
use ruff_linter::{RuleParser, RuleSelector, RuleSelectorParser};
|
||||||
|
use ruff_options_metadata::{OptionEntry, OptionsMetadata};
|
||||||
use ruff_python_ast as ast;
|
use ruff_python_ast as ast;
|
||||||
use ruff_source_file::{LineIndex, OneIndexed, PositionEncoding};
|
use ruff_source_file::{LineIndex, OneIndexed, PositionEncoding};
|
||||||
use ruff_text_size::TextRange;
|
use ruff_text_size::TextRange;
|
||||||
use ruff_workspace::configuration::{Configuration, RuleSelection};
|
use ruff_workspace::configuration::{Configuration, RuleSelection};
|
||||||
use ruff_workspace::options::{Options, PycodestyleOptions};
|
use ruff_workspace::options::{Options, PycodestyleOptions};
|
||||||
use ruff_workspace::options_base::{OptionEntry, OptionsMetadata};
|
|
||||||
use ruff_workspace::resolver::ConfigurationTransformer;
|
use ruff_workspace::resolver::ConfigurationTransformer;
|
||||||
use rustc_hash::FxHashMap;
|
use rustc_hash::FxHashMap;
|
||||||
use toml;
|
use toml;
|
||||||
|
|
|
@ -2,10 +2,8 @@ use clap::builder::{PossibleValue, TypedValueParser, ValueParserFactory};
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
use ruff_workspace::{
|
use ruff_options_metadata::{OptionField, OptionSet, OptionsMetadata, Visit};
|
||||||
options::Options,
|
use ruff_workspace::options::Options;
|
||||||
options_base::{OptionField, OptionSet, OptionsMetadata, Visit},
|
|
||||||
};
|
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
struct CollectOptionsVisitor {
|
struct CollectOptionsVisitor {
|
||||||
|
|
|
@ -2,8 +2,8 @@ use anyhow::{anyhow, Result};
|
||||||
|
|
||||||
use crate::args::HelpFormat;
|
use crate::args::HelpFormat;
|
||||||
|
|
||||||
|
use ruff_options_metadata::OptionsMetadata;
|
||||||
use ruff_workspace::options::Options;
|
use ruff_workspace::options::Options;
|
||||||
use ruff_workspace::options_base::OptionsMetadata;
|
|
||||||
|
|
||||||
#[expect(clippy::print_stdout)]
|
#[expect(clippy::print_stdout)]
|
||||||
pub(crate) fn config(key: Option<&str>, format: HelpFormat) -> Result<()> {
|
pub(crate) fn config(key: Option<&str>, format: HelpFormat) -> Result<()> {
|
||||||
|
|
|
@ -17,6 +17,7 @@ ruff_diagnostics = { workspace = true }
|
||||||
ruff_formatter = { workspace = true }
|
ruff_formatter = { workspace = true }
|
||||||
ruff_linter = { workspace = true, features = ["schemars"] }
|
ruff_linter = { workspace = true, features = ["schemars"] }
|
||||||
ruff_notebook = { workspace = true }
|
ruff_notebook = { workspace = true }
|
||||||
|
ruff_options_metadata = { workspace = true }
|
||||||
ruff_python_ast = { workspace = true }
|
ruff_python_ast = { workspace = true }
|
||||||
ruff_python_codegen = { workspace = true }
|
ruff_python_codegen = { workspace = true }
|
||||||
ruff_python_formatter = { workspace = true }
|
ruff_python_formatter = { workspace = true }
|
||||||
|
|
|
@ -3,7 +3,8 @@
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
generate_cli_help, generate_docs, generate_json_schema, generate_ty_rules, generate_ty_schema,
|
generate_cli_help, generate_docs, generate_json_schema, generate_ty_options, generate_ty_rules,
|
||||||
|
generate_ty_schema,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub(crate) const REGENERATE_ALL_COMMAND: &str = "cargo dev generate-all";
|
pub(crate) const REGENERATE_ALL_COMMAND: &str = "cargo dev generate-all";
|
||||||
|
@ -40,6 +41,7 @@ pub(crate) fn main(args: &Args) -> Result<()> {
|
||||||
generate_docs::main(&generate_docs::Args {
|
generate_docs::main(&generate_docs::Args {
|
||||||
dry_run: args.mode.is_dry_run(),
|
dry_run: args.mode.is_dry_run(),
|
||||||
})?;
|
})?;
|
||||||
|
generate_ty_options::main(&generate_ty_options::Args { mode: args.mode })?;
|
||||||
generate_ty_rules::main(&generate_ty_rules::Args { mode: args.mode })?;
|
generate_ty_rules::main(&generate_ty_rules::Args { mode: args.mode })?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,8 +13,8 @@ use strum::IntoEnumIterator;
|
||||||
|
|
||||||
use ruff_diagnostics::FixAvailability;
|
use ruff_diagnostics::FixAvailability;
|
||||||
use ruff_linter::registry::{Linter, Rule, RuleNamespace};
|
use ruff_linter::registry::{Linter, Rule, RuleNamespace};
|
||||||
|
use ruff_options_metadata::{OptionEntry, OptionsMetadata};
|
||||||
use ruff_workspace::options::Options;
|
use ruff_workspace::options::Options;
|
||||||
use ruff_workspace::options_base::{OptionEntry, OptionsMetadata};
|
|
||||||
|
|
||||||
use crate::ROOT_DIR;
|
use crate::ROOT_DIR;
|
||||||
|
|
||||||
|
|
|
@ -4,9 +4,9 @@
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use std::fmt::Write;
|
use std::fmt::Write;
|
||||||
|
|
||||||
|
use ruff_options_metadata::{OptionField, OptionSet, OptionsMetadata, Visit};
|
||||||
use ruff_python_trivia::textwrap;
|
use ruff_python_trivia::textwrap;
|
||||||
use ruff_workspace::options::Options;
|
use ruff_workspace::options::Options;
|
||||||
use ruff_workspace::options_base::{OptionField, OptionSet, OptionsMetadata, Visit};
|
|
||||||
|
|
||||||
pub(crate) fn generate() -> String {
|
pub(crate) fn generate() -> String {
|
||||||
let mut output = String::new();
|
let mut output = String::new();
|
||||||
|
|
|
@ -11,8 +11,8 @@ use strum::IntoEnumIterator;
|
||||||
use ruff_diagnostics::FixAvailability;
|
use ruff_diagnostics::FixAvailability;
|
||||||
use ruff_linter::registry::{Linter, Rule, RuleNamespace};
|
use ruff_linter::registry::{Linter, Rule, RuleNamespace};
|
||||||
use ruff_linter::upstream_categories::UpstreamCategoryAndPrefix;
|
use ruff_linter::upstream_categories::UpstreamCategoryAndPrefix;
|
||||||
|
use ruff_options_metadata::OptionsMetadata;
|
||||||
use ruff_workspace::options::Options;
|
use ruff_workspace::options::Options;
|
||||||
use ruff_workspace::options_base::OptionsMetadata;
|
|
||||||
|
|
||||||
const FIX_SYMBOL: &str = "🛠️";
|
const FIX_SYMBOL: &str = "🛠️";
|
||||||
const PREVIEW_SYMBOL: &str = "🧪";
|
const PREVIEW_SYMBOL: &str = "🧪";
|
||||||
|
|
258
crates/ruff_dev/src/generate_ty_options.rs
Normal file
258
crates/ruff_dev/src/generate_ty_options.rs
Normal file
|
@ -0,0 +1,258 @@
|
||||||
|
//! Generate a Markdown-compatible listing of configuration options for `pyproject.toml`.
|
||||||
|
#![allow(clippy::print_stdout, clippy::print_stderr)]
|
||||||
|
|
||||||
|
use anyhow::bail;
|
||||||
|
use itertools::Itertools;
|
||||||
|
use pretty_assertions::StrComparison;
|
||||||
|
use std::{fmt::Write, path::PathBuf};
|
||||||
|
|
||||||
|
use ruff_options_metadata::{OptionField, OptionSet, OptionsMetadata, Visit};
|
||||||
|
use ty_project::metadata::Options;
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
generate_all::{Mode, REGENERATE_ALL_COMMAND},
|
||||||
|
ROOT_DIR,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(clap::Args)]
|
||||||
|
pub(crate) struct Args {
|
||||||
|
/// Write the generated table to stdout (rather than to `crates/ty/docs/configuration.md`).
|
||||||
|
#[arg(long, default_value_t, value_enum)]
|
||||||
|
pub(crate) mode: Mode,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn main(args: &Args) -> anyhow::Result<()> {
|
||||||
|
let mut output = String::new();
|
||||||
|
let file_name = "crates/ty/docs/configuration.md";
|
||||||
|
let markdown_path = PathBuf::from(ROOT_DIR).join(file_name);
|
||||||
|
|
||||||
|
generate_set(
|
||||||
|
&mut output,
|
||||||
|
Set::Toplevel(Options::metadata()),
|
||||||
|
&mut Vec::new(),
|
||||||
|
);
|
||||||
|
|
||||||
|
match args.mode {
|
||||||
|
Mode::DryRun => {
|
||||||
|
println!("{output}");
|
||||||
|
}
|
||||||
|
Mode::Check => {
|
||||||
|
let current = std::fs::read_to_string(&markdown_path)?;
|
||||||
|
if output == current {
|
||||||
|
println!("Up-to-date: {file_name}",);
|
||||||
|
} else {
|
||||||
|
let comparison = StrComparison::new(¤t, &output);
|
||||||
|
bail!("{file_name} changed, please run `{REGENERATE_ALL_COMMAND}`:\n{comparison}",);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Mode::Write => {
|
||||||
|
let current = std::fs::read_to_string(&markdown_path)?;
|
||||||
|
if current == output {
|
||||||
|
println!("Up-to-date: {file_name}",);
|
||||||
|
} else {
|
||||||
|
println!("Updating: {file_name}",);
|
||||||
|
std::fs::write(markdown_path, output.as_bytes())?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn generate_set(output: &mut String, set: Set, parents: &mut Vec<Set>) {
|
||||||
|
match &set {
|
||||||
|
Set::Toplevel(_) => {
|
||||||
|
output.push_str("# Configuration\n");
|
||||||
|
}
|
||||||
|
Set::Named { name, .. } => {
|
||||||
|
let title = parents
|
||||||
|
.iter()
|
||||||
|
.filter_map(|set| set.name())
|
||||||
|
.chain(std::iter::once(name.as_str()))
|
||||||
|
.join(".");
|
||||||
|
writeln!(output, "## `{title}`\n",).unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(documentation) = set.metadata().documentation() {
|
||||||
|
output.push_str(documentation);
|
||||||
|
output.push('\n');
|
||||||
|
output.push('\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut visitor = CollectOptionsVisitor::default();
|
||||||
|
set.metadata().record(&mut visitor);
|
||||||
|
|
||||||
|
let (mut fields, mut sets) = (visitor.fields, visitor.groups);
|
||||||
|
|
||||||
|
fields.sort_unstable_by(|(name, _), (name2, _)| name.cmp(name2));
|
||||||
|
sets.sort_unstable_by(|(name, _), (name2, _)| name.cmp(name2));
|
||||||
|
|
||||||
|
parents.push(set);
|
||||||
|
|
||||||
|
// Generate the fields.
|
||||||
|
for (name, field) in &fields {
|
||||||
|
emit_field(output, name, field, parents.as_slice());
|
||||||
|
output.push_str("---\n\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate all the sub-sets.
|
||||||
|
for (set_name, sub_set) in &sets {
|
||||||
|
generate_set(
|
||||||
|
output,
|
||||||
|
Set::Named {
|
||||||
|
name: set_name.to_string(),
|
||||||
|
set: *sub_set,
|
||||||
|
},
|
||||||
|
parents,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
parents.pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
enum Set {
|
||||||
|
Toplevel(OptionSet),
|
||||||
|
Named { name: String, set: OptionSet },
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Set {
|
||||||
|
fn name(&self) -> Option<&str> {
|
||||||
|
match self {
|
||||||
|
Set::Toplevel(_) => None,
|
||||||
|
Set::Named { name, .. } => Some(name),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn metadata(&self) -> &OptionSet {
|
||||||
|
match self {
|
||||||
|
Set::Toplevel(set) => set,
|
||||||
|
Set::Named { set, .. } => set,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn emit_field(output: &mut String, name: &str, field: &OptionField, parents: &[Set]) {
|
||||||
|
let header_level = if parents.is_empty() { "###" } else { "####" };
|
||||||
|
|
||||||
|
let _ = writeln!(output, "{header_level} [`{name}`]");
|
||||||
|
|
||||||
|
output.push('\n');
|
||||||
|
|
||||||
|
if let Some(deprecated) = &field.deprecated {
|
||||||
|
output.push_str("!!! warning \"Deprecated\"\n");
|
||||||
|
output.push_str(" This option has been deprecated");
|
||||||
|
|
||||||
|
if let Some(since) = deprecated.since {
|
||||||
|
write!(output, " in {since}").unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
output.push('.');
|
||||||
|
|
||||||
|
if let Some(message) = deprecated.message {
|
||||||
|
writeln!(output, " {message}").unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
output.push('\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
output.push_str(field.doc);
|
||||||
|
output.push_str("\n\n");
|
||||||
|
let _ = writeln!(output, "**Default value**: `{}`", field.default);
|
||||||
|
output.push('\n');
|
||||||
|
let _ = writeln!(output, "**Type**: `{}`", field.value_type);
|
||||||
|
output.push('\n');
|
||||||
|
output.push_str("**Example usage** (`pyproject.toml`):\n\n");
|
||||||
|
output.push_str(&format_example(
|
||||||
|
&format_header(
|
||||||
|
field.scope,
|
||||||
|
field.example,
|
||||||
|
parents,
|
||||||
|
ConfigurationFile::PyprojectToml,
|
||||||
|
),
|
||||||
|
field.example,
|
||||||
|
));
|
||||||
|
output.push('\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
fn format_example(header: &str, content: &str) -> String {
|
||||||
|
if header.is_empty() {
|
||||||
|
format!("```toml\n{content}\n```\n",)
|
||||||
|
} else {
|
||||||
|
format!("```toml\n{header}\n{content}\n```\n",)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Format the TOML header for the example usage for a given option.
|
||||||
|
///
|
||||||
|
/// For example: `[tool.ruff.format]` or `[tool.ruff.lint.isort]`.
|
||||||
|
fn format_header(
|
||||||
|
scope: Option<&str>,
|
||||||
|
example: &str,
|
||||||
|
parents: &[Set],
|
||||||
|
configuration: ConfigurationFile,
|
||||||
|
) -> String {
|
||||||
|
let tool_parent = match configuration {
|
||||||
|
ConfigurationFile::PyprojectToml => Some("tool.ty"),
|
||||||
|
ConfigurationFile::TyToml => None,
|
||||||
|
};
|
||||||
|
|
||||||
|
let header = tool_parent
|
||||||
|
.into_iter()
|
||||||
|
.chain(parents.iter().filter_map(|parent| parent.name()))
|
||||||
|
.chain(scope)
|
||||||
|
.join(".");
|
||||||
|
|
||||||
|
// Ex) `[[tool.ty.xx]]`
|
||||||
|
if example.starts_with(&format!("[[{header}")) {
|
||||||
|
return String::new();
|
||||||
|
}
|
||||||
|
// Ex) `[tool.ty.rules]`
|
||||||
|
if example.starts_with(&format!("[{header}")) {
|
||||||
|
return String::new();
|
||||||
|
}
|
||||||
|
|
||||||
|
if header.is_empty() {
|
||||||
|
String::new()
|
||||||
|
} else {
|
||||||
|
format!("[{header}]")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
struct CollectOptionsVisitor {
|
||||||
|
groups: Vec<(String, OptionSet)>,
|
||||||
|
fields: Vec<(String, OptionField)>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Visit for CollectOptionsVisitor {
|
||||||
|
fn record_set(&mut self, name: &str, group: OptionSet) {
|
||||||
|
self.groups.push((name.to_owned(), group));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn record_field(&mut self, name: &str, field: OptionField) {
|
||||||
|
self.fields.push((name.to_owned(), field));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Copy, Clone)]
|
||||||
|
enum ConfigurationFile {
|
||||||
|
PyprojectToml,
|
||||||
|
#[expect(dead_code)]
|
||||||
|
TyToml,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use anyhow::Result;
|
||||||
|
|
||||||
|
use crate::generate_all::Mode;
|
||||||
|
|
||||||
|
use super::{main, Args};
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn ty_configuration_markdown_up_to_date() -> Result<()> {
|
||||||
|
main(&Args { mode: Mode::Check })?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
|
@ -15,6 +15,7 @@ mod generate_docs;
|
||||||
mod generate_json_schema;
|
mod generate_json_schema;
|
||||||
mod generate_options;
|
mod generate_options;
|
||||||
mod generate_rules_table;
|
mod generate_rules_table;
|
||||||
|
mod generate_ty_options;
|
||||||
mod generate_ty_rules;
|
mod generate_ty_rules;
|
||||||
mod generate_ty_schema;
|
mod generate_ty_schema;
|
||||||
mod print_ast;
|
mod print_ast;
|
||||||
|
@ -48,6 +49,7 @@ enum Command {
|
||||||
GenerateTyRules(generate_ty_rules::Args),
|
GenerateTyRules(generate_ty_rules::Args),
|
||||||
/// Generate a Markdown-compatible listing of configuration options.
|
/// Generate a Markdown-compatible listing of configuration options.
|
||||||
GenerateOptions,
|
GenerateOptions,
|
||||||
|
GenerateTyOptions(generate_ty_options::Args),
|
||||||
/// Generate CLI help.
|
/// Generate CLI help.
|
||||||
GenerateCliHelp(generate_cli_help::Args),
|
GenerateCliHelp(generate_cli_help::Args),
|
||||||
/// Generate Markdown docs.
|
/// Generate Markdown docs.
|
||||||
|
@ -92,6 +94,7 @@ fn main() -> Result<ExitCode> {
|
||||||
Command::GenerateRulesTable => println!("{}", generate_rules_table::generate()),
|
Command::GenerateRulesTable => println!("{}", generate_rules_table::generate()),
|
||||||
Command::GenerateTyRules(args) => generate_ty_rules::main(&args)?,
|
Command::GenerateTyRules(args) => generate_ty_rules::main(&args)?,
|
||||||
Command::GenerateOptions => println!("{}", generate_options::generate()),
|
Command::GenerateOptions => println!("{}", generate_options::generate()),
|
||||||
|
Command::GenerateTyOptions(args) => generate_ty_options::main(&args)?,
|
||||||
Command::GenerateCliHelp(args) => generate_cli_help::main(&args)?,
|
Command::GenerateCliHelp(args) => generate_cli_help::main(&args)?,
|
||||||
Command::GenerateDocs(args) => generate_docs::main(&args)?,
|
Command::GenerateDocs(args) => generate_docs::main(&args)?,
|
||||||
Command::PrintAST(args) => print_ast::main(&args)?,
|
Command::PrintAST(args) => print_ast::main(&args)?,
|
||||||
|
|
|
@ -86,8 +86,8 @@ pub(crate) fn derive_impl(input: DeriveInput) -> syn::Result<TokenStream> {
|
||||||
|
|
||||||
Ok(quote! {
|
Ok(quote! {
|
||||||
#[automatically_derived]
|
#[automatically_derived]
|
||||||
impl crate::options_base::OptionsMetadata for #ident {
|
impl ruff_options_metadata::OptionsMetadata for #ident {
|
||||||
fn record(visit: &mut dyn crate::options_base::Visit) {
|
fn record(visit: &mut dyn ruff_options_metadata::Visit) {
|
||||||
#(#output);*
|
#(#output);*
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -125,7 +125,7 @@ fn handle_option_group(field: &Field) -> syn::Result<proc_macro2::TokenStream> {
|
||||||
let kebab_name = LitStr::new(&ident.to_string().replace('_', "-"), ident.span());
|
let kebab_name = LitStr::new(&ident.to_string().replace('_', "-"), ident.span());
|
||||||
|
|
||||||
Ok(quote_spanned!(
|
Ok(quote_spanned!(
|
||||||
ident.span() => (visit.record_set(#kebab_name, crate::options_base::OptionSet::of::<#path>()))
|
ident.span() => (visit.record_set(#kebab_name, ruff_options_metadata::OptionSet::of::<#path>()))
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
_ => Err(syn::Error::new(
|
_ => Err(syn::Error::new(
|
||||||
|
@ -214,14 +214,14 @@ fn handle_option(field: &Field, attr: &Attribute) -> syn::Result<proc_macro2::To
|
||||||
let note = quote_option(deprecated.note);
|
let note = quote_option(deprecated.note);
|
||||||
let since = quote_option(deprecated.since);
|
let since = quote_option(deprecated.since);
|
||||||
|
|
||||||
quote!(Some(crate::options_base::Deprecated { since: #since, message: #note }))
|
quote!(Some(ruff_options_metadata::Deprecated { since: #since, message: #note }))
|
||||||
} else {
|
} else {
|
||||||
quote!(None)
|
quote!(None)
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(quote_spanned!(
|
Ok(quote_spanned!(
|
||||||
ident.span() => {
|
ident.span() => {
|
||||||
visit.record_field(#kebab_name, crate::options_base::OptionField{
|
visit.record_field(#kebab_name, ruff_options_metadata::OptionField{
|
||||||
doc: &#doc,
|
doc: &#doc,
|
||||||
default: &#default,
|
default: &#default,
|
||||||
value_type: &#value_type,
|
value_type: &#value_type,
|
||||||
|
|
19
crates/ruff_options_metadata/Cargo.toml
Normal file
19
crates/ruff_options_metadata/Cargo.toml
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
[package]
|
||||||
|
name = "ruff_options_metadata"
|
||||||
|
version = "0.0.0"
|
||||||
|
publish = false
|
||||||
|
authors = { workspace = true }
|
||||||
|
edition = { workspace = true }
|
||||||
|
rust-version = { workspace = true }
|
||||||
|
homepage = { workspace = true }
|
||||||
|
documentation = { workspace = true }
|
||||||
|
repository = { workspace = true }
|
||||||
|
license = { workspace = true }
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
serde = { workspace = true, optional = true }
|
||||||
|
|
||||||
|
[dev-dependencies]
|
||||||
|
|
||||||
|
[lints]
|
||||||
|
workspace = true
|
|
@ -1,6 +1,3 @@
|
||||||
use serde::{Serialize, Serializer};
|
|
||||||
use std::collections::BTreeMap;
|
|
||||||
|
|
||||||
use std::fmt::{Debug, Display, Formatter};
|
use std::fmt::{Debug, Display, Formatter};
|
||||||
|
|
||||||
/// Visits [`OptionsMetadata`].
|
/// Visits [`OptionsMetadata`].
|
||||||
|
@ -42,8 +39,8 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Metadata of an option that can either be a [`OptionField`] or [`OptionSet`].
|
/// Metadata of an option that can either be a [`OptionField`] or [`OptionSet`].
|
||||||
#[derive(Clone, PartialEq, Eq, Debug, Serialize)]
|
#[derive(Clone, PartialEq, Eq, Debug)]
|
||||||
#[serde(untagged)]
|
#[cfg_attr(feature = "serde", derive(::serde::Serialize), serde(untagged))]
|
||||||
pub enum OptionEntry {
|
pub enum OptionEntry {
|
||||||
/// A single option.
|
/// A single option.
|
||||||
Field(OptionField),
|
Field(OptionField),
|
||||||
|
@ -102,7 +99,7 @@ impl OptionSet {
|
||||||
/// ### Test for the existence of a child option
|
/// ### Test for the existence of a child option
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// # use ruff_workspace::options_base::{OptionField, OptionsMetadata, Visit};
|
/// # use ruff_options_metadata::{OptionField, OptionsMetadata, Visit};
|
||||||
///
|
///
|
||||||
/// struct WithOptions;
|
/// struct WithOptions;
|
||||||
///
|
///
|
||||||
|
@ -125,7 +122,7 @@ impl OptionSet {
|
||||||
/// ### Test for the existence of a nested option
|
/// ### Test for the existence of a nested option
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// # use ruff_workspace::options_base::{OptionField, OptionsMetadata, Visit};
|
/// # use ruff_options_metadata::{OptionField, OptionsMetadata, Visit};
|
||||||
///
|
///
|
||||||
/// struct Root;
|
/// struct Root;
|
||||||
///
|
///
|
||||||
|
@ -176,7 +173,7 @@ impl OptionSet {
|
||||||
/// ### Find a child option
|
/// ### Find a child option
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// # use ruff_workspace::options_base::{OptionEntry, OptionField, OptionsMetadata, Visit};
|
/// # use ruff_options_metadata::{OptionEntry, OptionField, OptionsMetadata, Visit};
|
||||||
///
|
///
|
||||||
/// struct WithOptions;
|
/// struct WithOptions;
|
||||||
///
|
///
|
||||||
|
@ -201,7 +198,7 @@ impl OptionSet {
|
||||||
/// ### Find a nested option
|
/// ### Find a nested option
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// # use ruff_workspace::options_base::{OptionEntry, OptionField, OptionsMetadata, Visit};
|
/// # use ruff_options_metadata::{OptionEntry, OptionField, OptionsMetadata, Visit};
|
||||||
///
|
///
|
||||||
/// static HARD_TABS: OptionField = OptionField {
|
/// static HARD_TABS: OptionField = OptionField {
|
||||||
/// doc: "Use hard tabs for indentation and spaces for alignment.",
|
/// doc: "Use hard tabs for indentation and spaces for alignment.",
|
||||||
|
@ -345,51 +342,14 @@ impl Display for OptionSet {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct SerializeVisitor<'a> {
|
|
||||||
entries: &'a mut BTreeMap<String, OptionField>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Visit for SerializeVisitor<'_> {
|
|
||||||
fn record_set(&mut self, name: &str, set: OptionSet) {
|
|
||||||
// Collect the entries of the set.
|
|
||||||
let mut entries = BTreeMap::new();
|
|
||||||
let mut visitor = SerializeVisitor {
|
|
||||||
entries: &mut entries,
|
|
||||||
};
|
|
||||||
set.record(&mut visitor);
|
|
||||||
|
|
||||||
// Insert the set into the entries.
|
|
||||||
for (key, value) in entries {
|
|
||||||
self.entries.insert(format!("{name}.{key}"), value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn record_field(&mut self, name: &str, field: OptionField) {
|
|
||||||
self.entries.insert(name.to_string(), field);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Serialize for OptionSet {
|
|
||||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
|
||||||
where
|
|
||||||
S: Serializer,
|
|
||||||
{
|
|
||||||
let mut entries = BTreeMap::new();
|
|
||||||
let mut visitor = SerializeVisitor {
|
|
||||||
entries: &mut entries,
|
|
||||||
};
|
|
||||||
self.record(&mut visitor);
|
|
||||||
entries.serialize(serializer)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Debug for OptionSet {
|
impl Debug for OptionSet {
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||||
Display::fmt(self, f)
|
Display::fmt(self, f)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Eq, PartialEq, Clone, Serialize)]
|
#[derive(Debug, Eq, PartialEq, Clone)]
|
||||||
|
#[cfg_attr(feature = "serde", derive(::serde::Serialize))]
|
||||||
pub struct OptionField {
|
pub struct OptionField {
|
||||||
pub doc: &'static str,
|
pub doc: &'static str,
|
||||||
/// Ex) `"false"`
|
/// Ex) `"false"`
|
||||||
|
@ -402,7 +362,8 @@ pub struct OptionField {
|
||||||
pub deprecated: Option<Deprecated>,
|
pub deprecated: Option<Deprecated>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Eq, PartialEq, Serialize)]
|
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||||
|
#[cfg_attr(feature = "serde", derive(::serde::Serialize))]
|
||||||
pub struct Deprecated {
|
pub struct Deprecated {
|
||||||
pub since: Option<&'static str>,
|
pub since: Option<&'static str>,
|
||||||
pub message: Option<&'static str>,
|
pub message: Option<&'static str>,
|
||||||
|
@ -432,3 +393,48 @@ impl Display for OptionField {
|
||||||
writeln!(f, "Example usage:\n```toml\n{}\n```", self.example)
|
writeln!(f, "Example usage:\n```toml\n{}\n```", self.example)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "serde")]
|
||||||
|
mod serde {
|
||||||
|
use super::{OptionField, OptionSet, Visit};
|
||||||
|
use serde::{Serialize, Serializer};
|
||||||
|
use std::collections::BTreeMap;
|
||||||
|
|
||||||
|
impl Serialize for OptionSet {
|
||||||
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
|
where
|
||||||
|
S: Serializer,
|
||||||
|
{
|
||||||
|
let mut entries = BTreeMap::new();
|
||||||
|
let mut visitor = SerializeVisitor {
|
||||||
|
entries: &mut entries,
|
||||||
|
};
|
||||||
|
self.record(&mut visitor);
|
||||||
|
entries.serialize(serializer)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct SerializeVisitor<'a> {
|
||||||
|
entries: &'a mut BTreeMap<String, OptionField>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Visit for SerializeVisitor<'_> {
|
||||||
|
fn record_set(&mut self, name: &str, set: OptionSet) {
|
||||||
|
// Collect the entries of the set.
|
||||||
|
let mut entries = BTreeMap::new();
|
||||||
|
let mut visitor = SerializeVisitor {
|
||||||
|
entries: &mut entries,
|
||||||
|
};
|
||||||
|
set.record(&mut visitor);
|
||||||
|
|
||||||
|
// Insert the set into the entries.
|
||||||
|
for (key, value) in entries {
|
||||||
|
self.entries.insert(format!("{name}.{key}"), value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn record_field(&mut self, name: &str, field: OptionField) {
|
||||||
|
self.entries.insert(name.to_string(), field);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -60,6 +60,7 @@ impl PythonVersion {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const fn latest_ty() -> Self {
|
pub const fn latest_ty() -> Self {
|
||||||
|
// Make sure to update the default value for `EnvironmentOptions::python_version` when bumping this version.
|
||||||
Self::PY313
|
Self::PY313
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,7 @@ ruff_formatter = { workspace = true }
|
||||||
ruff_graph = { workspace = true, features = ["serde", "schemars"] }
|
ruff_graph = { workspace = true, features = ["serde", "schemars"] }
|
||||||
ruff_linter = { workspace = true }
|
ruff_linter = { workspace = true }
|
||||||
ruff_macros = { workspace = true }
|
ruff_macros = { workspace = true }
|
||||||
|
ruff_options_metadata = { workspace = true }
|
||||||
ruff_python_ast = { workspace = true }
|
ruff_python_ast = { workspace = true }
|
||||||
ruff_python_formatter = { workspace = true, features = ["serde"] }
|
ruff_python_formatter = { workspace = true, features = ["serde"] }
|
||||||
ruff_python_semantic = { workspace = true, features = ["serde"] }
|
ruff_python_semantic = { workspace = true, features = ["serde"] }
|
||||||
|
|
|
@ -3,7 +3,6 @@ pub mod options;
|
||||||
pub mod pyproject;
|
pub mod pyproject;
|
||||||
pub mod resolver;
|
pub mod resolver;
|
||||||
|
|
||||||
pub mod options_base;
|
|
||||||
mod settings;
|
mod settings;
|
||||||
|
|
||||||
pub use settings::{FileResolverSettings, FormatterSettings, Settings};
|
pub use settings::{FileResolverSettings, FormatterSettings, Settings};
|
||||||
|
|
|
@ -6,7 +6,6 @@ use std::collections::{BTreeMap, BTreeSet};
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use strum::IntoEnumIterator;
|
use strum::IntoEnumIterator;
|
||||||
|
|
||||||
use crate::options_base::{OptionsMetadata, Visit};
|
|
||||||
use crate::settings::LineEnding;
|
use crate::settings::LineEnding;
|
||||||
use ruff_formatter::IndentStyle;
|
use ruff_formatter::IndentStyle;
|
||||||
use ruff_graph::Direction;
|
use ruff_graph::Direction;
|
||||||
|
@ -32,6 +31,7 @@ use ruff_linter::settings::types::{
|
||||||
};
|
};
|
||||||
use ruff_linter::{warn_user_once, RuleSelector};
|
use ruff_linter::{warn_user_once, RuleSelector};
|
||||||
use ruff_macros::{CombineOptions, OptionsMetadata};
|
use ruff_macros::{CombineOptions, OptionsMetadata};
|
||||||
|
use ruff_options_metadata::{OptionsMetadata, Visit};
|
||||||
use ruff_python_ast::name::Name;
|
use ruff_python_ast::name::Name;
|
||||||
use ruff_python_formatter::{DocstringCodeLineWidth, QuoteStyle};
|
use ruff_python_formatter::{DocstringCodeLineWidth, QuoteStyle};
|
||||||
use ruff_python_semantic::NameImports;
|
use ruff_python_semantic::NameImports;
|
||||||
|
|
220
crates/ty/docs/configuration.md
Normal file
220
crates/ty/docs/configuration.md
Normal file
|
@ -0,0 +1,220 @@
|
||||||
|
# Configuration
|
||||||
|
#### [`respect-ignore-files`]
|
||||||
|
|
||||||
|
Whether to automatically exclude files that are ignored by `.ignore`,
|
||||||
|
`.gitignore`, `.git/info/exclude`, and global `gitignore` files.
|
||||||
|
Enabled by default.
|
||||||
|
|
||||||
|
**Default value**: `true`
|
||||||
|
|
||||||
|
**Type**: `bool`
|
||||||
|
|
||||||
|
**Example usage** (`pyproject.toml`):
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[tool.ty]
|
||||||
|
respect-ignore-files = false
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
#### [`rules`]
|
||||||
|
|
||||||
|
Configures the enabled rules and their severity.
|
||||||
|
|
||||||
|
See [the rules documentation](https://github.com/astral-sh/ruff/blob/main/crates/ty/docs/rules.md) for a list of all available rules.
|
||||||
|
|
||||||
|
Valid severities are:
|
||||||
|
|
||||||
|
* `ignore`: Disable the rule.
|
||||||
|
* `warn`: Enable the rule and create a warning diagnostic.
|
||||||
|
* `error`: Enable the rule and create an error diagnostic.
|
||||||
|
ty will exit with a non-zero code if any error diagnostics are emitted.
|
||||||
|
|
||||||
|
**Default value**: `{...}`
|
||||||
|
|
||||||
|
**Type**: `dict[RuleName, "ignore" | "warn" | "error"]`
|
||||||
|
|
||||||
|
**Example usage** (`pyproject.toml`):
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[tool.ty.rules]
|
||||||
|
possibly-unresolved-reference = "warn"
|
||||||
|
division-by-zero = "ignore"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## `environment`
|
||||||
|
|
||||||
|
#### [`extra-paths`]
|
||||||
|
|
||||||
|
List of user-provided paths that should take first priority in the module resolution.
|
||||||
|
Examples in other type checkers are mypy's `MYPYPATH` environment variable,
|
||||||
|
or pyright's `stubPath` configuration setting.
|
||||||
|
|
||||||
|
**Default value**: `[]`
|
||||||
|
|
||||||
|
**Type**: `list[str]`
|
||||||
|
|
||||||
|
**Example usage** (`pyproject.toml`):
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[tool.ty.environment]
|
||||||
|
extra-paths = ["~/shared/my-search-path"]
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
#### [`python`]
|
||||||
|
|
||||||
|
Path to the Python installation from which ty resolves type information and third-party dependencies.
|
||||||
|
|
||||||
|
ty will search in the path's `site-packages` directories for type information and
|
||||||
|
third-party imports.
|
||||||
|
|
||||||
|
This option is commonly used to specify the path to a virtual environment.
|
||||||
|
|
||||||
|
**Default value**: `null`
|
||||||
|
|
||||||
|
**Type**: `str`
|
||||||
|
|
||||||
|
**Example usage** (`pyproject.toml`):
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[tool.ty.environment]
|
||||||
|
python = "./.venv"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
#### [`python-platform`]
|
||||||
|
|
||||||
|
Specifies the target platform that will be used to analyze the source code.
|
||||||
|
If specified, ty will understand conditions based on comparisons with `sys.platform`, such
|
||||||
|
as are commonly found in typeshed to reflect the differing contents of the standard library across platforms.
|
||||||
|
|
||||||
|
If no platform is specified, ty will use the current platform:
|
||||||
|
- `win32` for Windows
|
||||||
|
- `darwin` for macOS
|
||||||
|
- `android` for Android
|
||||||
|
- `ios` for iOS
|
||||||
|
- `linux` for everything else
|
||||||
|
|
||||||
|
**Default value**: `<current-platform>`
|
||||||
|
|
||||||
|
**Type**: `"win32" | "darwin" | "android" | "ios" | "linux" | str`
|
||||||
|
|
||||||
|
**Example usage** (`pyproject.toml`):
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[tool.ty.environment]
|
||||||
|
# Tailor type stubs and conditionalized type definitions to windows.
|
||||||
|
python-platform = "win32"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
#### [`python-version`]
|
||||||
|
|
||||||
|
Specifies the version of Python that will be used to analyze the source code.
|
||||||
|
The version should be specified as a string in the format `M.m` where `M` is the major version
|
||||||
|
and `m` is the minor (e.g. `"3.0"` or `"3.6"`).
|
||||||
|
If a version is provided, ty will generate errors if the source code makes use of language features
|
||||||
|
that are not supported in that version.
|
||||||
|
It will also understand conditionals based on comparisons with `sys.version_info`, such
|
||||||
|
as are commonly found in typeshed to reflect the differing contents of the standard
|
||||||
|
library across Python versions.
|
||||||
|
|
||||||
|
**Default value**: `"3.13"`
|
||||||
|
|
||||||
|
**Type**: `"3.7" | "3.8" | "3.9" | "3.10" | "3.11" | "3.12" | "3.13" | <major>.<minor>`
|
||||||
|
|
||||||
|
**Example usage** (`pyproject.toml`):
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[tool.ty.environment]
|
||||||
|
python-version = "3.12"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
#### [`typeshed`]
|
||||||
|
|
||||||
|
Optional path to a "typeshed" directory on disk for us to use for standard-library types.
|
||||||
|
If this is not provided, we will fallback to our vendored typeshed stubs for the stdlib,
|
||||||
|
bundled as a zip file in the binary
|
||||||
|
|
||||||
|
**Default value**: `null`
|
||||||
|
|
||||||
|
**Type**: `str`
|
||||||
|
|
||||||
|
**Example usage** (`pyproject.toml`):
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[tool.ty.environment]
|
||||||
|
typeshed = "/path/to/custom/typeshed"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## `src`
|
||||||
|
|
||||||
|
#### [`root`]
|
||||||
|
|
||||||
|
The root(s) of the project, used for finding first-party modules.
|
||||||
|
|
||||||
|
**Default value**: `[".", "./src"]`
|
||||||
|
|
||||||
|
**Type**: `list[str]`
|
||||||
|
|
||||||
|
**Example usage** (`pyproject.toml`):
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[tool.ty.src]
|
||||||
|
root = ["./app"]
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## `terminal`
|
||||||
|
|
||||||
|
#### [`error-on-warning`]
|
||||||
|
|
||||||
|
Use exit code 1 if there are any warning-level diagnostics.
|
||||||
|
|
||||||
|
Defaults to `false`.
|
||||||
|
|
||||||
|
**Default value**: `false`
|
||||||
|
|
||||||
|
**Type**: `bool`
|
||||||
|
|
||||||
|
**Example usage** (`pyproject.toml`):
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[tool.ty.terminal]
|
||||||
|
# Error if ty emits any warning-level diagnostics.
|
||||||
|
error-on-warning = true
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
#### [`output-format`]
|
||||||
|
|
||||||
|
The format to use for printing diagnostic messages.
|
||||||
|
|
||||||
|
Defaults to `full`.
|
||||||
|
|
||||||
|
**Default value**: `full`
|
||||||
|
|
||||||
|
**Type**: `full | concise`
|
||||||
|
|
||||||
|
**Example usage** (`pyproject.toml`):
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[tool.ty.terminal]
|
||||||
|
output-format = "concise"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
|
@ -15,6 +15,7 @@ license.workspace = true
|
||||||
ruff_cache = { workspace = true }
|
ruff_cache = { workspace = true }
|
||||||
ruff_db = { workspace = true, features = ["cache", "serde"] }
|
ruff_db = { workspace = true, features = ["cache", "serde"] }
|
||||||
ruff_macros = { workspace = true }
|
ruff_macros = { workspace = true }
|
||||||
|
ruff_options_metadata = { workspace = true }
|
||||||
ruff_python_ast = { workspace = true, features = ["serde"] }
|
ruff_python_ast = { workspace = true, features = ["serde"] }
|
||||||
ruff_python_formatter = { workspace = true, optional = true }
|
ruff_python_formatter = { workspace = true, optional = true }
|
||||||
ruff_text_size = { workspace = true }
|
ruff_text_size = { workspace = true }
|
||||||
|
@ -44,11 +45,7 @@ insta = { workspace = true, features = ["redactions", "ron"] }
|
||||||
[features]
|
[features]
|
||||||
default = ["zstd"]
|
default = ["zstd"]
|
||||||
deflate = ["ty_vendored/deflate"]
|
deflate = ["ty_vendored/deflate"]
|
||||||
schemars = [
|
schemars = ["dep:schemars", "ruff_db/schemars", "ty_python_semantic/schemars"]
|
||||||
"dep:schemars",
|
|
||||||
"ruff_db/schemars",
|
|
||||||
"ty_python_semantic/schemars",
|
|
||||||
]
|
|
||||||
zstd = ["ty_vendored/zstd"]
|
zstd = ["ty_vendored/zstd"]
|
||||||
format = ["ruff_python_formatter"]
|
format = ["ruff_python_formatter"]
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@ use ty_python_semantic::ProgramSettings;
|
||||||
use crate::combine::Combine;
|
use crate::combine::Combine;
|
||||||
use crate::metadata::pyproject::{Project, PyProject, PyProjectError, ResolveRequiresPythonError};
|
use crate::metadata::pyproject::{Project, PyProject, PyProjectError, ResolveRequiresPythonError};
|
||||||
use crate::metadata::value::ValueSource;
|
use crate::metadata::value::ValueSource;
|
||||||
use options::Options;
|
pub use options::Options;
|
||||||
use options::TyTomlError;
|
use options::TyTomlError;
|
||||||
|
|
||||||
mod configuration_file;
|
mod configuration_file;
|
||||||
|
|
|
@ -3,7 +3,7 @@ use crate::Db;
|
||||||
use ruff_db::diagnostic::{Annotation, Diagnostic, DiagnosticFormat, DiagnosticId, Severity, Span};
|
use ruff_db::diagnostic::{Annotation, Diagnostic, DiagnosticFormat, DiagnosticId, Severity, Span};
|
||||||
use ruff_db::files::system_path_to_file;
|
use ruff_db::files::system_path_to_file;
|
||||||
use ruff_db::system::{System, SystemPath};
|
use ruff_db::system::{System, SystemPath};
|
||||||
use ruff_macros::Combine;
|
use ruff_macros::{Combine, OptionsMetadata};
|
||||||
use ruff_python_ast::PythonVersion;
|
use ruff_python_ast::PythonVersion;
|
||||||
use rustc_hash::FxHashMap;
|
use rustc_hash::FxHashMap;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
@ -14,25 +14,57 @@ use ty_python_semantic::{ProgramSettings, PythonPath, PythonPlatform, SearchPath
|
||||||
|
|
||||||
use super::settings::{Settings, TerminalSettings};
|
use super::settings::{Settings, TerminalSettings};
|
||||||
|
|
||||||
/// The options for the project.
|
#[derive(
|
||||||
#[derive(Debug, Default, Clone, PartialEq, Eq, Combine, Serialize, Deserialize)]
|
Debug, Default, Clone, PartialEq, Eq, Combine, Serialize, Deserialize, OptionsMetadata,
|
||||||
|
)]
|
||||||
#[serde(rename_all = "kebab-case", deny_unknown_fields)]
|
#[serde(rename_all = "kebab-case", deny_unknown_fields)]
|
||||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||||
pub struct Options {
|
pub struct Options {
|
||||||
/// Configures the type checking environment.
|
/// Configures the type checking environment.
|
||||||
|
#[option_group]
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
pub environment: Option<EnvironmentOptions>,
|
pub environment: Option<EnvironmentOptions>,
|
||||||
|
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
#[option_group]
|
||||||
pub src: Option<SrcOptions>,
|
pub src: Option<SrcOptions>,
|
||||||
|
|
||||||
/// Configures the enabled lints and their severity.
|
/// Configures the enabled rules and their severity.
|
||||||
|
///
|
||||||
|
/// See [the rules documentation](https://github.com/astral-sh/ruff/blob/main/crates/ty/docs/rules.md) for a list of all available rules.
|
||||||
|
///
|
||||||
|
/// Valid severities are:
|
||||||
|
///
|
||||||
|
/// * `ignore`: Disable the rule.
|
||||||
|
/// * `warn`: Enable the rule and create a warning diagnostic.
|
||||||
|
/// * `error`: Enable the rule and create an error diagnostic.
|
||||||
|
/// ty will exit with a non-zero code if any error diagnostics are emitted.
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
#[option(
|
||||||
|
default = r#"{...}"#,
|
||||||
|
value_type = r#"dict[RuleName, "ignore" | "warn" | "error"]"#,
|
||||||
|
example = r#"
|
||||||
|
[tool.ty.rules]
|
||||||
|
possibly-unresolved-reference = "warn"
|
||||||
|
division-by-zero = "ignore"
|
||||||
|
"#
|
||||||
|
)]
|
||||||
pub rules: Option<Rules>,
|
pub rules: Option<Rules>,
|
||||||
|
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
#[option_group]
|
||||||
pub terminal: Option<TerminalOptions>,
|
pub terminal: Option<TerminalOptions>,
|
||||||
|
|
||||||
|
/// Whether to automatically exclude files that are ignored by `.ignore`,
|
||||||
|
/// `.gitignore`, `.git/info/exclude`, and global `gitignore` files.
|
||||||
|
/// Enabled by default.
|
||||||
|
#[option(
|
||||||
|
default = r#"true"#,
|
||||||
|
value_type = r#"bool"#,
|
||||||
|
example = r#"
|
||||||
|
respect-ignore-files = false
|
||||||
|
"#
|
||||||
|
)]
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
pub respect_ignore_files: Option<bool>,
|
pub respect_ignore_files: Option<bool>,
|
||||||
}
|
}
|
||||||
|
@ -226,22 +258,33 @@ impl Options {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Default, Clone, Eq, PartialEq, Combine, Serialize, Deserialize)]
|
#[derive(
|
||||||
|
Debug, Default, Clone, Eq, PartialEq, Combine, Serialize, Deserialize, OptionsMetadata,
|
||||||
|
)]
|
||||||
#[serde(rename_all = "kebab-case", deny_unknown_fields)]
|
#[serde(rename_all = "kebab-case", deny_unknown_fields)]
|
||||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||||
pub struct EnvironmentOptions {
|
pub struct EnvironmentOptions {
|
||||||
/// Specifies the version of Python that will be used to analyze the source code.
|
/// Specifies the version of Python that will be used to analyze the source code.
|
||||||
/// The version should be specified as a string in the format `M.m` where `M` is the major version
|
/// The version should be specified as a string in the format `M.m` where `M` is the major version
|
||||||
/// and `m` is the minor (e.g. "3.0" or "3.6").
|
/// and `m` is the minor (e.g. `"3.0"` or `"3.6"`).
|
||||||
/// If a version is provided, ty will generate errors if the source code makes use of language features
|
/// If a version is provided, ty will generate errors if the source code makes use of language features
|
||||||
/// that are not supported in that version.
|
/// that are not supported in that version.
|
||||||
/// It will also tailor its use of type stub files, which conditionalizes type definitions based on the version.
|
/// It will also understand conditionals based on comparisons with `sys.version_info`, such
|
||||||
|
/// as are commonly found in typeshed to reflect the differing contents of the standard
|
||||||
|
/// library across Python versions.
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
#[option(
|
||||||
|
default = r#""3.13""#,
|
||||||
|
value_type = r#""3.7" | "3.8" | "3.9" | "3.10" | "3.11" | "3.12" | "3.13" | <major>.<minor>"#,
|
||||||
|
example = r#"
|
||||||
|
python-version = "3.12"
|
||||||
|
"#
|
||||||
|
)]
|
||||||
pub python_version: Option<RangedValue<PythonVersion>>,
|
pub python_version: Option<RangedValue<PythonVersion>>,
|
||||||
|
|
||||||
/// Specifies the target platform that will be used to analyze the source code.
|
/// Specifies the target platform that will be used to analyze the source code.
|
||||||
/// If specified, ty will tailor its use of type stub files,
|
/// If specified, ty will understand conditions based on comparisons with `sys.platform`, such
|
||||||
/// which conditionalize type definitions based on the platform.
|
/// as are commonly found in typeshed to reflect the differing contents of the standard library across platforms.
|
||||||
///
|
///
|
||||||
/// If no platform is specified, ty will use the current platform:
|
/// If no platform is specified, ty will use the current platform:
|
||||||
/// - `win32` for Windows
|
/// - `win32` for Windows
|
||||||
|
@ -250,18 +293,40 @@ pub struct EnvironmentOptions {
|
||||||
/// - `ios` for iOS
|
/// - `ios` for iOS
|
||||||
/// - `linux` for everything else
|
/// - `linux` for everything else
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
#[option(
|
||||||
|
default = r#"<current-platform>"#,
|
||||||
|
value_type = r#""win32" | "darwin" | "android" | "ios" | "linux" | str"#,
|
||||||
|
example = r#"
|
||||||
|
# Tailor type stubs and conditionalized type definitions to windows.
|
||||||
|
python-platform = "win32"
|
||||||
|
"#
|
||||||
|
)]
|
||||||
pub python_platform: Option<RangedValue<PythonPlatform>>,
|
pub python_platform: Option<RangedValue<PythonPlatform>>,
|
||||||
|
|
||||||
/// List of user-provided paths that should take first priority in the module resolution.
|
/// List of user-provided paths that should take first priority in the module resolution.
|
||||||
/// Examples in other type checkers are mypy's MYPYPATH environment variable,
|
/// Examples in other type checkers are mypy's `MYPYPATH` environment variable,
|
||||||
/// or pyright's stubPath configuration setting.
|
/// or pyright's `stubPath` configuration setting.
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
#[option(
|
||||||
|
default = r#"[]"#,
|
||||||
|
value_type = "list[str]",
|
||||||
|
example = r#"
|
||||||
|
extra-paths = ["~/shared/my-search-path"]
|
||||||
|
"#
|
||||||
|
)]
|
||||||
pub extra_paths: Option<Vec<RelativePathBuf>>,
|
pub extra_paths: Option<Vec<RelativePathBuf>>,
|
||||||
|
|
||||||
/// Optional path to a "typeshed" directory on disk for us to use for standard-library types.
|
/// Optional path to a "typeshed" directory on disk for us to use for standard-library types.
|
||||||
/// If this is not provided, we will fallback to our vendored typeshed stubs for the stdlib,
|
/// If this is not provided, we will fallback to our vendored typeshed stubs for the stdlib,
|
||||||
/// bundled as a zip file in the binary
|
/// bundled as a zip file in the binary
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
#[option(
|
||||||
|
default = r#"null"#,
|
||||||
|
value_type = "str",
|
||||||
|
example = r#"
|
||||||
|
typeshed = "/path/to/custom/typeshed"
|
||||||
|
"#
|
||||||
|
)]
|
||||||
pub typeshed: Option<RelativePathBuf>,
|
pub typeshed: Option<RelativePathBuf>,
|
||||||
|
|
||||||
/// Path to the Python installation from which ty resolves type information and third-party dependencies.
|
/// Path to the Python installation from which ty resolves type information and third-party dependencies.
|
||||||
|
@ -271,15 +336,31 @@ pub struct EnvironmentOptions {
|
||||||
///
|
///
|
||||||
/// This option is commonly used to specify the path to a virtual environment.
|
/// This option is commonly used to specify the path to a virtual environment.
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
#[option(
|
||||||
|
default = r#"null"#,
|
||||||
|
value_type = "str",
|
||||||
|
example = r#"
|
||||||
|
python = "./.venv"
|
||||||
|
"#
|
||||||
|
)]
|
||||||
pub python: Option<RelativePathBuf>,
|
pub python: Option<RelativePathBuf>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Default, Clone, Eq, PartialEq, Combine, Serialize, Deserialize)]
|
#[derive(
|
||||||
|
Debug, Default, Clone, Eq, PartialEq, Combine, Serialize, Deserialize, OptionsMetadata,
|
||||||
|
)]
|
||||||
#[serde(rename_all = "kebab-case", deny_unknown_fields)]
|
#[serde(rename_all = "kebab-case", deny_unknown_fields)]
|
||||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||||
pub struct SrcOptions {
|
pub struct SrcOptions {
|
||||||
/// The root of the project, used for finding first-party modules.
|
/// The root(s) of the project, used for finding first-party modules.
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
#[option(
|
||||||
|
default = r#"[".", "./src"]"#,
|
||||||
|
value_type = "list[str]",
|
||||||
|
example = r#"
|
||||||
|
root = ["./app"]
|
||||||
|
"#
|
||||||
|
)]
|
||||||
pub root: Option<RelativePathBuf>,
|
pub root: Option<RelativePathBuf>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -301,7 +382,9 @@ impl FromIterator<(RangedValue<String>, RangedValue<Level>)> for Rules {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Default, Clone, Eq, PartialEq, Combine, Serialize, Deserialize)]
|
#[derive(
|
||||||
|
Debug, Default, Clone, Eq, PartialEq, Combine, Serialize, Deserialize, OptionsMetadata,
|
||||||
|
)]
|
||||||
#[serde(rename_all = "kebab-case", deny_unknown_fields)]
|
#[serde(rename_all = "kebab-case", deny_unknown_fields)]
|
||||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||||
pub struct TerminalOptions {
|
pub struct TerminalOptions {
|
||||||
|
@ -309,10 +392,25 @@ pub struct TerminalOptions {
|
||||||
///
|
///
|
||||||
/// Defaults to `full`.
|
/// Defaults to `full`.
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
#[option(
|
||||||
|
default = r#"full"#,
|
||||||
|
value_type = "full | concise",
|
||||||
|
example = r#"
|
||||||
|
output-format = "concise"
|
||||||
|
"#
|
||||||
|
)]
|
||||||
pub output_format: Option<RangedValue<DiagnosticFormat>>,
|
pub output_format: Option<RangedValue<DiagnosticFormat>>,
|
||||||
/// Use exit code 1 if there are any warning-level diagnostics.
|
/// Use exit code 1 if there are any warning-level diagnostics.
|
||||||
///
|
///
|
||||||
/// Defaults to `false`.
|
/// Defaults to `false`.
|
||||||
|
#[option(
|
||||||
|
default = r#"false"#,
|
||||||
|
value_type = "bool",
|
||||||
|
example = r#"
|
||||||
|
# Error if ty emits any warning-level diagnostics.
|
||||||
|
error-on-warning = true
|
||||||
|
"#
|
||||||
|
)]
|
||||||
pub error_on_warning: Option<bool>,
|
pub error_on_warning: Option<bool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
{
|
{
|
||||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||||
"title": "Options",
|
"title": "Options",
|
||||||
"description": "The options for the project.",
|
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
"environment": {
|
"environment": {
|
||||||
|
@ -16,13 +15,14 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"respect-ignore-files": {
|
"respect-ignore-files": {
|
||||||
|
"description": "Whether to automatically exclude files that are ignored by `.ignore`, `.gitignore`, `.git/info/exclude`, and global `gitignore` files. Enabled by default.",
|
||||||
"type": [
|
"type": [
|
||||||
"boolean",
|
"boolean",
|
||||||
"null"
|
"null"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"rules": {
|
"rules": {
|
||||||
"description": "Configures the enabled lints and their severity.",
|
"description": "Configures the enabled rules and their severity.\n\nSee [the rules documentation](https://github.com/astral-sh/ruff/blob/main/crates/ty/docs/rules.md) for a list of all available rules.\n\nValid severities are:\n\n* `ignore`: Disable the rule. * `warn`: Enable the rule and create a warning diagnostic. * `error`: Enable the rule and create an error diagnostic. ty will exit with a non-zero code if any error diagnostics are emitted.",
|
||||||
"anyOf": [
|
"anyOf": [
|
||||||
{
|
{
|
||||||
"$ref": "#/definitions/Rules"
|
"$ref": "#/definitions/Rules"
|
||||||
|
@ -78,7 +78,7 @@
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
"extra-paths": {
|
"extra-paths": {
|
||||||
"description": "List of user-provided paths that should take first priority in the module resolution. Examples in other type checkers are mypy's MYPYPATH environment variable, or pyright's stubPath configuration setting.",
|
"description": "List of user-provided paths that should take first priority in the module resolution. Examples in other type checkers are mypy's `MYPYPATH` environment variable, or pyright's `stubPath` configuration setting.",
|
||||||
"type": [
|
"type": [
|
||||||
"array",
|
"array",
|
||||||
"null"
|
"null"
|
||||||
|
@ -95,7 +95,7 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"python-platform": {
|
"python-platform": {
|
||||||
"description": "Specifies the target platform that will be used to analyze the source code. If specified, ty will tailor its use of type stub files, which conditionalize type definitions based on the platform.\n\nIf no platform is specified, ty will use the current platform: - `win32` for Windows - `darwin` for macOS - `android` for Android - `ios` for iOS - `linux` for everything else",
|
"description": "Specifies the target platform that will be used to analyze the source code. If specified, ty will understand conditions based on comparisons with `sys.platform`, such as are commonly found in typeshed to reflect the differing contents of the standard library across platforms.\n\nIf no platform is specified, ty will use the current platform: - `win32` for Windows - `darwin` for macOS - `android` for Android - `ios` for iOS - `linux` for everything else",
|
||||||
"anyOf": [
|
"anyOf": [
|
||||||
{
|
{
|
||||||
"$ref": "#/definitions/PythonPlatform"
|
"$ref": "#/definitions/PythonPlatform"
|
||||||
|
@ -106,7 +106,7 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"python-version": {
|
"python-version": {
|
||||||
"description": "Specifies the version of Python that will be used to analyze the source code. The version should be specified as a string in the format `M.m` where `M` is the major version and `m` is the minor (e.g. \"3.0\" or \"3.6\"). If a version is provided, ty will generate errors if the source code makes use of language features that are not supported in that version. It will also tailor its use of type stub files, which conditionalizes type definitions based on the version.",
|
"description": "Specifies the version of Python that will be used to analyze the source code. The version should be specified as a string in the format `M.m` where `M` is the major version and `m` is the minor (e.g. `\"3.0\"` or `\"3.6\"`). If a version is provided, ty will generate errors if the source code makes use of language features that are not supported in that version. It will also understand conditionals based on comparisons with `sys.version_info`, such as are commonly found in typeshed to reflect the differing contents of the standard library across Python versions.",
|
||||||
"anyOf": [
|
"anyOf": [
|
||||||
{
|
{
|
||||||
"$ref": "#/definitions/PythonVersion"
|
"$ref": "#/definitions/PythonVersion"
|
||||||
|
@ -839,7 +839,7 @@
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
"root": {
|
"root": {
|
||||||
"description": "The root of the project, used for finding first-party modules.",
|
"description": "The root(s) of the project, used for finding first-party modules.",
|
||||||
"type": [
|
"type": [
|
||||||
"string",
|
"string",
|
||||||
"null"
|
"null"
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue