Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 10 additions & 10 deletions native/Cargo.lock

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

2 changes: 1 addition & 1 deletion native/libcst/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ trace = ["peg/trace"]

[dependencies]
paste = "1.0.15"
pyo3 = { version = "0.22", optional = true }
pyo3 = { version = "0.23", optional = true }
thiserror = "1.0.63"
peg = "0.8.4"
chic = "1.2.2"
Expand Down
8 changes: 4 additions & 4 deletions native/libcst/src/nodes/expression.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2536,7 +2536,7 @@ mod py {
match self {
Self::Starred(s) => s.try_into_py(py),
Self::Simple { value, comma } => {
let libcst = PyModule::import_bound(py, "libcst")?;
let libcst = PyModule::import(py, "libcst")?;
let kwargs = [
Some(("value", value.try_into_py(py)?)),
comma
Expand All @@ -2548,7 +2548,7 @@ mod py {
.filter(|x| x.is_some())
.map(|x| x.as_ref().unwrap())
.collect::<Vec<_>>()
.into_py_dict_bound(py);
.into_py_dict(py)?;
Ok(libcst
.getattr("Element")
.expect("no Element found in libcst")
Expand All @@ -2572,7 +2572,7 @@ mod py {
whitespace_before_colon,
..
} => {
let libcst = PyModule::import_bound(py, "libcst")?;
let libcst = PyModule::import(py, "libcst")?;
let kwargs = [
Some(("key", key.try_into_py(py)?)),
Some(("value", value.try_into_py(py)?)),
Expand All @@ -2593,7 +2593,7 @@ mod py {
.filter(|x| x.is_some())
.map(|x| x.as_ref().unwrap())
.collect::<Vec<_>>()
.into_py_dict_bound(py);
.into_py_dict(py)?;
Ok(libcst
.getattr("DictElement")
.expect("no Element found in libcst")
Expand Down
23 changes: 4 additions & 19 deletions native/libcst/src/nodes/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ impl<'a, T: Inflate<'a>> Inflate<'a> for Vec<T> {
}
#[cfg(feature = "py")]
pub mod py {
use pyo3::{types::PyAny, types::PyTuple, IntoPy, PyObject, PyResult, Python};
use pyo3::{types::PyTuple, IntoPyObjectExt, PyObject, PyResult, Python};

// TODO: replace with upstream implementation once
// https://github.com/PyO3/pyo3/issues/1813 is resolved
Expand All @@ -135,7 +135,7 @@ pub mod py {

impl TryIntoPy<PyObject> for bool {
fn try_into_py(self, py: Python) -> PyResult<PyObject> {
Ok(self.into_py(py))
self.into_py_any(py)
}
}

Expand Down Expand Up @@ -170,28 +170,13 @@ pub mod py {
.map(|x| x.try_into_py(py))
.collect::<PyResult<Vec<_>>>()?
.into_iter();
Ok(PyTuple::new_bound(py, converted).into())
}
}

impl TryIntoPy<PyObject> for PyTuple {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I found that with IntoPyObject that some of these impls aren't needed at all. I didn't look too closely to try to understand why though so there could be something subtle happening.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great, I was hoping to get rid of these.

fn try_into_py(self, py: Python) -> PyResult<PyObject> {
Ok(self.into_py(py))
PyTuple::new(py, converted).unwrap().into_py_any(py)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Anything we can do to avoid the unwrap() and potential panic here?

}
}

impl<'a> TryIntoPy<PyObject> for &'a str {
fn try_into_py(self, py: Python) -> PyResult<PyObject> {
Ok(self.into_py(py))
}
}

impl<T> TryIntoPy<PyObject> for &'_ T
where
T: AsRef<PyAny>,
{
fn try_into_py(self, py: Python) -> PyResult<PyObject> {
Ok(self.into_py(py))
self.into_py_any(py)
}
}
}
54 changes: 16 additions & 38 deletions native/libcst/src/parser/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,18 +28,11 @@ pub enum ParserError<'a> {
#[cfg(feature = "py")]
mod py_error {

use pyo3::types::{IntoPyDict, PyAnyMethods, PyModule};
use pyo3::{IntoPy, PyErr, PyErrArguments, Python};
use pyo3::types::{IntoPyDict, PyAny, PyAnyMethods, PyModule};
use pyo3::{Bound, IntoPyObject, PyErr, PyResult, Python};

use super::ParserError;

struct Details {
message: String,
lines: Vec<String>,
raw_line: u32,
raw_column: u32,
}

impl<'a> From<ParserError<'a>> for PyErr {
fn from(e: ParserError) -> Self {
Python::with_gil(|py| {
Expand All @@ -59,36 +52,21 @@ mod py_error {
line = lines.len() - 1;
col = 0;
}
let kwargs = [
("message", e.to_string().into_py(py)),
("lines", lines.into_py(py)),
("raw_line", (line + 1).into_py(py)),
("raw_column", col.into_py(py)),
]
.into_py_dict_bound(py);
let libcst =
PyModule::import_bound(py, "libcst").expect("libcst cannot be imported");
PyErr::from_value_bound(
libcst
.getattr("ParserSyntaxError")
.expect("ParserSyntaxError not found")
.call((), Some(&kwargs))
.expect("failed to instantiate"),
)
match || -> PyResult<Bound<'_, PyAny>> {
let kwargs = [
("message", e.to_string().into_pyobject(py)?.into_any()),
("lines", lines.into_pyobject(py)?.into_any()),
("raw_line", (line + 1).into_pyobject(py)?.into_any()),
("raw_column", col.into_pyobject(py)?.into_any()),
]
.into_py_dict(py)?;
let libcst = PyModule::import(py, "libcst")?;
libcst.getattr("ParserSyntaxError")?.call((), Some(&kwargs))
}() {
Ok(py_err_value) => PyErr::from_value(py_err_value),
Err(e) => e,
}
Copy link
Contributor Author

@ngoldbaum ngoldbaum Jan 28, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since ultimately we want a PyErr in both the success and error cases, we can make use of a closure that returns a result and ? to avoid unwrap or expect in the new into_pyobject() calls that can return errors and at the same time clean up some unnecessary pre-existing expect use to turn some panics into errors. This is a neat Rust trick, unfortuntely it's only convenient in error handling code.

})
}
}

impl<'a> PyErrArguments for Details {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Both this and Details are unused and the compiler warns about them.

fn arguments(self, py: pyo3::Python) -> pyo3::PyObject {
[
("message", self.message.into_py(py)),
("lines", self.lines.into_py(py)),
("raw_line", self.raw_line.into_py(py)),
("raw_column", self.raw_column.into_py(py)),
]
.into_py_dict_bound(py)
.into_py(py)
}
}
}
Loading