Skip to content

Commit 9391445

Browse files
committed
fix(bindings): fixed broken python binding for extractors
1 parent 07dab9c commit 9391445

2 files changed

Lines changed: 23 additions & 17 deletions

File tree

src/extractors/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use std::fmt::Write;
77

88
/// Takes a list of features and makes each one unique by appending its occurrence count,
99
/// then interns the result and returns them sorted.
10-
fn append_feature_counts(interner: &mut Rodeo, features: Vec<String>) -> Vec<Spur> {
10+
pub(crate) fn append_feature_counts(interner: &mut Rodeo, features: Vec<String>) -> Vec<Spur> {
1111
let mut counter: FxHashMap<String, usize> = FxHashMap::default();
1212
let mut unique_features = Vec::with_capacity(features.len());
1313

src/python/mod.rs

Lines changed: 22 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -12,22 +12,25 @@ create_exception!(simstring_rust, SearchError, pyo3::exceptions::PyValueError);
1212

1313
#[derive(Clone)]
1414
struct CustomExtractorInner {
15-
extractor: Py<PyAny>,
15+
extractor: Arc<Py<PyAny>>,
1616
}
1717

1818
unsafe impl Send for CustomExtractorInner {}
1919
unsafe impl Sync for CustomExtractorInner {}
2020

2121
impl CustomExtractorInner {
2222
fn new(extractor: Py<PyAny>) -> Self {
23-
Self { extractor }
23+
Self {
24+
extractor: Arc::new(extractor),
25+
}
2426
}
2527

2628
fn collect_raw_features(&self, text: &str) -> PyResult<Vec<String>> {
27-
Python::with_gil(|py| {
28-
let extractor = self.extractor.bind(py);
29+
let extractor = Arc::clone(&self.extractor);
30+
Python::attach(|py| {
31+
let extractor = extractor.bind(py);
2932
let result = extractor.call_method1("apply", (text,))?;
30-
let iter = result.iter()?;
33+
let iter = result.try_iter()?;
3134

3235
let mut features = Vec::new();
3336
for item in iter {
@@ -41,13 +44,13 @@ impl CustomExtractorInner {
4144

4245
fn features(&self, text: &str, interner: &mut lasso::Rodeo) -> PyResult<Vec<lasso::Spur>> {
4346
let raw = self.collect_raw_features(text)?;
44-
Ok(super::append_feature_counts(interner, raw))
47+
Ok(crate::extractors::append_feature_counts(interner, raw))
4548
}
4649

4750
fn apply(&self, text: &str) -> PyResult<Vec<String>> {
4851
let raw = self.collect_raw_features(text)?;
4952
let mut interner = lasso::Rodeo::default();
50-
let spurs = super::append_feature_counts(&mut interner, raw);
53+
let spurs = crate::extractors::append_feature_counts(&mut interner, raw);
5154

5255
Ok(spurs
5356
.into_iter()
@@ -72,7 +75,7 @@ impl FeatureExtractor for PyFeatureExtractor {
7275
PyFeatureExtractor::Custom(e) => match e.features(text, interner) {
7376
Ok(features) => features,
7477
Err(err) => {
75-
Python::with_gil(|py| err.print(py));
78+
Python::attach(|py| err.print(py));
7679
panic!("Custom extractor apply() raised an exception");
7780
}
7881
},
@@ -131,14 +134,17 @@ struct PyCustomExtractor(CustomExtractorInner);
131134
#[pymethods]
132135
impl PyCustomExtractor {
133136
#[new]
134-
fn new(extractor: &Bound<'_, PyAny>) -> PyResult<Self> {
135-
if !extractor.hasattr("apply")? {
136-
return Err(pyo3::exceptions::PyTypeError::new_err(
137-
"Custom extractor must provide an apply(text: str) -> Iterable[str] method",
138-
));
139-
}
140-
141-
Ok(Self(CustomExtractorInner::new(extractor.unbind())))
137+
fn new(extractor: Py<PyAny>) -> PyResult<Self> {
138+
Python::attach(|py| {
139+
let bound = extractor.bind(py);
140+
if !bound.hasattr("apply")? {
141+
Err(pyo3::exceptions::PyTypeError::new_err(
142+
"Custom extractor must provide an apply(text: str) -> Iterable[str] method",
143+
))
144+
} else {
145+
Ok(Self(CustomExtractorInner::new(extractor)))
146+
}
147+
})
142148
}
143149

144150
fn apply(&self, text: &str) -> PyResult<Vec<String>> {

0 commit comments

Comments
 (0)