// yt - A fully featured command line YouTube client // // Copyright (C) 2025 Benedikt Peetz // SPDX-License-Identifier: GPL-3.0-or-later // // This file is part of Yt. // // You should have received a copy of the License along with this program. // If not, see . use pyo3::{ Bound, Python, intern, types::{PyAnyMethods, PyDict}, }; pub type InfoJson = serde_json::Map; /// # Panics /// If expectation about python operations fail. #[must_use] pub fn json_loads( input: serde_json::Map, py: Python<'_>, ) -> Bound<'_, PyDict> { let json = py.import(intern!(py, "json")).expect("Module exists"); let loads = json.getattr(intern!(py, "loads")).expect("Method exists"); let self_str = serde_json::to_string(&serde_json::Value::Object(input)).expect("Vaild json"); let dict = loads .call((self_str,), None) .expect("Vaild json is always a valid dict"); dict.cast_into().expect("Should always be a dict") } /// # Panics /// If expectation about python operations fail. #[must_use] pub fn json_dumps(input: &Bound<'_, PyDict>) -> serde_json::Map { let py = input.py(); let json = py.import(intern!(py, "json")).expect("Module exists"); let dumps = json.getattr(intern!(py, "dumps")).expect("Method exists"); let dict = dumps .call((input,), None) .map_err(|err| err.print(py)) .expect("Might not always work, but for our dicts it works"); let string: String = dict.extract().expect("Should always be a string"); let value: serde_json::Value = serde_json::from_str(&string).expect("Should be valid json"); match value { serde_json::Value::Object(map) => map, _ => unreachable!("These should not be json.dumps output"), } } /// # Panics /// If expectation about python operations fail. #[must_use] pub fn filter_dict(input: Bound<'_, PyDict>) -> Bound<'_, PyDict> { let new_dict = PyDict::new(input.py()); input .into_iter() .filter_map(|(name, value)| { let real_name = name.extract::().expect("Should always be a string"); if real_name.starts_with('_') { None } else { let value = if value.is_instance_of::() { filter_dict( value .cast_into::() .expect("to be a dict, because we checked"), ) .into_any() } else { value }; Some((real_name, value)) } }) .for_each(|(key, value)| { new_dict .set_item(&key, value) .expect("This is a transposition, should always be valid"); }); new_dict }