aboutsummaryrefslogtreecommitdiffstats
path: root/crates/yt_dlp/src/lib.rs
diff options
context:
space:
mode:
authorBenedikt Peetz <benedikt.peetz@b-peetz.de>2024-10-14 18:05:33 +0200
committerBenedikt Peetz <benedikt.peetz@b-peetz.de>2024-10-14 18:05:33 +0200
commit2c7980b773cad586af5db8ff0755f1d74d94f7d1 (patch)
tree5207aa3a69945ae7d5e5ef77ad14a50313954c25 /crates/yt_dlp/src/lib.rs
parentfeat(unreachable): Init trait (diff)
downloadyt-2c7980b773cad586af5db8ff0755f1d74d94f7d1.zip
refactor(treewide): Conform to the clippy and rust lints
Diffstat (limited to '')
-rw-r--r--crates/yt_dlp/src/lib.rs67
1 files changed, 46 insertions, 21 deletions
diff --git a/crates/yt_dlp/src/lib.rs b/crates/yt_dlp/src/lib.rs
index f958895..4e35cb0 100644
--- a/crates/yt_dlp/src/lib.rs
+++ b/crates/yt_dlp/src/lib.rs
@@ -8,6 +8,10 @@
// You should have received a copy of the License along with this program.
// If not, see <https://www.gnu.org/licenses/gpl-3.0.txt>.
+// The pyo3 `pyfunction` proc-macros call unsafe functions internally, which trigger this lint.
+#![allow(unsafe_op_in_unsafe_fn)]
+#![allow(clippy::missing_errors_doc)]
+
use std::env;
use std::{fs::File, io::Write};
@@ -31,14 +35,20 @@ pub mod duration;
pub mod logging;
pub mod wrapper;
+#[cfg(test)]
+mod tests;
+
/// Synchronisation helper, to ensure that we don't setup the logger multiple times
static SYNC_OBJ: Once = Once::new();
/// Add a logger to the yt-dlp options.
/// If you have an logger set (i.e. for rust), than this will log to rust
+///
+/// # Panics
+/// This should never panic.
pub fn add_logger_and_sig_handler<'a>(
opts: Bound<'a, PyDict>,
- py: Python,
+ py: Python<'_>,
) -> PyResult<Bound<'a, PyDict>> {
setup_logging(py, "yt_dlp")?;
@@ -52,10 +62,9 @@ pub fn add_logger_and_sig_handler<'a>(
// This allows the user to actually stop the application with Ctrl+C.
// This is here because it can only be run in the main thread and this was here already.
py.run_bound(
- r#"
+ "\
import signal
-signal.signal(signal.SIGINT, signal.SIG_DFL)
- "#,
+signal.signal(signal.SIGINT, signal.SIG_DFL)",
None,
None,
)
@@ -82,14 +91,22 @@ signal.signal(signal.SIGINT, signal.SIG_DFL)
}
#[pyfunction]
-pub fn progress_hook(py: Python, input: Bound<'_, PyDict>) -> PyResult<()> {
+#[allow(clippy::too_many_lines)]
+#[allow(clippy::missing_panics_doc)]
+#[allow(clippy::items_after_statements)]
+#[allow(
+ clippy::cast_possible_truncation,
+ clippy::cast_sign_loss,
+ clippy::cast_precision_loss
+)]
+pub fn progress_hook(py: Python<'_>, input: &Bound<'_, PyDict>) -> PyResult<()> {
// Only add the handler, if the log-level is higher than Debug (this avoids covering debug
// messages).
if log_enabled!(Level::Debug) {
return Ok(());
}
- let input: serde_json::Map<String, Value> = serde_json::from_str(&json_dumps(
+ let input: Map<String, Value> = serde_json::from_str(&json_dumps(
py,
input
.downcast::<PyAny>()
@@ -164,8 +181,9 @@ pub fn progress_hook(py: Python, input: Bound<'_, PyDict>) -> PyResult<()> {
}
fn format_speed(speed: f64) -> String {
+ #[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss)]
let bytes = Bytes::new(speed.floor() as u64);
- format!("{}/s", bytes)
+ format!("{bytes}/s")
}
let get_title = |add_extension: bool| -> String {
@@ -187,7 +205,7 @@ pub fn progress_hook(py: Python, input: Bound<'_, PyDict>) -> PyResult<()> {
default_get! { as_str, "<No title>", "info_dict", "title"}.to_owned()
}
}
- other => panic!("The extension '{}' is not yet implemented", other),
+ other => panic!("The extension '{other}' is not yet implemented"),
}
};
@@ -242,18 +260,18 @@ pub fn progress_hook(py: Python, input: Bound<'_, PyDict>) -> PyResult<()> {
);
}
"finished" => {
- println!("Finished downloading: '{}'", c!("34;1", get_title(false)))
+ println!("Finished downloading: '{}'", c!("34;1", get_title(false)));
}
"error" => {
panic!("Error whilst downloading: {}", get_title(true))
}
- other => panic!("{} is not a valid state!", other),
+ other => panic!("{other} is not a valid state!"),
};
Ok(())
}
-pub fn add_hooks<'a>(opts: Bound<'a, PyDict>, py: Python) -> PyResult<Bound<'a, PyDict>> {
+pub fn add_hooks<'a>(opts: Bound<'a, PyDict>, py: Python<'_>) -> PyResult<Bound<'a, PyDict>> {
if let Some(hooks) = opts.get_item("progress_hooks")? {
let hooks = hooks.downcast::<PyList>()?;
hooks.append(wrap_pyfunction_bound!(progress_hook, py)?)?;
@@ -280,10 +298,12 @@ pub fn add_hooks<'a>(opts: Bound<'a, PyDict>, py: Python) -> PyResult<Bound<'a,
/// @param download Whether to download videos
/// @param process Whether to resolve all unresolved references (URLs, playlist items).
/// Must be True for download to work
-/// @param ie_key Use only the extractor with this key
+/// @param `ie_key` Use only the extractor with this key
///
-/// @param extra_info Dictionary containing the extra values to add to the info (For internal use only)
-/// @force_generic_extractor Force using the generic extractor (Deprecated; use ie_key='Generic')
+/// @param `extra_info` Dictionary containing the extra values to add to the info (For internal use only)
+/// @`force_generic_extractor` Force using the generic extractor (Deprecated; use `ie_key`='Generic')
+#[allow(clippy::unused_async)]
+#[allow(clippy::missing_panics_doc)]
pub async fn extract_info(
yt_dlp_opts: &Map<String, Value>,
url: &Url,
@@ -311,8 +331,8 @@ pub async fn extract_info(
if let Ok(confirm) = env::var("YT_STORE_INFO_JSON") {
if confirm == "yes" {
- let mut file = File::create("output.info.json").unwrap();
- write!(file, "{}", result_str).unwrap();
+ let mut file = File::create("output.info.json")?;
+ write!(file, "{result_str}").unwrap();
}
}
@@ -321,7 +341,9 @@ pub async fn extract_info(
})
}
-pub fn unsmuggle_url(smug_url: Url) -> PyResult<Url> {
+/// # Panics
+/// Only if python fails to return a valid URL.
+pub fn unsmuggle_url(smug_url: &Url) -> PyResult<Url> {
Python::with_gil(|py| {
let utils = get_yt_dlp_utils(py)?;
let url = utils
@@ -341,6 +363,9 @@ pub fn unsmuggle_url(smug_url: Url) -> PyResult<Url> {
/// Download a given list of URLs.
/// Returns the paths they were downloaded to.
+///
+/// # Panics
+/// Only if `yt_dlp` changes their `info_json` schema.
pub async fn download(
urls: &[Url],
download_options: &Map<String, Value>,
@@ -357,7 +382,7 @@ pub async fn download(
} else {
info_json.requested_downloads.expect("This must exist")[0]
.filename
- .to_owned()
+ .clone()
};
out_paths.push(result_string);
@@ -378,7 +403,7 @@ fn json_map_to_py_dict<'a>(
Ok(python_dict)
}
-fn json_dumps(py: Python, input: Bound<PyAny>) -> PyResult<String> {
+fn json_dumps(py: Python<'_>, input: Bound<'_, PyAny>) -> PyResult<String> {
// json.dumps(yt_dlp.sanitize_info(input))
let yt_dlp = get_yt_dlp(py, PyDict::new_bound(py))?;
@@ -394,13 +419,13 @@ fn json_dumps(py: Python, input: Bound<PyAny>) -> PyResult<String> {
Ok(output_str)
}
-fn json_loads_str<T: Serialize>(py: Python, input: T) -> PyResult<Bound<PyDict>> {
+fn json_loads_str<T: Serialize>(py: Python<'_>, input: T) -> PyResult<Bound<'_, PyDict>> {
let string = serde_json::to_string(&input).expect("Correct json must be pased");
json_loads(py, string)
}
-fn json_loads(py: Python, input: String) -> PyResult<Bound<PyDict>> {
+fn json_loads(py: Python<'_>, input: String) -> PyResult<Bound<'_, PyDict>> {
// json.loads(input)
let json = PyModule::import_bound(py, "json")?;