Skip to content

Commit

Permalink
Improve json handling: add static JSON_DUMPS and JSON_LOADS
Browse files Browse the repository at this point in the history
  • Loading branch information
deedy5 committed Aug 14, 2024
1 parent 84747aa commit a6cff1c
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 29 deletions.
8 changes: 5 additions & 3 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -246,9 +246,11 @@ impl Client {
.map(|data_pydict| url_encode(py, Some(data_pydict)).ok())
.unwrap_or_else(|| None);
// Converts 'json' (if any) into a JSON string for sending the data as `application/json` content type.
let json_str = json
.map(|json_pydict| json_dumps(py, Some(json_pydict)).ok())
.unwrap_or_else(|| None);
let json_str = json
.map(|json_pydict| {
json_dumps(py).call1((json_pydict.clone().unbind(),)).unwrap().extract::<String>().ok()
})
.unwrap_or(None);

let future = async move {
// Check if method is POST || PUT || PATCH
Expand Down
8 changes: 4 additions & 4 deletions src/response.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::utils::{get_encoding_from_content, get_encoding_from_headers};
use crate::utils::{get_encoding_from_content, get_encoding_from_headers, json_loads};
use ahash::RandomState;
use anyhow::{anyhow, Result};
use encoding_rs::Encoding;
Expand Down Expand Up @@ -78,9 +78,9 @@ impl Response {
}

fn json(&mut self, py: Python) -> Result<PyObject> {
let json_module = PyModule::import_bound(py, "json")?;
let loads = json_module.getattr("loads")?;
let result = loads.call1((&self.content,))?.extract::<PyObject>()?;
let result = json_loads(py)
.call1((&self.content,))?
.extract::<PyObject>()?;
Ok(result)
}

Expand Down
64 changes: 42 additions & 22 deletions src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,50 @@ use std::cmp::min;
use ahash::RandomState;
use indexmap::IndexMap;
use pyo3::prelude::*;
use pyo3::sync::GILOnceCell;
use pyo3::types::{PyBool, PyDict};

static JSON_DUMPS: GILOnceCell<Py<PyAny>> = GILOnceCell::new();
static JSON_LOADS: GILOnceCell<Py<PyAny>> = GILOnceCell::new();

/// python json.dumps
pub fn json_dumps(py: Python<'_>) -> &Bound<'_, PyAny> {
JSON_DUMPS
.get_or_init(py, || {
py.import_bound("json")
.unwrap()
.getattr("dumps")
.unwrap()
.unbind()
})
.bind(py)
}

/// python json.loads
pub fn json_loads(py: Python<'_>) -> &Bound<'_, PyAny> {
JSON_LOADS
.get_or_init(py, || {
py.import_bound("json")
.unwrap()
.getattr("loads")
.unwrap()
.unbind()
})
.bind(py)
}

/// python urllib.parse.urlencode
pub fn url_encode(py: Python, pydict: Option<&Bound<'_, PyDict>>) -> PyResult<String> {
let urllib_parse = PyModule::import_bound(py, "urllib.parse")?;
let urlencode = urllib_parse.getattr("urlencode")?;
match pydict {
Some(dict) => urlencode
.call1((dict, ("doseq", py.get_type_bound::<PyBool>().call1(())?)))?
.extract::<String>(),
None => Ok("".to_string()),
}
}

/// Get encoding from the "Content-Type" header
pub fn get_encoding_from_headers(
headers: &IndexMap<String, String, RandomState>,
Expand Down Expand Up @@ -56,28 +98,6 @@ pub fn get_encoding_from_content(raw_bytes: &[u8]) -> Option<String> {
}
}

/// python json.dumps
pub fn json_dumps(py: Python, pydict: Option<&Bound<'_, PyDict>>) -> PyResult<String> {
let json_module = PyModule::import_bound(py, "json")?;
let dumps = json_module.getattr("dumps")?;
match pydict {
Some(dict) => dumps.call1((dict,))?.extract::<String>(),
None => Ok("".to_string()),
}
}

/// python urllib.parse.urlencode
pub fn url_encode(py: Python, pydict: Option<&Bound<'_, PyDict>>) -> PyResult<String> {
let urllib_parse = PyModule::import_bound(py, "urllib.parse")?;
let urlencode = urllib_parse.getattr("urlencode")?;
match pydict {
Some(dict) => urlencode
.call1((dict, ("doseq", py.get_type_bound::<PyBool>().call1(())?)))?
.extract::<String>(),
None => Ok("".to_string()),
}
}

#[cfg(test)]
mod utils_tests {
use super::*;
Expand Down

0 comments on commit a6cff1c

Please sign in to comment.