Skip to content
Merged
8 changes: 8 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion impit-node/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ impl ImpitWrapper {
timeout: request_init
.as_ref()
.and_then(|init| init.timeout)
.map(|timeout| Duration::from_millis(timeout.into())),
.map(|timeout| Some(Duration::from_millis(timeout.into()))),
http3_prior_knowledge: request_init
.as_ref()
.and_then(|init| init.force_http3)
Expand Down
3 changes: 2 additions & 1 deletion impit-python/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,10 @@ h2 = "0.4.7"
reqwest = "0.13.1"
tokio-stream = "0.1.17"
bytes = "1.9.0"
pyo3 = { version = "0.28", features = ["extension-module", "auto-initialize"] }
pyo3 = { version = "0.28", features = ["extension-module", "auto-initialize", "either"] }
pyo3-async-runtimes = { version = "0.28", features = ["attributes", "async-std-runtime", "tokio-runtime"] }
urlencoding = "2.1.3"
encoding = "0.2.33"
cookie = "0.18.1"
futures = "0.3.31"
either = "1.15.0"
2 changes: 2 additions & 0 deletions impit-python/python/impit/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

from .cookies import Cookies
from .impit import (
USE_CLIENT_DEFAULT,
AsyncClient,
Client,
CloseError,
Expand Down Expand Up @@ -48,6 +49,7 @@
__version__ = metadata.version('impit')

__all__ = [
'USE_CLIENT_DEFAULT',
'AsyncClient',
'Browser',
'Client',
Expand Down
117 changes: 62 additions & 55 deletions impit-python/python/impit/impit.pyi

Large diffs are not rendered by default.

60 changes: 33 additions & 27 deletions impit-python/src/async_client.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use std::{collections::HashMap, sync::Arc, time::Duration};

use either::{Either, Right};
use impit::{
errors::ImpitError,
impit::{Impit, ImpitBuilder},
Expand All @@ -8,8 +9,10 @@ use impit::{
use pyo3::{exceptions::PyTypeError, ffi::c_str, prelude::*};

use crate::{
cookies::PythonCookieJar, errors::ImpitPyError, request::form_to_bytes,
response::ImpitPyResponse, RequestBody,
cookies::PythonCookieJar,
errors::ImpitPyError,
request::{form_to_bytes, parse_timeout, RequestBody, USE_CLIENT_DEFAULT_SENTINEL},
response::ImpitPyResponse,
};

#[pyclass]
Expand Down Expand Up @@ -38,13 +41,13 @@ impl AsyncClient {
}

#[new]
#[pyo3(signature = (browser=None, http3=None, proxy=None, timeout=None, verify=None, default_encoding=None, follow_redirects=None, max_redirects=Some(20), cookie_jar=None, cookies=None, headers=None, local_address=None))]
#[pyo3(signature = (browser=None, http3=None, proxy=None, timeout=Some(Right(USE_CLIENT_DEFAULT_SENTINEL)), verify=None, default_encoding=None, follow_redirects=None, max_redirects=Some(20), cookie_jar=None, cookies=None, headers=None, local_address=None))]
pub fn new(
py: Python<'_>,
browser: Option<String>,
http3: Option<bool>,
proxy: Option<String>,
timeout: Option<f64>,
timeout: Option<Either<f64, &str>>,
verify: Option<bool>,
default_encoding: Option<String>,
follow_redirects: Option<bool>,
Expand Down Expand Up @@ -107,8 +110,9 @@ impl AsyncClient {
None => builder,
};

let builder = match timeout {
Some(secs) => builder.with_default_timeout(Duration::from_secs_f64(secs)),
let builder = match parse_timeout(timeout)? {
Some(Some(d)) => builder.with_default_timeout(d),
Some(None) => builder.with_default_timeout(Duration::MAX),
None => builder,
};

Expand Down Expand Up @@ -160,15 +164,15 @@ impl AsyncClient {
})
}

#[pyo3(signature = (url, content=None, data=None, headers=None, timeout=None, force_http3=false))]
#[pyo3(signature = (url, content=None, data=None, headers=None, timeout=Some(Right(USE_CLIENT_DEFAULT_SENTINEL)), force_http3=false))]
pub fn get<'python>(
&self,
py: Python<'python>,
url: String,
content: Option<Vec<u8>>,
data: Option<RequestBody>,
headers: Option<HashMap<String, String>>,
timeout: Option<f64>,
timeout: Option<Either<f64, &str>>,
force_http3: Option<bool>,
) -> Result<pyo3::Bound<'python, PyAny>, PyErr> {
self.request(
Expand All @@ -184,15 +188,15 @@ impl AsyncClient {
)
}

#[pyo3(signature = (url, content=None, data=None, headers=None, timeout=None, force_http3=false))]
#[pyo3(signature = (url, content=None, data=None, headers=None, timeout=Some(Right(USE_CLIENT_DEFAULT_SENTINEL)), force_http3=false))]
pub fn head<'python>(
&self,
py: Python<'python>,
url: String,
content: Option<Vec<u8>>,
data: Option<RequestBody>,
headers: Option<HashMap<String, String>>,
timeout: Option<f64>,
timeout: Option<Either<f64, &str>>,
force_http3: Option<bool>,
) -> Result<pyo3::Bound<'python, PyAny>, PyErr> {
self.request(
Expand All @@ -208,15 +212,15 @@ impl AsyncClient {
)
}

#[pyo3(signature = (url, content=None, data=None, headers=None, timeout=None, force_http3=false))]
#[pyo3(signature = (url, content=None, data=None, headers=None, timeout=Some(Right(USE_CLIENT_DEFAULT_SENTINEL)), force_http3=false))]
pub fn post<'python>(
&self,
py: Python<'python>,
url: String,
content: Option<Vec<u8>>,
data: Option<RequestBody>,
headers: Option<HashMap<String, String>>,
timeout: Option<f64>,
timeout: Option<Either<f64, &str>>,
force_http3: Option<bool>,
) -> Result<pyo3::Bound<'python, PyAny>, PyErr> {
self.request(
Expand All @@ -232,15 +236,15 @@ impl AsyncClient {
)
}

#[pyo3(signature = (url, content=None, data=None, headers=None, timeout=None, force_http3=false))]
#[pyo3(signature = (url, content=None, data=None, headers=None, timeout=Some(Right(USE_CLIENT_DEFAULT_SENTINEL)), force_http3=false))]
pub fn patch<'python>(
&self,
py: Python<'python>,
url: String,
content: Option<Vec<u8>>,
data: Option<RequestBody>,
headers: Option<HashMap<String, String>>,
timeout: Option<f64>,
timeout: Option<Either<f64, &str>>,
force_http3: Option<bool>,
) -> Result<pyo3::Bound<'python, PyAny>, PyErr> {
self.request(
Expand All @@ -256,15 +260,15 @@ impl AsyncClient {
)
}

#[pyo3(signature = (url, content=None, data=None, headers=None, timeout=None, force_http3=false))]
#[pyo3(signature = (url, content=None, data=None, headers=None, timeout=Some(Right(USE_CLIENT_DEFAULT_SENTINEL)), force_http3=false))]
pub fn put<'python>(
&self,
py: Python<'python>,
url: String,
content: Option<Vec<u8>>,
data: Option<RequestBody>,
headers: Option<HashMap<String, String>>,
timeout: Option<f64>,
timeout: Option<Either<f64, &str>>,
force_http3: Option<bool>,
) -> Result<pyo3::Bound<'python, PyAny>, PyErr> {
self.request(
Expand All @@ -280,15 +284,15 @@ impl AsyncClient {
)
}

