diff --git a/crates/ruff/resources/test/fixtures/jupyter/no_cell_id.ipynb b/crates/ruff/resources/test/fixtures/jupyter/no_cell_id.ipynb new file mode 100644 index 0000000000000..ea9e9e654af2b --- /dev/null +++ b/crates/ruff/resources/test/fixtures/jupyter/no_cell_id.ipynb @@ -0,0 +1,37 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import math\n", + "import os\n", + "\n", + "math.pi" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python (ruff)", + "language": "python", + "name": "ruff" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.3" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/crates/ruff/src/jupyter/notebook.rs b/crates/ruff/src/jupyter/notebook.rs index 018dc2d864307..144fa948c4149 100644 --- a/crates/ruff/src/jupyter/notebook.rs +++ b/crates/ruff/src/jupyter/notebook.rs @@ -477,8 +477,10 @@ mod tests { use crate::jupyter::schema::Cell; use crate::jupyter::Notebook; use crate::registry::Rule; + use crate::source_kind::SourceKind; use crate::test::{ - read_jupyter_notebook, test_notebook_path, test_resource_path, TestedNotebook, + read_jupyter_notebook, test_contents, test_notebook_path, test_resource_path, + TestedNotebook, }; use crate::{assert_messages, settings}; @@ -659,4 +661,22 @@ print("after empty cells") Ok(()) } + + #[test] + fn test_no_cell_id() -> Result<()> { + let path = "no_cell_id.ipynb".to_string(); + let source_notebook = read_jupyter_notebook(path.as_ref())?; + let source_kind = SourceKind::Jupyter(source_notebook); + let (_, transformed) = test_contents( + &source_kind, + path.as_ref(), + &settings::Settings::for_rule(Rule::UnusedImport), + ); + let linted_notebook = transformed.into_owned().expect_jupyter(); + let mut writer = Vec::new(); + linted_notebook.write_inner(&mut writer)?; + let actual = String::from_utf8(writer)?; + assert!(!actual.contains(r#""id":"#)); + Ok(()) + } } diff --git a/crates/ruff/src/jupyter/schema.rs b/crates/ruff/src/jupyter/schema.rs index b6f9ed3c47134..e466615feca52 100644 --- a/crates/ruff/src/jupyter/schema.rs +++ b/crates/ruff/src/jupyter/schema.rs @@ -150,6 +150,7 @@ pub struct CodeCell { /// Technically, id isn't required (it's not even present) in schema v4.0 through v4.4, but /// it's required in v4.5. Main issue is that pycharm creates notebooks without an id /// + #[serde(skip_serializing_if = "Option::is_none")] pub id: Option, /// Cell-level metadata. pub metadata: Value, diff --git a/crates/ruff/src/test.rs b/crates/ruff/src/test.rs index 7434a4ef45a82..5fa67c4eb74da 100644 --- a/crates/ruff/src/test.rs +++ b/crates/ruff/src/test.rs @@ -112,7 +112,7 @@ pub(crate) fn max_iterations() -> usize { /// A convenient wrapper around [`check_path`], that additionally /// asserts that autofixes converge after a fixed number of iterations. -fn test_contents<'a>( +pub(crate) fn test_contents<'a>( source_kind: &'a SourceKind, path: &Path, settings: &Settings,