Compare commits

..

5 Commits

Author SHA1 Message Date
Charlie Marsh
22991e3e0e Bump version to 0.0.98 2022-11-03 10:09:33 -04:00
Charlie Marsh
242bdf86b1 Use ::ruff to ensure ruff imports come first 2022-11-03 10:09:28 -04:00
Charlie Marsh
a3f7de2257 Make --quiet more aggressive (#566) 2022-11-03 10:08:15 -04:00
Charlie Marsh
9f9cbb5520 Improve pyproject.toml examples in README.md 2022-11-03 09:33:17 -04:00
Charlie Marsh
937c83d57f Remove crates subdirectory (#563) 2022-11-03 09:19:54 -04:00
18 changed files with 218 additions and 100 deletions

View File

@@ -30,7 +30,7 @@ jobs:
uses: messense/maturin-action@v1
with:
target: x86_64
args: --release --out dist --sdist -m ./crates/${{ env.CRATE_NAME }}/Cargo.toml
args: --release --out dist --sdist -m ./${{ env.CRATE_NAME }}/Cargo.toml
maturin-version: "v0.13.0"
- name: Install built wheel - x86_64
run: |
@@ -57,7 +57,7 @@ jobs:
- name: Build wheels - universal2
uses: messense/maturin-action@v1
with:
args: --release --universal2 --out dist -m ./crates/${{ env.CRATE_NAME }}/Cargo.toml
args: --release --universal2 --out dist -m ./${{ env.CRATE_NAME }}/Cargo.toml
maturin-version: "v0.13.0"
- name: Install built wheel - universal2
run: |
@@ -89,7 +89,7 @@ jobs:
uses: messense/maturin-action@v1
with:
target: ${{ matrix.target }}
args: --release --out dist -m ./crates/${{ env.CRATE_NAME }}/Cargo.toml
args: --release --out dist -m ./${{ env.CRATE_NAME }}/Cargo.toml
maturin-version: "v0.13.0"
- name: Install built wheel
shell: bash
@@ -117,7 +117,7 @@ jobs:
with:
target: ${{ matrix.target }}
manylinux: auto
args: --release --out dist -m ./crates/${{ env.CRATE_NAME }}/Cargo.toml
args: --release --out dist -m ./${{ env.CRATE_NAME }}/Cargo.toml
maturin-version: "v0.13.0"
- name: Install built wheel
if: matrix.target == 'x86_64'
@@ -144,7 +144,7 @@ jobs:
with:
target: ${{ matrix.target }}
manylinux: auto
args: --no-default-features --release --out dist -m ./crates/${{ env.CRATE_NAME }}/Cargo.toml
args: --no-default-features --release --out dist -m ./${{ env.CRATE_NAME }}/Cargo.toml
maturin-version: "v0.13.0"
- uses: uraimo/run-on-arch-action@v2.0.5
if: matrix.target != 'ppc64'
@@ -183,7 +183,7 @@ jobs:
with:
target: ${{ matrix.target }}
manylinux: musllinux_1_2
args: --release --out dist -m ./crates/${{ env.CRATE_NAME }}/Cargo.toml
args: --release --out dist -m ./${{ env.CRATE_NAME }}/Cargo.toml
maturin-version: "v0.13.0"
- name: Install built wheel
if: matrix.target == 'x86_64-unknown-linux-musl'
@@ -219,7 +219,7 @@ jobs:
with:
target: ${{ matrix.platform.target }}
manylinux: musllinux_1_2
args: --release --out dist -m ./crates/${{ env.CRATE_NAME }}/Cargo.toml
args: --release --out dist -m ./${{ env.CRATE_NAME }}/Cargo.toml
maturin-version: "v0.13.0"
- uses: uraimo/run-on-arch-action@master
name: Install built wheel
@@ -261,7 +261,7 @@ jobs:
maturin-version: "v0.13.0"
target: ${{ matrix.target }}
manylinux: auto
args: --release --out dist -i pypy${{ matrix.python-version }} -m ./crates/${{ env.CRATE_NAME }}/Cargo.toml
args: --release --out dist -i pypy${{ matrix.python-version }} -m ./${{ env.CRATE_NAME }}/Cargo.toml
- name: Install built wheel
if: matrix.target == 'x86_64'
run: |

View File

@@ -1,6 +1,6 @@
repos:
- repo: https://github.com/charliermarsh/ruff-pre-commit
rev: v0.0.97
rev: v0.0.98
hooks:
- id: ruff

4
Cargo.lock generated
View File

@@ -920,7 +920,7 @@ checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80"
[[package]]
name = "flake8-to-ruff"
version = "0.0.97-dev.0"
version = "0.0.98-dev.0"
dependencies = [
"anyhow",
"clap 4.0.15",
@@ -2211,7 +2211,7 @@ dependencies = [
[[package]]
name = "ruff"
version = "0.0.97"
version = "0.0.98"
dependencies = [
"anyhow",
"assert_cmd",

View File

@@ -1,11 +1,11 @@
[workspace]
members = [
"crates/flake8_to_ruff",
"flake8_to_ruff",
]
[package]
name = "ruff"
version = "0.0.97"
version = "0.0.98"
edition = "2021"
[lib]

View File

@@ -89,7 +89,7 @@ Ruff also works with [pre-commit](https://pre-commit.com):
```yaml
repos:
- repo: https://github.com/charliermarsh/ruff-pre-commit
rev: v0.0.97
rev: v0.0.98
hooks:
- id: ruff
```
@@ -99,15 +99,59 @@ _Note: prior to `v0.0.86`, `ruff-pre-commit` used `lint` (rather than `ruff`) as
## Configuration
Ruff is configurable both via `pyproject.toml` and the command line.
For example, you could configure Ruff to only enforce a subset of rules with:
Ruff is configurable both via `pyproject.toml` and the command line. If left unspecified, the
default configuration is equivalent to:
```toml
[tool.ruff]
line-length = 88
# Enable Flake's "E" and "F" codes by default.
select = ["E", "F"]
ignore = []
# Exclude a variety of commonly ignored directories.
exclude = [
".bzr",
".direnv",
".eggs",
".git",
".hg",
".mypy_cache",
".nox",
".pants.d",
".ruff_cache",
".svn",
".tox",
".venv",
"__pypackages__",
"_build",
"buck-out",
"build",
"dist",
"node_modules",
"venv",
]
per-file-ignores = {}
# Allow unused variables when underscore-prefixed.
dummy-variable-rgx = "^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$"
# Assume Python 3.10.
target-version = "py310"
```
As an example, the following would configure Ruff to (1) avoid checking for line-length
violations (`E501`) and (2) ignore unused import rules in `__init__.py` files:
```toml
[tool.ruff]
select = ["E", "F"]
# Never enforce `E501`.
ignore = ["E501"]
# Ignore `F401` violations in any `__init__.py` file, and in `path/to/file.py`.
per-file-ignores = {"__init__.py" = ["F401"], "path/to/file.py" = ["F401"]}
```
@@ -115,7 +159,8 @@ Plugin configurations should be expressed as subsections, e.g.:
```toml
[tool.ruff]
line-length = 88
# Add "Q" to the list of enabled codes.
select = ["E", "F", "Q"]
[tool.ruff.flake8-quotes]
docstring-quotes = "double"
@@ -143,6 +188,8 @@ Options:
-v, --verbose
Enable verbose logging
-q, --quiet
Only log errors
-s, --silent
Disable all logging (but still exit with status code "1" upon detecting errors)
-e, --exit-zero
Exit with status code "0", even upon detecting errors

View File

@@ -771,7 +771,7 @@ checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80"
[[package]]
name = "flake8_to_ruff"
version = "0.0.97"
version = "0.0.98"
dependencies = [
"anyhow",
"clap",
@@ -1410,7 +1410,7 @@ dependencies = [
name = "net2"
version = "0.2.38"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "74d0df99cfcd2530b2e694f6e17e7f37b8e26bb23983ac530c0c97408837c631"
checksum = "74d0df99cfcd2530b2e694f6e17e7f37b8e26bb23983ac530.0.98408837c631"
dependencies = [
"cfg-if 0.1.10",
"libc",
@@ -1975,7 +1975,7 @@ dependencies = [
[[package]]
name = "ruff"
version = "0.0.97"
version = "0.0.98"
dependencies = [
"anyhow",
"bincode",

View File

@@ -1,6 +1,6 @@
[package]
name = "flake8-to-ruff"
version = "0.0.97-dev.0"
version = "0.0.98-dev.0"
edition = "2021"
[lib]
@@ -12,7 +12,7 @@ clap = { version = "4.0.1", features = ["derive"] }
configparser = { version = "3.0.2" }
once_cell = { version = "1.13.1" }
regex = { version = "1.6.0" }
ruff = { path = "../..", default-features = false }
ruff = { path = "..", default-features = false }
serde = { version = "1.0.143", features = ["derive"] }
serde_json = { version = "1.0.83" }
toml = { version = "0.5.9" }

View File

@@ -7,6 +7,7 @@ use log::warn;
use regex::Regex;
use crate::checks_gen::CheckCodePrefix;
use crate::logging::LogLevel;
use crate::printer::SerializationFormat;
use crate::settings::configuration::Configuration;
use crate::settings::types::{PatternPrefixPair, PythonVersion};
@@ -93,6 +94,19 @@ pub struct Cli {
pub stdin_filename: Option<String>,
}
/// Map the CLI settings to a `LogLevel`.
pub fn extract_log_level(cli: &Cli) -> LogLevel {
if cli.silent {
LogLevel::Silent
} else if cli.quiet {
LogLevel::Quiet
} else if cli.verbose {
LogLevel::Verbose
} else {
LogLevel::Default
}
}
pub enum Warnable {
Select,
ExtendSelect,

View File

@@ -15,7 +15,36 @@ macro_rules! tell_user {
}
}
pub fn set_up_logging(verbose: bool) -> Result<()> {
#[derive(Debug, PartialOrd, Ord, PartialEq, Eq)]
pub enum LogLevel {
// No output (+ `log::LevelFilter::Off`).
Silent,
// Only show lint violations, with no decorative output (+ `log::LevelFilter::Off`).
Quiet,
// All user-facing output (+ `log::LevelFilter::Info`).
Default,
// All user-facing output (+ `log::LevelFilter::Debug`).
Verbose,
}
impl LogLevel {
fn level_filter(&self) -> log::LevelFilter {
match self {
LogLevel::Default => log::LevelFilter::Info,
LogLevel::Verbose => log::LevelFilter::Debug,
LogLevel::Quiet => log::LevelFilter::Off,
LogLevel::Silent => log::LevelFilter::Off,
}
}
}
impl Default for LogLevel {
fn default() -> Self {
LogLevel::Default
}
}
pub fn set_up_logging(level: &LogLevel) -> Result<()> {
fern::Dispatch::new()
.format(|out, message, record| {
out.finish(format_args!(
@@ -26,12 +55,22 @@ pub fn set_up_logging(verbose: bool) -> Result<()> {
message
))
})
.level(if verbose {
log::LevelFilter::Debug
} else {
log::LevelFilter::Info
})
.level(level.level_filter())
.chain(std::io::stdout())
.apply()
.map_err(|e| e.into())
}
#[cfg(test)]
mod tests {
use crate::logging::LogLevel;
#[test]
fn ordering() {
assert!(LogLevel::Default > LogLevel::Silent);
assert!(LogLevel::Default >= LogLevel::Default);
assert!(LogLevel::Quiet > LogLevel::Silent);
assert!(LogLevel::Verbose > LogLevel::Default);
assert!(LogLevel::Verbose > LogLevel::Silent);
}
}

View File

@@ -5,6 +5,20 @@ use std::process::ExitCode;
use std::sync::mpsc::channel;
use std::time::Instant;
#[cfg(not(target_family = "wasm"))]
use ::ruff::cache;
use ::ruff::checks::{CheckCode, CheckKind};
use ::ruff::checks_gen::CheckCodePrefix;
use ::ruff::cli::{collect_per_file_ignores, extract_log_level, warn_on, Cli, Warnable};
use ::ruff::fs::iter_python_files;
use ::ruff::linter::{add_noqa_to_path, autoformat_path, lint_path, lint_stdin};
use ::ruff::logging::{set_up_logging, LogLevel};
use ::ruff::message::Message;
use ::ruff::printer::{Printer, SerializationFormat};
use ::ruff::settings::configuration::Configuration;
use ::ruff::settings::types::FilePattern;
use ::ruff::settings::user::UserConfiguration;
use ::ruff::settings::{pyproject, Settings};
use anyhow::Result;
use clap::Parser;
use colored::Colorize;
@@ -12,21 +26,6 @@ use log::{debug, error};
use notify::{raw_watcher, RecursiveMode, Watcher};
#[cfg(not(target_family = "wasm"))]
use rayon::prelude::*;
#[cfg(not(target_family = "wasm"))]
use ruff::cache;
use ruff::checks::{CheckCode, CheckKind};
use ruff::checks_gen::CheckCodePrefix;
use ruff::cli::{collect_per_file_ignores, warn_on, Cli, Warnable};
use ruff::fs::iter_python_files;
use ruff::linter::{add_noqa_to_path, autoformat_path, lint_path, lint_stdin};
use ruff::logging::set_up_logging;
use ruff::message::Message;
use ruff::printer::{Printer, SerializationFormat};
use ruff::settings::configuration::Configuration;
use ruff::settings::types::FilePattern;
use ruff::settings::user::UserConfiguration;
use ruff::settings::{pyproject, Settings};
use ruff::tell_user;
use walkdir::DirEntry;
#[cfg(feature = "update-informer")]
@@ -223,10 +222,10 @@ fn autoformat(files: &[PathBuf], settings: &Settings) -> Result<usize> {
}
fn inner_main() -> Result<ExitCode> {
let mut cli = Cli::parse();
cli.quiet |= cli.silent;
let cli = Cli::parse();
set_up_logging(cli.verbose)?;
let log_level = extract_log_level(&cli);
set_up_logging(&log_level)?;
// Find the project root and pyproject.toml.
let project_root = pyproject::find_project_root(&cli.files);
@@ -320,7 +319,7 @@ fn inner_main() -> Result<ExitCode> {
#[cfg(not(target_family = "wasm"))]
cache::init()?;
let mut printer = Printer::new(cli.format, cli.verbose);
let printer = Printer::new(&cli.format, &log_level);
if cli.watch {
if cli.fix {
eprintln!("Warning: --fix is not enabled in watch mode.");
@@ -340,12 +339,10 @@ fn inner_main() -> Result<ExitCode> {
// Perform an initial run instantly.
printer.clear_screen()?;
tell_user!("Starting linter in watch mode...\n");
printer.write_to_user("Starting linter in watch mode...\n");
let messages = run_once(&cli.files, &settings, !cli.no_cache, false)?;
if !cli.silent {
printer.write_continuously(&messages)?;
}
printer.write_continuously(&messages)?;
// Configure the file watcher.
let (tx, rx) = channel();
@@ -360,12 +357,10 @@ fn inner_main() -> Result<ExitCode> {
if let Some(path) = e.path {
if path.to_string_lossy().ends_with(".py") {
printer.clear_screen()?;
tell_user!("File change detected...\n");
printer.write_to_user("File change detected...\n");
let messages = run_once(&cli.files, &settings, !cli.no_cache, false)?;
if !cli.silent {
printer.write_continuously(&messages)?;
}
printer.write_continuously(&messages)?;
}
}
}
@@ -374,37 +369,36 @@ fn inner_main() -> Result<ExitCode> {
}
} else if cli.add_noqa {
let modifications = add_noqa(&cli.files, &settings)?;
if modifications > 0 {
if modifications > 0 && log_level >= LogLevel::Default {
println!("Added {modifications} noqa directives.");
}
} else if cli.autoformat {
let modifications = autoformat(&cli.files, &settings)?;
if modifications > 0 {
if modifications > 0 && log_level >= LogLevel::Default {
println!("Formatted {modifications} files.");
}
} else {
let (messages, should_print_messages, should_check_updates) =
if cli.files == vec![PathBuf::from("-")] {
let filename = cli.stdin_filename.unwrap_or_else(|| "-".to_string());
let path = Path::new(&filename);
(
run_once_stdin(&settings, path, cli.fix)?,
!cli.silent && !cli.fix,
false,
)
} else {
(
run_once(&cli.files, &settings, !cli.no_cache, cli.fix)?,
!cli.silent,
!cli.quiet,
)
};
if should_print_messages {
let is_stdin = cli.files == vec![PathBuf::from("-")];
// Generate lint violations.
let messages = if is_stdin {
let filename = cli.stdin_filename.unwrap_or_else(|| "-".to_string());
let path = Path::new(&filename);
run_once_stdin(&settings, path, cli.fix)?
} else {
run_once(&cli.files, &settings, !cli.no_cache, cli.fix)?
};
// Always try to print violations (the printer itself may suppress output),
// unless we're writing fixes via stdin (in which case, the transformed
// source code goes to stdout).
if !(is_stdin && cli.fix) {
printer.write_once(&messages)?;
}
// Check for updates if we're in a non-silent log level.
#[cfg(feature = "update-informer")]
if should_check_updates {
if !is_stdin && log_level >= LogLevel::Default {
check_for_updates();
}

View File

@@ -5,6 +5,7 @@ use rustpython_parser::ast::Location;
use serde::Serialize;
use crate::checks::{CheckCode, CheckKind};
use crate::logging::LogLevel;
use crate::message::Message;
use crate::tell_user;
@@ -25,17 +26,27 @@ struct ExpandedMessage<'a> {
filename: &'a String,
}
pub struct Printer {
format: SerializationFormat,
verbose: bool,
pub struct Printer<'a> {
format: &'a SerializationFormat,
log_level: &'a LogLevel,
}
impl Printer {
pub fn new(format: SerializationFormat, verbose: bool) -> Self {
Self { format, verbose }
impl<'a> Printer<'a> {
pub fn new(format: &'a SerializationFormat, log_level: &'a LogLevel) -> Self {
Self { format, log_level }
}
pub fn write_once(&mut self, messages: &[Message]) -> Result<()> {
pub fn write_to_user(&self, message: &str) {
if self.log_level >= &LogLevel::Default {
tell_user!("{}", message);
}
}
pub fn write_once(&self, messages: &[Message]) -> Result<()> {
if matches!(self.log_level, LogLevel::Silent) {
return Ok(());
}
let (fixed, outstanding): (Vec<&Message>, Vec<&Message>) =
messages.iter().partition(|message| message.fixed);
let num_fixable = outstanding
@@ -64,22 +75,26 @@ impl Printer {
)
}
SerializationFormat::Text => {
if !fixed.is_empty() {
println!(
"Found {} error(s) ({} fixed).",
outstanding.len(),
fixed.len()
)
} else if !outstanding.is_empty() || self.verbose {
println!("Found {} error(s).", outstanding.len())
if self.log_level >= &LogLevel::Default {
if !fixed.is_empty() {
println!(
"Found {} error(s) ({} fixed).",
outstanding.len(),
fixed.len()
)
} else if !outstanding.is_empty() {
println!("Found {} error(s).", outstanding.len())
}
}
for message in outstanding {
println!("{}", message)
}
if num_fixable > 0 {
println!("{num_fixable} potentially fixable with the --fix option.")
if self.log_level >= &LogLevel::Default {
if num_fixable > 0 {
println!("{num_fixable} potentially fixable with the --fix option.")
}
}
}
}
@@ -87,14 +102,22 @@ impl Printer {
Ok(())
}
pub fn write_continuously(&mut self, messages: &[Message]) -> Result<()> {
tell_user!(
"Found {} error(s). Watching for file changes.",
messages.len(),
);
pub fn write_continuously(&self, messages: &[Message]) -> Result<()> {
if matches!(self.log_level, LogLevel::Silent) {
return Ok(());
}
if self.log_level >= &LogLevel::Default {
tell_user!(
"Found {} error(s). Watching for file changes.",
messages.len(),
);
}
if !messages.is_empty() {
println!();
if self.log_level >= &LogLevel::Default {
println!();
}
for message in messages {
println!("{}", message)
}
@@ -103,7 +126,7 @@ impl Printer {
Ok(())
}
pub fn clear_screen(&mut self) -> Result<()> {
pub fn clear_screen(&self) -> Result<()> {
#[cfg(not(target_family = "wasm"))]
clearscreen::clear()?;
Ok(())

View File

@@ -12,6 +12,7 @@ use crate::checks_gen::CheckCodePrefix;
use crate::fs;
#[derive(Clone, Debug, PartialOrd, PartialEq, Eq, Serialize, Deserialize, Hash)]
#[serde(rename_all = "lowercase")]
pub enum PythonVersion {
Py33,
Py34,