Show per-cell diffs when analyzing notebooks over stdin (#7789)

## Summary

The implementation here differs from the non-`stdin` version -- this is
now more consistent.

## Test Plan

```
❯ cat Untitled.ipynb | cargo run -p ruff_cli -- check --stdin-filename Untitled.ipynb --diff -n
    Finished dev [unoptimized + debuginfo] target(s) in 0.11s
     Running `target/debug/ruff check --stdin-filename Untitled.ipynb --diff -n`
--- Untitled.ipynb:cell 2
+++ Untitled.ipynb:cell 2
@@ -1 +0,0 @@
-import os
--- Untitled.ipynb:cell 4
+++ Untitled.ipynb:cell 4
@@ -1 +0,0 @@
-import sys
```
This commit is contained in:
Charlie Marsh 2023-10-04 09:58:07 -04:00 committed by GitHub
parent 600471e45f
commit e674e87d1b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -428,14 +428,18 @@ pub(crate) fn lint_stdin(
flags::FixMode::Diff => {
// But only write a diff if it's non-empty.
if !fixed.is_empty() {
match transformed.as_ref() {
SourceKind::Python(_) => {
let text_diff = TextDiff::from_lines(
source_kind.source_code(),
transformed.source_code(),
);
let mut unified_diff = text_diff.unified_diff();
if let Some(path) = path {
unified_diff
.header(&fs::relativize_path(path), &fs::relativize_path(path));
unified_diff.header(
&fs::relativize_path(path),
&fs::relativize_path(path),
);
}
let mut stdout = io::stdout().lock();
@ -443,6 +447,60 @@ pub(crate) fn lint_stdin(
stdout.write_all(b"\n")?;
stdout.flush()?;
}
SourceKind::IpyNotebook(dst_notebook) => {
let src_notebook = source_kind.as_ipy_notebook().unwrap();
let mut stdout = io::stdout().lock();
// Cell indices are 1-based.
for ((idx, src_cell), dest_cell) in (1u32..)
.zip(src_notebook.cells().iter())
.zip(dst_notebook.cells().iter())
{
let (Cell::Code(src_code_cell), Cell::Code(dest_code_cell)) =
(src_cell, dest_cell)
else {
continue;
};
let src_source_code = src_code_cell.source.to_string();
let dest_source_code = dest_code_cell.source.to_string();
let text_diff =
TextDiff::from_lines(&src_source_code, &dest_source_code);
let mut unified_diff = text_diff.unified_diff();
// Jupyter notebook cells don't necessarily have a newline
// at the end. For example,
//
// ```python
// print("hello")
// ```
//
// For a cell containing the above code, there'll only be one line,
// and it won't have a newline at the end. If it did, there'd be
// two lines, and the second line would be empty:
//
// ```python
// print("hello")
//
// ```
unified_diff.missing_newline_hint(false);
if let Some(path) = path {
unified_diff.header(
&format!("{}:cell {}", &fs::relativize_path(path), idx),
&format!("{}:cell {}", &fs::relativize_path(path), idx),
);
} else {
unified_diff
.header(&format!("cell {idx}"), &format!("cell {idx}"));
};
unified_diff.to_writer(&mut stdout)?;
}
stdout.write_all(b"\n")?;
stdout.flush()?;
}
}
}
}
flags::FixMode::Generate => {}
}