Skip to content

Commit

Permalink
Workaround Even Better TOML crash related to allOf (#15992)
Browse files Browse the repository at this point in the history
## Summary

Fixes #15978

Even Better TOML doesn't support `allOf` well. In fact, it just crashes.

This PR works around this limitation by avoid using `allOf` in the
automatically
derived schema for the docstring formatting setting. 

### Alternatives

schemars introduces `allOf` whenver it sees a `$ref` alongside other
object properties
because this is no longer valid according to Draft 7. We could replace
the
visitor performing the rewrite but I prefer not to because replacing
`allOf` with `oneOf`
is only valid for objects that don't have any other `oneOf` or `anyOf`
schema.

## Test Plan


https://github.com/user-attachments/assets/25d73b2a-fee1-4ba6-9ffe-869b2c3bc64e
  • Loading branch information
MichaReiser authored Feb 6, 2025
1 parent b66cc94 commit 7cac0da
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 28 deletions.
57 changes: 39 additions & 18 deletions crates/ruff_python_formatter/src/options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -374,12 +374,15 @@ impl fmt::Display for DocstringCode {
}

#[derive(Copy, Clone, Default, Eq, PartialEq, CacheKey)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "serde", serde(rename_all = "lowercase"))]
#[cfg_attr(feature = "serde", serde(untagged))]
#[cfg_attr(
feature = "serde",
derive(serde::Serialize, serde::Deserialize),
serde(untagged, rename_all = "lowercase")
)]
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
pub enum DocstringCodeLineWidth {
/// Wrap docstring code examples at a fixed line width.
#[cfg_attr(feature = "schemars", schemars(schema_with = "schema::fixed"))]
Fixed(LineWidth),

/// Respect the line length limit setting for the surrounding Python code.
Expand All @@ -388,27 +391,45 @@ pub enum DocstringCodeLineWidth {
feature = "serde",
serde(deserialize_with = "deserialize_docstring_code_line_width_dynamic")
)]
#[cfg_attr(feature = "schemars", schemars(with = "DynamicSchema"))]
#[cfg_attr(feature = "schemars", schemars(schema_with = "schema::dynamic"))]
Dynamic,
}

/// A dummy type that is used to generate a schema for `DocstringCodeLineWidth::Dynamic`.
#[cfg(feature = "schemars")]
struct DynamicSchema;

#[cfg(feature = "schemars")]
impl schemars::JsonSchema for DynamicSchema {
fn schema_name() -> String {
"Dynamic".to_string()
}

fn json_schema(_: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema {
schemars::schema::SchemaObject {
instance_type: Some(schemars::schema::InstanceType::String.into()),
mod schema {
use ruff_formatter::LineWidth;
use schemars::gen::SchemaGenerator;
use schemars::schema::{Metadata, Schema, SubschemaValidation};

/// A dummy type that is used to generate a schema for `DocstringCodeLineWidth::Dynamic`.
pub(super) fn dynamic(_: &mut SchemaGenerator) -> Schema {
Schema::Object(schemars::schema::SchemaObject {
const_value: Some("dynamic".to_string().into()),
..Default::default()
}
.into()
})
}

// We use a manual schema for `fixed` even thought it isn't strictly necessary according to the
// JSON schema specification to work around a bug in Even Better TOML with `allOf`.
// https://github.com/astral-sh/ruff/issues/15978#issuecomment-2639547101
//
// The only difference to the automatically derived schema is that we use `oneOf` instead of
// `allOf`. There's no semantic difference between `allOf` and `oneOf` for single element lists.
pub(super) fn fixed(gen: &mut SchemaGenerator) -> Schema {
let schema = gen.subschema_for::<LineWidth>();
Schema::Object(schemars::schema::SchemaObject {
metadata: Some(Box::new(Metadata {
description: Some(
"Wrap docstring code examples at a fixed line width.".to_string(),
),
..Metadata::default()
})),
subschemas: Some(Box::new(SubschemaValidation {
one_of: Some(vec![schema]),
..SubschemaValidation::default()
})),
..Default::default()
})
}
}

Expand Down
12 changes: 2 additions & 10 deletions ruff.schema.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 7cac0da

Please sign in to comment.