Skip to content

Commit

Permalink
Accept options in check
Browse files Browse the repository at this point in the history
  • Loading branch information
squiddy committed Dec 28, 2022
1 parent 7c91d47 commit 79990b9
Show file tree
Hide file tree
Showing 6 changed files with 80 additions and 31 deletions.
11 changes: 11 additions & 0 deletions Cargo.lock

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

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ clearscreen = { version = "1.0.10" }
rayon = { version = "1.5.3" }
update-informer = { version = "0.5.0", default-features = false, features = ["pypi"], optional = true }
pyo3 = { version = "0.17.3", features = ["extension-module", "abi3", "abi3-py37", "anyhow"] }
pythonize = "0.17.0"

# https://docs.rs/getrandom/0.2.7/getrandom/#webassembly-support
# For (future) wasm-pack support
Expand Down
2 changes: 1 addition & 1 deletion ruff/__init__.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,4 @@ class Message:
location: Location
end_location: Location

def check(contents: str | None, path: str | None) -> list(Message): ...
def check(contents: str | None, path: str | None, options: Mapping[str, Any] | None) -> list(Message): ...
24 changes: 24 additions & 0 deletions ruff/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,30 @@ def test_something(self):
self.assertEqual(results[0].end_location.row, 3)
self.assertEqual(results[0].end_location.column, 10)

def test_options(self):
results = check(
"""
import sys
print("This is a really long text")
""",
options={"line-length": 10, "ignore": ["F401"]},
)
self.assertEqual(len(results), 1)
self.assertEqual(results[0].code, "E501")
self.assertEqual(results[0].message, "Line too long (35 > 10 characters)")
self.assertEqual(results[0].location.row, 4)
self.assertEqual(results[0].location.column, 10)
self.assertEqual(results[0].end_location.row, 4)
self.assertEqual(results[0].end_location.column, 35)

def test_invalid_options(self):
with self.assertRaisesRegex(
Exception,
"unknown field `line-count`, expected one of `allowed-confusables`, .*",
):
check("print(123)", options={"line-count": 10})


if __name__ == "__main__":
unittest.main()
4 changes: 3 additions & 1 deletion src/lib_native.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@ use crate::source_code_style::SourceCodeStyleDetector;
use crate::{directives, packages, resolver};

/// Load the relevant `Settings` for a given `Path`.
fn resolve(path: &Path) -> Result<Settings> {
/// TODO(rgerecke): Move this somewhere else as to not make it part of public
/// API
pub fn resolve(path: &Path) -> Result<Settings> {
if let Some(pyproject) = pyproject::find_settings_toml(path)? {
// First priority: `pyproject.toml` in the current `Path`.
resolver::resolve_settings(&pyproject, &Relativity::Parent, None)
Expand Down
69 changes: 40 additions & 29 deletions src/lib_python.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
use std::path::Path;

use anyhow::Result;
use path_absolutize::path_dedot;
use pyo3::prelude::*;
use pyo3::types::PyString;
use pythonize::depythonize;
use rustpython_parser::lexer::LexResult;

use crate::checks::{Check, CheckCode};
use crate::lib_native::resolve;
use crate::linter::check_path;
use crate::rustpython_helpers::tokenize;
use crate::settings::configuration::Configuration;
Expand Down Expand Up @@ -46,13 +49,18 @@ impl IntoPy<PyObject> for CheckCode {
}
}

fn inner_check<P>(contents: &str, path: P) -> Result<Vec<Check>>
where
P: AsRef<Path>,
{
// let configuration = Configuration::from_options(options, path.as_ref())?;
let configuration = Configuration::default();
let settings = Settings::from_configuration(configuration, path.as_ref())?;
fn inner_check(
contents: &str,
path: Option<&Path>,
options: Option<Options>,
) -> Result<Vec<Check>> {
let filename = path.unwrap_or_else(|| Path::new("<filename>"));
let path = path.unwrap_or(&path_dedot::CWD);

let settings = match options {
Some(opt) => Settings::from_configuration(Configuration::from_options(opt, path)?, path)?,
None => resolve(path)?,
};

// Tokenize once.
let tokens: Vec<LexResult> = tokenize(contents);
Expand All @@ -68,8 +76,8 @@ where

// Generate checks.
let checks = check_path(
path.as_ref(),
packages::detect_package_root(path.as_ref()),
filename,
packages::detect_package_root(path),
contents,
tokens,
&locator,
Expand All @@ -84,26 +92,29 @@ where
}

#[pyfunction]
fn check(contents: &str, path: Option<&str>) -> PyResult<Vec<Message>> {
// TODO(rgerecke): Accept settings
Ok(
inner_check(contents, path.unwrap_or("<filename>")).map(|r| {
r.iter()
.map(|check| Message {
code: check.kind.code().clone(),
message: check.kind.body(),
location: Location {
row: check.location.row(),
column: check.location.column(),
},
end_location: Location {
row: check.end_location.row(),
column: check.end_location.column(),
},
})
.collect::<Vec<_>>()
})?,
)
fn check(contents: &str, path: Option<&str>, options: Option<&PyAny>) -> PyResult<Vec<Message>> {
let path = path.map(Path::new);
let options = match options {
Some(v) => depythonize(v)?,
None => None,
};

Ok(inner_check(contents, path, options).map(|r| {
r.iter()
.map(|check| Message {
code: check.kind.code().clone(),
message: check.kind.body(),
location: Location {
row: check.location.row(),
column: check.location.column(),
},
end_location: Location {
row: check.end_location.row(),
column: check.end_location.column(),
},
})
.collect::<Vec<_>>()
})?)
}

#[pymodule]
Expand Down

0 comments on commit 79990b9

Please sign in to comment.