#[pyo3(signature = (url, content=None, data=None, headers=None, timeout=None, force_http3=false))]
#[pyo3(signature = (url, content=None, data=None, headers=None, timeout=Some(Right(USE_CLIENT_DEFAULT_SENTINEL)), force_http3=false))]
pub fn delete<'python>(
&self,
py: Python<'python>,
url: String,
content: Option<Vec<u8>>,
data: Option<RequestBody>,
headers: Option<HashMap<String, String>>,
timeout: Option<f64>,
timeout: Option<Either<f64, &str>>,
force_http3: Option<bool>,
) -> Result<pyo3::Bound<'python, PyAny>, PyErr> {
self.request(
Expand All @@ -304,15 +308,15 @@ impl AsyncClient {
)
}

#[pyo3(signature = (url, content=None, data=None, headers=None, timeout=None, force_http3=false))]
#[pyo3(signature = (url, content=None, data=None, headers=None, timeout=Some(Right(USE_CLIENT_DEFAULT_SENTINEL)), force_http3=false))]
pub fn options<'python>(
&self,
py: Python<'python>,
url: String,
content: Option<Vec<u8>>,
data: Option<RequestBody>,
headers: Option<HashMap<String, String>>,
timeout: Option<f64>,
timeout: Option<Either<f64, &str>>,
force_http3: Option<bool>,
) -> Result<pyo3::Bound<'python, PyAny>, PyErr> {
self.request(
Expand All @@ -328,15 +332,15 @@ impl AsyncClient {
)
}

