add pyo3 as a feature flag for python bindings (#2710)

* updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* thing

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* add feature flag for pyo3 for gregs stuff;

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* add more

Signed-off-by: Jess Frazelle <github@jessfraz.com>

---------

Signed-off-by: Jess Frazelle <github@jessfraz.com>
This commit is contained in:
Jess Frazelle
2024-06-19 17:32:08 -07:00
committed by GitHub
parent dc226d3270
commit f1ef9d5200
10 changed files with 155 additions and 32 deletions

View File

@ -1277,6 +1277,12 @@ dependencies = [
"hashbrown 0.14.3",
]
[[package]]
name = "indoc"
version = "2.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b248f5224d1d606005e02c97f5aa4e88eeb230488bcc03bc9ca4d7991399f2b5"
[[package]]
name = "inflections"
version = "1.1.1"
@ -1399,6 +1405,7 @@ dependencies = [
"mime_guess",
"parse-display",
"pretty_assertions",
"pyo3",
"reqwest",
"ropey",
"schemars",
@ -1569,6 +1576,15 @@ version = "2.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149"
[[package]]
name = "memoffset"
version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a"
dependencies = [
"autocfg",
]
[[package]]
name = "mime"
version = "0.3.17"
@ -1907,6 +1923,12 @@ dependencies = [
"miniz_oxide",
]
[[package]]
name = "portable-atomic"
version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7170ef9988bc169ba16dd36a7fa041e5c4cbeb6a35b76d4c03daded371eae7c0"
[[package]]
name = "powerfmt"
version = "0.2.0"
@ -1962,6 +1984,69 @@ dependencies = [
"unicode-ident",
]
[[package]]
name = "pyo3"
version = "0.21.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a5e00b96a521718e08e03b1a622f01c8a8deb50719335de3f60b3b3950f069d8"
dependencies = [
"cfg-if",
"indoc",
"libc",
"memoffset",
"parking_lot 0.12.1",
"portable-atomic",
"pyo3-build-config",
"pyo3-ffi",
"pyo3-macros",
"unindent",
]
[[package]]
name = "pyo3-build-config"
version = "0.21.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7883df5835fafdad87c0d888b266c8ec0f4c9ca48a5bed6bbb592e8dedee1b50"
dependencies = [
"once_cell",
"target-lexicon",
]
[[package]]
name = "pyo3-ffi"
version = "0.21.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "01be5843dc60b916ab4dad1dca6d20b9b4e6ddc8e15f50c47fe6d85f1fb97403"
dependencies = [
"libc",
"pyo3-build-config",
]
[[package]]
name = "pyo3-macros"
version = "0.21.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77b34069fc0682e11b31dbd10321cbf94808394c56fd996796ce45217dfac53c"
dependencies = [
"proc-macro2",
"pyo3-macros-backend",
"quote",
"syn 2.0.66",
]
[[package]]
name = "pyo3-macros-backend"
version = "0.21.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08260721f32db5e1a5beae69a55553f56b99bd0e1c3e6e0a5e8851a9d0f5a85c"
dependencies = [
"heck 0.4.1",
"proc-macro2",
"pyo3-build-config",
"quote",
"syn 2.0.66",
]
[[package]]
name = "quick-xml"
version = "0.28.2"
@ -2795,6 +2880,12 @@ version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369"
[[package]]
name = "target-lexicon"
version = "0.12.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e1fc403891a21bcfb7c37834ba66a547a8f402146eba7265b5a6d88059c9ff2f"
[[package]]
name = "task-local-extensions"
version = "0.1.4"
@ -3277,6 +3368,12 @@ version = "0.1.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85"
[[package]]
name = "unindent"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c7de7d73e1754487cb58364ee906a499937a0dfabd86bcb980fa99ec8c8fa2ce"
[[package]]
name = "untrusted"
version = "0.9.0"

View File

@ -28,6 +28,7 @@ kittycad = { workspace = true, features = ["clap"] }
lazy_static = "1.4.0"
mime_guess = "2.0.4"
parse-display = "0.9.1"
pyo3 = {version = "0.21.2", optional = true}
reqwest = { version = "0.11.26", default-features = false, features = ["stream", "rustls-tls"] }
ropey = "1.6.1"
schemars = { version = "0.8.17", features = ["impl_json_schema", "url", "uuid1"] }
@ -63,6 +64,7 @@ tower-lsp = { version = "0.20.0", features = ["proposed"] }
default = ["cli", "engine"]
cli = ["dep:clap"]
engine = []
pyo3 = ["dep:pyo3"]
[profile.release]
panic = "abort"

View File

@ -1,6 +1,11 @@
//! Data types for the AST.
use std::{collections::HashMap, fmt::Write, ops::RangeInclusive};
use std::{
collections::HashMap,
fmt::Write,
ops::RangeInclusive,
sync::{Arc, Mutex},
};
use anyhow::Result;
use databake::*;
@ -147,6 +152,21 @@ impl Program {
}
}
/// Check the provided Program for any lint findings.
pub fn lint<'a, RuleT>(&'a self, rule: RuleT) -> Result<Vec<crate::lint::Discovered>>
where
RuleT: crate::lint::rule::Rule<'a>,
{
let v = Arc::new(Mutex::new(vec![]));
crate::lint::walk(self, &|node: crate::lint::Node<'a>| {
let mut findings = v.lock().map_err(|_| anyhow::anyhow!("mutex"))?;
findings.append(&mut rule.check(node)?);
Ok(true)
})?;
let x = v.lock().unwrap();
Ok(x.clone())
}
/// Returns the body item that includes the given character position.
pub fn get_body_item_for_position(&self, pos: usize) -> Option<&BodyItem> {
for item in &self.body {
@ -3004,6 +3024,7 @@ pub enum Hover {
/// Format options.
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
#[cfg_attr(feature = "pyo3", pyo3::pyclass)]
#[ts(export)]
#[serde(rename_all = "camelCase")]
pub struct FormatOptions {

View File

@ -168,3 +168,20 @@ impl From<String> for KclError {
serde_json::from_str(&error).unwrap()
}
}
#[cfg(feature = "pyo3")]
impl From<pyo3::PyErr> for KclError {
fn from(error: pyo3::PyErr) -> Self {
KclError::Internal(KclErrorDetails {
source_ranges: vec![],
message: error.to_string(),
})
}
}
#[cfg(feature = "pyo3")]
impl From<KclError> for pyo3::PyErr {
fn from(error: KclError) -> Self {
pyo3::exceptions::PyException::new_err(error.to_string())
}
}

View File

@ -617,6 +617,7 @@ impl From<Position> for Point3d {
pub struct Rotation(#[ts(type = "[number, number, number, number]")] pub [f64; 4]);
#[derive(Debug, Default, Deserialize, Serialize, PartialEq, Copy, Clone, ts_rs::TS, JsonSchema, Hash, Eq)]
#[cfg_attr(feature = "pyo3", pyo3::pyclass)]
#[ts(export)]
pub struct SourceRange(#[ts(type = "[number, number]")] pub [usize; 2]);
@ -1149,7 +1150,7 @@ impl ExecutorContext {
uuid::Uuid::new_v4(),
SourceRange::default(),
&kittycad::types::ModelingCmd::SetSceneUnits {
unit: self.settings.units.clone().into(),
unit: self.settings.units.into(),
},
)
.await?;

View File

@ -1,9 +1,9 @@
mod ast_node;
mod ast_walk;
pub mod checks;
mod rule;
pub mod rule;
pub use ast_node::Node;
pub use ast_walk::walk;
// pub(crate) use rule::{def_finding, finding};
pub use rule::{lint, Discovered, Finding};
pub use rule::{Discovered, Finding};

View File

@ -1,14 +1,7 @@
use std::sync::{Arc, Mutex};
use anyhow::Result;
use tower_lsp::lsp_types::{Diagnostic, DiagnosticSeverity};
use crate::{
ast::types::Program,
executor::SourceRange,
lint::{walk, Node},
lsp::IntoDiagnostic,
};
use crate::{executor::SourceRange, lint::Node, lsp::IntoDiagnostic};
/// Check the provided AST for any found rule violations.
///
@ -30,6 +23,7 @@ where
/// Specific discovered lint rule Violation of a particular Finding.
#[derive(Clone, Debug)]
#[cfg_attr(feature = "pyo3", pyo3::pyclass)]
pub struct Discovered {
/// Zoo Lint Finding information.
pub finding: Finding,
@ -66,6 +60,7 @@ impl IntoDiagnostic for Discovered {
/// Abstract lint problem type.
#[derive(Clone, Debug, PartialEq)]
#[cfg_attr(feature = "pyo3", pyo3::pyclass)]
pub struct Finding {
/// Unique identifier for this particular issue.
pub code: &'static str,
@ -114,21 +109,6 @@ pub(crate) use finding;
#[cfg(test)]
pub(crate) use test::{assert_finding, assert_no_finding, test_finding, test_no_finding};
/// Check the provided Program for any Findings.
pub fn lint<'a, RuleT>(prog: &'a Program, rule: RuleT) -> Result<Vec<Discovered>>
where
RuleT: Rule<'a>,
{
let v = Arc::new(Mutex::new(vec![]));
walk(prog, &|node: Node<'a>| {
let mut findings = v.lock().map_err(|_| anyhow::anyhow!("mutex"))?;
findings.append(&mut rule.check(node)?);
Ok(true)
})?;
let x = v.lock().unwrap();
Ok(x.clone())
}
#[cfg(test)]
mod test {
@ -137,7 +117,7 @@ mod test {
let tokens = $crate::token::lexer($kcl).unwrap();
let parser = $crate::parser::Parser::new(tokens);
let prog = parser.ast().unwrap();
for discovered_finding in $crate::lint::lint(&prog, $check).unwrap() {
for discovered_finding in prog.lint($check).unwrap() {
if discovered_finding.finding == $finding {
assert!(false, "Finding {:?} was emitted", $finding.code);
}
@ -151,7 +131,7 @@ mod test {
let parser = $crate::parser::Parser::new(tokens);
let prog = parser.ast().unwrap();
for discovered_finding in $crate::lint::lint(&prog, $check).unwrap() {
for discovered_finding in prog.lint($check).unwrap() {
if discovered_finding.finding == $finding {
return;
}

View File

@ -37,7 +37,7 @@ use super::backend::{InnerHandle, UpdateHandle};
use crate::{
ast::types::VariableKind,
executor::SourceRange,
lint::{checks, lint},
lint::checks,
lsp::{backend::Backend as _, safemap::SafeMap, util::IntoDiagnostic},
parser::PIPE_OPERATOR,
};
@ -257,7 +257,7 @@ impl crate::lsp::backend::Backend for Backend {
return;
}
for discovered_finding in lint(&ast, checks::lint_variables).into_iter().flatten() {
for discovered_finding in ast.lint(checks::lint_variables).into_iter().flatten() {
self.add_to_diagnostics(&params, discovered_finding).await;
}
}

View File

@ -405,7 +405,10 @@ impl From<bool> for DefaultTrue {
}
/// The valid types of length units.
#[derive(Debug, Default, Eq, PartialEq, Clone, Deserialize, Serialize, JsonSchema, ts_rs::TS, Display, FromStr)]
#[derive(
Debug, Default, Eq, PartialEq, Copy, Clone, Deserialize, Serialize, JsonSchema, ts_rs::TS, Display, FromStr,
)]
#[cfg_attr(feature = "pyo3", pyo3::pyclass)]
#[ts(export)]
#[serde(rename_all = "lowercase")]
#[display(style = "lowercase")]

View File

@ -13,6 +13,7 @@ mod tokeniser;
/// The types of tokens.
#[derive(Debug, PartialEq, Eq, Copy, Clone, Deserialize, Serialize, ts_rs::TS, JsonSchema, FromStr, Display)]
#[cfg_attr(feature = "pyo3", pyo3::pyclass)]
#[ts(export)]
#[serde(rename_all = "camelCase")]
#[display(style = "camelCase")]
@ -142,6 +143,7 @@ impl TokenType {
}
#[derive(Debug, PartialEq, Eq, Deserialize, Serialize, Clone, ts_rs::TS)]
#[cfg_attr(feature = "pyo3", pyo3::pyclass)]
#[ts(export)]
pub struct Token {
#[serde(rename = "type")]