Skip to content

Commit

Permalink
Update rust re-hydration code to pyo3 0.21 (#264)
Browse files Browse the repository at this point in the history
* Upgrade to 0.20

* Bump to pyo3 0.21
  • Loading branch information
kylebarron authored Apr 29, 2024
1 parent 35a4d1c commit fbe9203
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 31 deletions.
47 changes: 31 additions & 16 deletions src/pypgstac/Cargo.lock

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

6 changes: 5 additions & 1 deletion src/pypgstac/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,8 @@ crate-type = ["cdylib"]

[dependencies]
anyhow = "1"
pyo3 = { version = "0.19.1", features = ["abi3-py38", "extension-module", "anyhow"] }
pyo3 = { version = "0.21", features = [
"abi3-py38",
"extension-module",
"anyhow",
] }
40 changes: 26 additions & 14 deletions src/pypgstac/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,30 +22,37 @@
)]

use anyhow::anyhow;
use pyo3::pybacked::PyBackedStr;
use pyo3::{
prelude::*,
types::{PyDict, PyList, PyString},
types::{PyDict, PyList},
};

const MAGIC_MARKER: &str = "𒍟※";

#[pyfunction]
fn hydrate<'a>(base: &PyAny, item: &'a PyAny) -> PyResult<&'a PyAny> {
fn hydrate<'py>(
base: &'py Bound<'py, PyAny>,
item: &'py Bound<'py, PyAny>,
) -> PyResult<&'py Bound<'py, PyAny>> {
hydrate_any(base, item)
}

fn hydrate_any<'a>(base: &PyAny, item: &'a PyAny) -> PyResult<&'a PyAny> {
fn hydrate_any<'py>(
base: &'py Bound<'py, PyAny>,
item: &'py Bound<'py, PyAny>,
) -> PyResult<&'py Bound<'py, PyAny>> {
if let Ok(item) = item.downcast::<PyDict>() {
if let Ok(base) = base.downcast::<PyDict>() {
hydrate_dict(base, item).map(|item| item.into())
Ok(hydrate_dict(base, item)?.as_any())
} else if base.is_none() {
Ok(item)
} else {
Err(anyhow!("type mismatch").into())
}
} else if let Ok(item) = item.downcast::<PyList>() {
if let Ok(base) = base.downcast::<PyList>() {
hydrate_list(base, item).map(|item| item.into())
Ok(hydrate_list(base, item)?.as_any())
} else if base.is_none() {
Ok(item)
} else {
Expand All @@ -56,30 +63,35 @@ fn hydrate_any<'a>(base: &PyAny, item: &'a PyAny) -> PyResult<&'a PyAny> {
}
}

fn hydrate_list<'a>(base: &PyList, item: &'a PyList) -> PyResult<&'a PyList> {
fn hydrate_list<'py>(
base: &'py Bound<'py, PyList>,
item: &'py Bound<'py, PyList>,
) -> PyResult<&'py Bound<'py, PyList>> {
for i in 0..item.len() {
if i >= base.len() {
return Ok(item);
} else {
item.set_item(i, hydrate(&base[i], &item[i])?)?;
item.set_item(i, hydrate(&base.get_item(i)?, &item.get_item(i)?)?)?;
}
}
Ok(item)
}

fn hydrate_dict<'a>(base: &PyDict, item: &'a PyDict) -> PyResult<&'a PyDict> {
fn hydrate_dict<'py>(
base: &'py Bound<'py, PyDict>,
item: &'py Bound<'py, PyDict>,
) -> PyResult<&'py Bound<'py, PyDict>> {
for (key, base_value) in base {
if let Some(item_value) = item.get_item(key) {
if let Some(item_value) = item.get_item(&key)? {
if item_value
.downcast::<PyString>()
.extract::<PyBackedStr>()
.ok()
.and_then(|value| value.to_str().ok())
.map(|s| s == MAGIC_MARKER)
.map(|s| <PyBackedStr as AsRef<str>>::as_ref(&s) == MAGIC_MARKER)
.unwrap_or(false)
{
item.del_item(key)?;
} else {
item.set_item(key, hydrate(base_value, item_value)?)?;
item.set_item(&key, hydrate(&base_value, &item_value)?)?;
}
} else {
item.set_item(key, base_value)?;
Expand All @@ -89,7 +101,7 @@ fn hydrate_dict<'a>(base: &PyDict, item: &'a PyDict) -> PyResult<&'a PyDict> {
}

#[pymodule]
fn pgstacrs(_py: Python<'_>, m: &PyModule) -> PyResult<()> {
fn pgstacrs(_py: Python<'_>, m: &Bound<'_, PyModule>) -> PyResult<()> {
m.add_function(wrap_pyfunction!(crate::hydrate, m)?)?;
Ok(())
}

0 comments on commit fbe9203

Please sign in to comment.