#[pyo3(signature = (url, content=None, data=None, headers=None, timeout=None, force_http3=false))]
#[pyo3(signature = (url, content=None, data=None, headers=None, timeout=Some(Right(USE_CLIENT_DEFAULT_SENTINEL)), force_http3=false))]
pub fn trace<'python>(
&self,
py: Python<'python>,
url: String,
content: Option<Vec<u8>>,
data: Option<RequestBody>,
headers: Option<HashMap<String, String>>,
timeout: Option<f64>,
timeout: Option<Either<f64, &str>>,
force_http3: Option<bool>,
) -> Result<pyo3::Bound<'python, PyAny>, PyErr> {
self.request(
Expand All @@ -352,7 +356,7 @@ impl AsyncClient {
)
}

#[pyo3(signature = (method, url, content=None, data=None, headers=None, timeout=None, force_http3=false))]
#[pyo3(signature = (method, url, content=None, data=None, headers=None, timeout=Some(Right(USE_CLIENT_DEFAULT_SENTINEL)), force_http3=false))]
pub fn stream<'python>(
&self,
py: Python<'python>,
Expand All @@ -361,7 +365,7 @@ impl AsyncClient {
content: Option<Vec<u8>>,
data: Option<RequestBody>,
headers: Option<HashMap<String, String>>,
timeout: Option<f64>,
timeout: Option<Either<f64, &str>>,
force_http3: Option<bool>,
) -> Result<pyo3::Bound<'python, PyAny>, PyErr> {
let response = self.request(
Expand Down Expand Up @@ -398,7 +402,7 @@ impl AsyncClient {
Ok(wrapped_response.into_bound(py))
}

#[pyo3(signature = (method, url, content=None, data=None, headers=None, timeout=None, force_http3=false, stream=false))]
#[pyo3(signature = (method, url, content=None, data=None, headers=None, timeout=Some(Right(USE_CLIENT_DEFAULT_SENTINEL)), force_http3=false, stream=false))]
pub fn request<'python>(
&self,
py: Python<'python>,
Expand All @@ -407,7 +411,7 @@ impl AsyncClient {
content: Option<Vec<u8>>,
mut data: Option<RequestBody>,
headers: Option<HashMap<String, String>>,
timeout: Option<f64>,
timeout: Option<Either<f64, &str>>,
force_http3: Option<bool>,
stream: Option<bool>,
) -> Result<pyo3::Bound<'python, PyAny>, PyErr> {
Expand All @@ -434,13 +438,15 @@ impl AsyncClient {
None => Ok(Vec::new()),
}?;

let timeout = parse_timeout(timeout)?;

let options = RequestOptions {
headers: headers
.unwrap_or_default()
.iter()
.map(|(k, v)| (k.clone(), v.clone()))
.collect(),
timeout: timeout.map(Duration::from_secs_f64),
timeout,
http3_prior_knowledge: force_http3.unwrap_or(false),
};

Expand Down
Loading