Skip to content

Commit c742915

Browse files
aepfliclaude
andcommitted
fix(python): update PyO3 to 0.22 and fix API compatibility
Update PyO3 from 0.20 to 0.22 to resolve non-local impl definition warnings and ensure compatibility with newer Rust compiler versions. Changes: - Update pyo3 and pythonize dependencies to 0.22 - Update method signatures to use Bound<'_, PyDict> instead of &PyDict - Use .as_any() when calling depythonize (now requires &Bound<PyAny>) - Use PyDict::new_bound() instead of PyDict::new() - Update pymodule signature to use &Bound<PyModule> - Convert pythonize result with .unbind() to match PyObject return type This resolves the compiler warning: "non-local impl definition, impl blocks should be written at the same level as their item" 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
1 parent 198df13 commit c742915

2 files changed

Lines changed: 25 additions & 23 deletions

File tree

python/Cargo.toml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,10 @@ name = "flagd_evaluator"
1111
crate-type = ["cdylib"]
1212

1313
[dependencies]
14-
pyo3 = { version = "0.20", features = ["extension-module"] }
15-
pythonize = "0.20"
14+
pyo3 = { version = "0.22", features = ["extension-module"] }
15+
pythonize = "0.22"
1616
flagd-evaluator = { path = "..", default-features = false }
1717
serde_json = "1.0"
1818

1919
[dev-dependencies]
20-
pyo3 = { version = "0.20", features = ["auto-initialize"] }
20+
pyo3 = { version = "0.22", features = ["auto-initialize"] }

python/src/lib.rs

