Create ruff_notebook crate (#7039)

## Summary

This PR moves `ruff/jupyter` into its own `ruff_notebook` crate. Beyond
the move itself, there were a few challenges:

1. `ruff_notebook` relies on the source map abstraction. I've moved the
source map into `ruff_diagnostics`, since it doesn't have any
dependencies on its own and is used alongside diagnostics.
2. `ruff_notebook` has a couple tests for end-to-end linting and
autofixing. I had to leave these tests in `ruff` itself.
3. We had code in `ruff/jupyter` that relied on Python lexing, in order
to provide a more targeted error message in the event that a user saves
a `.py` file with a `.ipynb` extension. I removed this in order to avoid
a dependency on the parser, it felt like it wasn't worth retaining just
for that dependency.

## Test Plan

`cargo test`
This commit is contained in:
Charlie Marsh 2023-09-01 14:56:44 +01:00 committed by GitHub
parent 08e246764f
commit afcd00da56
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
48 changed files with 274 additions and 253 deletions

View file

@ -1,8 +1,8 @@
#![cfg_attr(target_family = "wasm", allow(dead_code))]
use std::fs::write;
use std::fs::{write, File};
use std::io;
use std::io::Write;
use std::io::{BufWriter, Write};
use std::ops::AddAssign;
#[cfg(unix)]
use std::os::unix::fs::PermissionsExt;
@ -16,7 +16,6 @@ use rustc_hash::FxHashMap;
use similar::TextDiff;
use thiserror::Error;
use ruff::jupyter::{Cell, Notebook, NotebookError};
use ruff::linter::{lint_fix, lint_only, FixTable, FixerResult, LinterResult};
use ruff::logging::DisplayParseError;
use ruff::message::Message;
@ -27,6 +26,7 @@ use ruff::source_kind::SourceKind;
use ruff::{fs, IOError, SyntaxError};
use ruff_diagnostics::Diagnostic;
use ruff_macros::CacheKey;
use ruff_notebook::{Cell, Notebook, NotebookError};
use ruff_python_ast::imports::ImportMap;
use ruff_python_ast::{PySourceType, SourceType, TomlSourceType};
use ruff_source_file::{LineIndex, SourceCode, SourceFileBuilder};
@ -243,7 +243,8 @@ pub(crate) fn lint_path(
write(path, transformed.as_bytes())?;
}
SourceKind::IpyNotebook(notebook) => {
notebook.write(path)?;
let mut writer = BufWriter::new(File::create(path)?);
notebook.write(&mut writer)?;
}
},
flags::FixMode::Diff => {
@ -565,8 +566,7 @@ impl From<&SourceExtractionError> for Diagnostic {
}
// Syntax errors.
SourceExtractionError::Notebook(
NotebookError::PythonSource(_)
| NotebookError::InvalidJson(_)
NotebookError::InvalidJson(_)
| NotebookError::InvalidSchema(_)
| NotebookError::InvalidFormat(_),
) => Diagnostic::new(