Lines changed: 22 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -45,9 +45,9 @@ impl FlagEvaluator {
4545
///
4646
/// Returns:
4747
/// dict: Update response with changed flag keys
48-
fn update_state(&mut self, py: Python, config: &PyDict) -> PyResult<PyObject> {
48+
fn update_state(&mut self, py: Python, config: &Bound<'_, PyDict>) -> PyResult<PyObject> {
4949
// Convert Python dict to JSON Value
50-
let config_value: Value = pythonize::depythonize(config)?;
50+
let config_value: Value = pythonize::depythonize(config.as_any())?;
5151

5252
// Convert to JSON string for parsing
5353
let config_str = serde_json::to_string(&config_value).map_err(|e| {
@@ -69,7 +69,7 @@ impl FlagEvaluator {
6969
self.state = Some(parsing_result.clone());
7070

7171
// Return update response (simplified - just success)
72-
let result_dict = PyDict::new(py);
72+
let result_dict = PyDict::new_bound(py);
7373
result_dict.set_item("success", true)?;
7474
Ok(result_dict.into())
7575
}
@@ -82,7 +82,7 @@ impl FlagEvaluator {
8282
///
8383
/// Returns:
8484
/// dict: Evaluation result with value, variant, reason, and metadata
85-
fn evaluate(&self, py: Python, flag_key: String, context: &PyDict) -> PyResult<PyObject> {
85+
fn evaluate(&self, py: Python, flag_key: String, context: &Bound<'_, PyDict>) -> PyResult<PyObject> {
8686
let state = self.state.as_ref().ok_or_else(|| {
8787
PyErr::new::<pyo3::exceptions::PyRuntimeError, _>(
8888
"No state loaded. Call update_state() first.",
@@ -95,18 +95,20 @@ impl FlagEvaluator {
9595
})?;
9696

9797
// Convert context to JSON Value
98-
let context_value: Value = pythonize::depythonize(context)?;
98+
let context_value: Value = pythonize::depythonize(context.as_any())?;
9999

100100
// Evaluate the flag
101101
let result = evaluate_flag(flag, &context_value, &state.flag_set_metadata);
102102

103103
// Convert result to Python dict
104-
pythonize::pythonize(py, &result).map_err(|e| {
105-
PyErr::new::<pyo3::exceptions::PyValueError, _>(format!(
106-
"Failed to convert result: {}",
107-
e
108-
))
109-
})
104+
pythonize::pythonize(py, &result)
105+
.map(|bound| bound.unbind())
106+
.map_err(|e| {
107+
PyErr::new::<pyo3::exceptions::PyValueError, _>(format!(
108+
"Failed to convert result: {}",
109+
e
110+
))
111+
})
110112
}
111113

112114
/// Evaluate a boolean flag
@@ -121,7 +123,7 @@ impl FlagEvaluator {
121123
fn evaluate_bool(
122124
&self,
123125
flag_key: String,
124-
context: &PyDict,
126+
context: &Bound<'_, PyDict>,
125127
default_value: bool,
126128
) -> PyResult<bool> {
127129
let state = self.state.as_ref().ok_or_else(|| {
@@ -134,7 +136,7 @@ impl FlagEvaluator {
134136
PyErr::new::<pyo3::exceptions::PyKeyError, _>(format!("Flag not found: {}", flag_key))
135137
})?;
136138

137-
let context_value: Value = pythonize::depythonize(context)?;
139+
let context_value: Value = pythonize::depythonize(context.as_any())?;
138140
let result = evaluate_bool_flag(flag, &context_value, &state.flag_set_metadata);
139141

140142
match result.value {
@@ -155,7 +157,7 @@ impl FlagEvaluator {
155157
fn evaluate_string(
156158
&self,
157159
flag_key: String,
158-
context: &PyDict,
160+
context: &Bound<'_, PyDict>,
159161
default_value: String,
160162
) -> PyResult<String> {
161163
let state = self.state.as_ref().ok_or_else(|| {
@@ -168,7 +170,7 @@ impl FlagEvaluator {
168170
PyErr::new::<pyo3::exceptions::PyKeyError, _>(format!("Flag not found: {}", flag_key))
169171
})?;
170172

171-
let context_value: Value = pythonize::depythonize(context)?;
173+
let context_value: Value = pythonize::depythonize(context.as_any())?;
172174
let result = evaluate_string_flag(flag, &context_value, &state.flag_set_metadata);
173175

174176
match result.value {
@@ -189,7 +191,7 @@ impl FlagEvaluator {
189191
fn evaluate_int(
190192
&self,
191193
flag_key: String,
192-
context: &PyDict,
194+
context: &Bound<'_, PyDict>,
193195
default_value: i64,
194196
) -> PyResult<i64> {
195197
let state = self.state.as_ref().ok_or_else(|| {
@@ -202,7 +204,7 @@ impl FlagEvaluator {
202204
PyErr::new::<pyo3::exceptions::PyKeyError, _>(format!("Flag not found: {}", flag_key))
203205
})?;
204206

205-
let context_value: Value = pythonize::depythonize(context)?;
207+
let context_value: Value = pythonize::depythonize(context.as_any())?;
206208
let result = evaluate_int_flag(flag, &context_value, &state.flag_set_metadata);
207209

208210
match result.value {
@@ -223,7 +225,7 @@ impl FlagEvaluator {
223225
fn evaluate_float(
224226
&self,
225227
flag_key: String,
226-
context: &PyDict,
228+
context: &Bound<'_, PyDict>,
227229
default_value: f64,
228230
) -> PyResult<f64> {
229231
let state = self.state.as_ref().ok_or_else(|| {
@@ -236,7 +238,7 @@ impl FlagEvaluator {
236238
PyErr::new::<pyo3::exceptions::PyKeyError, _>(format!("Flag not found: {}", flag_key))
237239
})?;
238240

239-
let context_value: Value = pythonize::depythonize(context)?;
241+
let context_value: Value = pythonize::depythonize(context.as_any())?;
240242
let result = evaluate_float_flag(flag, &context_value, &state.flag_set_metadata);
241243

242244
match result.value {
@@ -251,7 +253,7 @@ impl FlagEvaluator {
251253
/// This module provides native Python bindings for the flagd-evaluator library,
252254
/// offering high-performance feature flag evaluation.
253255
#[pymodule]
254-
fn flagd_evaluator(_py: Python, m: &PyModule) -> PyResult<()> {
256+
fn flagd_evaluator(m: &Bound<'_, PyModule>) -> PyResult<()> {
255257
m.add_class::<FlagEvaluator>()?;
256258
Ok(())
257259
}

0 commit comments

Comments
 (0)