pyreqwest 0.6.0__cp314-cp314-macosx_10_12_x86_64.whl → 0.10.1__cp314-cp314-macosx_10_12_x86_64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Binary file
@@ -5,17 +5,15 @@ from pyreqwest._pyreqwest.client import (
5
5
  BaseClientBuilder,
6
6
  Client,
7
7
  ClientBuilder,
8
- Runtime,
9
8
  SyncClient,
10
9
  SyncClientBuilder,
11
10
  )
12
11
 
13
- __all__ = [ # noqa: RUF022
14
- "Client",
12
+ __all__ = [
13
+ "BaseClientBuilder",
15
14
  "ClientBuilder",
16
- "SyncClient",
17
15
  "SyncClientBuilder",
18
16
  "BaseClient",
19
- "BaseClientBuilder",
20
- "Runtime",
17
+ "Client",
18
+ "SyncClient",
21
19
  ]
@@ -103,13 +103,18 @@ class BaseClientBuilder:
103
103
  def base_url(self, url: Url | str) -> Self:
104
104
  """Set a base URL automatically prepended to relative request URLs."""
105
105
 
106
- def runtime(self, runtime: "Runtime") -> Self:
107
- """Use a custom runtime (advanced scenarios). Usually not needed. By default, a global runtime is used."""
106
+ def runtime_multithreaded(self, enable: bool) -> Self:
107
+ """Use multithreaded Tokio runtime for client. Default is single-threaded or as configured globally via
108
+ `pyreqwest.runtime` module.
109
+
110
+ Multithreaded runtime may improve performance for high concurrency workloads with complex requests.
111
+ See also `pyreqwest.runtime` module for configuring global multithreaded runtime behavior.
112
+ """
108
113
 
109
114
  def max_connections(self, max_connections: int | None) -> Self:
110
115
  """Maximum number of inflight requests. None means no limit. Default is None."""
111
116
 
112
- def error_for_status(self, enable: bool) -> Self:
117
+ def error_for_status(self, enable: bool = True) -> Self:
113
118
  """Enable automatic HTTP error raising (4xx/5xx)."""
114
119
 
115
120
  def user_agent(self, value: str) -> Self:
@@ -176,6 +181,14 @@ class BaseClientBuilder:
176
181
  def pool_max_idle_per_host(self, max_idle: int) -> Self:
177
182
  """Sets the maximum idle connection per host allowed in the pool."""
178
183
 
184
+ def connection_verbose(self, enable: bool) -> Self:
185
+ """Set whether connections should emit verbose logs. This should be used for debugging only.
186
+
187
+ Enabling this option will emit log messages at the Debug level for read and write operations on connections.
188
+ Note that logs are flushed to Python logging handling when request finishes or client closes. Logs can be
189
+ manually flushed by calling `pyreqwest.logging.flush_logs`.
190
+ """
191
+
179
192
  def http1_lower_case_headers(self) -> Self:
180
193
  """Send headers as lowercase instead of title case. Default is false.
181
194
 
@@ -198,13 +211,22 @@ class BaseClientBuilder:
198
211
  """
199
212
 
200
213
  def http1_only(self) -> Self:
201
- """Only use HTTP/1."""
214
+ """Only use HTTP/1. This is the default. This is consistent with reqwest opt-in http2 feature.
202
215
 
203
- def http09_responses(self) -> Self:
204
- """Allow HTTP/0.9 responses (very old / uncommon)."""
216
+ Same as `.http2(False)`
217
+ """
218
+
219
+ def http2(self, enabled: bool) -> Self:
220
+ """Enable or disable HTTP/2 support. Default is false. This is consistent with reqwest opt-in http2 feature.
221
+
222
+ When enabling, it is recommended to tune "http2_" settings for production usage based on expected workloads.
223
+ """
205
224
 
206
225
  def http2_prior_knowledge(self) -> Self:
207
- """Only use HTTP/2."""
226
+ """Only use HTTP/2.
227
+
228
+ When enabling, it is recommended to tune "http2_" settings for production usage based on expected workloads.
229
+ """
208
230
 
209
231
  def http2_initial_stream_window_size(self, value: int | None) -> Self:
210
232
  """Sets the SETTINGS_INITIAL_WINDOW_SIZE option for HTTP2 stream-level flow control. Default is 65K."""
@@ -230,6 +252,9 @@ class BaseClientBuilder:
230
252
  def http2_keep_alive_while_idle(self, enabled: bool) -> Self:
231
253
  """Sets whether HTTP2 keep-alive should apply while the connection is idle. Default is false."""
232
254
 
255
+ def http09_responses(self) -> Self:
256
+ """Allow HTTP/0.9 responses (very old / uncommon)."""
257
+
233
258
  def tcp_nodelay(self, enabled: bool) -> Self:
234
259
  """Set TCP_NODELAY (disable Nagle). Default is true."""
235
260
 
@@ -260,15 +285,9 @@ class BaseClientBuilder:
260
285
  def add_crl_pem(self, cert: bytes) -> Self:
261
286
  """Add a certificate revocation list from PEM data."""
262
287
 
263
- def tls_built_in_root_certs(self, enable: bool) -> Self:
264
- """Toggle built-in root cert usage. Defaults to true - built-in system certs will be used."""
265
-
266
288
  def identity_pem(self, buf: bytes) -> Self:
267
289
  """Sets the identity to be used for client certificate authentication."""
268
290
 
269
- def danger_accept_invalid_hostnames(self, enable: bool) -> Self:
270
- """Disable hostname verification (INSECURE). Defaults to false."""
271
-
272
291
  def danger_accept_invalid_certs(self, enable: bool) -> Self:
273
292
  """Disable certificate validation (INSECURE). Defaults to false."""
274
293
 
@@ -330,12 +349,3 @@ class SyncClientBuilder(BaseClientBuilder):
330
349
 
331
350
  def json_handler(self, *, loads: SyncJsonLoads | None = ..., dumps: JsonDumps | None = ...) -> Self:
332
351
  """Override JSON loads / dumps callables for this sync client."""
333
-
334
- class Runtime:
335
- """Tokio runtime instance. Usually not needed, as library global runtime is used by default."""
336
-
337
- def __init__(self) -> None:
338
- """Create a tokio runtime instance. This is an advanced feature."""
339
-
340
- async def close(self) -> None:
341
- """Shutdown runtime resources. Clients using this runtime won't work anymore after closing."""
@@ -1,7 +1,7 @@
1
1
  """Exception classes."""
2
2
 
3
3
  from json import JSONDecodeError as JSONDecodeError_
4
- from typing import Any, Generic, TypedDict, TypeVar
4
+ from typing import Any, TypedDict
5
5
 
6
6
 
7
7
  class Cause(TypedDict):
@@ -19,12 +19,10 @@ class CauseErrorDetails(TypedDict):
19
19
  class StatusErrorDetails(TypedDict):
20
20
  """Details for errors that have an associated HTTP status code."""
21
21
 
22
+ causes: list[Cause] | None
22
23
  status: int
23
24
 
24
25
 
25
- T = TypeVar("T", bound=CauseErrorDetails | StatusErrorDetails)
26
-
27
-
28
26
  class PyreqwestError(Exception):
29
27
  """Base class for all pyreqwest errors."""
30
28
 
@@ -35,41 +33,46 @@ class PyreqwestError(Exception):
35
33
  self.message = message
36
34
 
37
35
 
38
- class DetailedPyreqwestError(PyreqwestError, Generic[T]):
36
+ class DetailedPyreqwestError(PyreqwestError):
39
37
  """Base class for all pyreqwest errors with details.
40
38
 
41
39
  Details may be available in `details`.
42
40
  """
43
41
 
44
- def __init__(self, message: str, details: T) -> None:
42
+ def __init__(self, message: str, details: CauseErrorDetails) -> None:
45
43
  """Internally initialized."""
46
44
  assert isinstance(details, dict)
47
45
  PyreqwestError.__init__(self, message, details)
48
- self.details = details
46
+ self.details: CauseErrorDetails = details
49
47
 
50
48
 
51
- class RequestError(DetailedPyreqwestError[T], Generic[T]):
49
+ class RequestError(DetailedPyreqwestError):
52
50
  """Error while processing a request.
53
51
 
54
52
  Details may be available in `details`.
55
53
  """
56
54
 
57
55
 
58
- class StatusError(RequestError[StatusErrorDetails]):
56
+ class StatusError(RequestError):
59
57
  """Error due to HTTP 4xx or 5xx status code. Raised when `error_for_status` is enabled.
60
58
 
61
59
  The status code is available in `details["status"]`.
62
60
  """
63
61
 
62
+ def __init__(self, message: str, details: StatusErrorDetails) -> None:
63
+ """Internally initialized."""
64
+ RequestError.__init__(self, message, details)
65
+ self.details: StatusErrorDetails = details
66
+
64
67
 
65
- class RedirectError(RequestError[CauseErrorDetails]):
68
+ class RedirectError(RequestError):
66
69
  """Error due to too many redirects. Raised when `max_redirects` is exceeded.
67
70
 
68
71
  Cause details may be available in `details["causes"]`.
69
72
  """
70
73
 
71
74
 
72
- class DecodeError(RequestError[CauseErrorDetails]):
75
+ class DecodeError(RequestError):
73
76
  """Error while decoding the response.
74
77
 
75
78
  Cause details may be available in `details["causes"]`.
@@ -98,7 +101,7 @@ class JSONDecodeError(BodyDecodeError, JSONDecodeError_):
98
101
  BodyDecodeError.__init__(self, message, {"causes": details["causes"]})
99
102
 
100
103
 
101
- class TransportError(RequestError[CauseErrorDetails]):
104
+ class TransportError(RequestError):
102
105
  """Error while processing the transport layer.
103
106
 
104
107
  Cause details may be available in `details["causes"]`.
@@ -170,21 +173,21 @@ class WriteError(NetworkError):
170
173
  """
171
174
 
172
175
 
173
- class ClientClosedError(RequestError[CauseErrorDetails]):
176
+ class ClientClosedError(RequestError):
174
177
  """Error due to user closing the client while request was being processed.
175
178
 
176
179
  Cause details may be available in `details["causes"]`.
177
180
  """
178
181
 
179
182
 
180
- class BuilderError(DetailedPyreqwestError[CauseErrorDetails], ValueError):
183
+ class BuilderError(DetailedPyreqwestError, ValueError):
181
184
  """Error while building a request.
182
185
 
183
186
  Cause details may be available in `details["causes"]`.
184
187
  """
185
188
 
186
189
 
187
- class RequestPanicError(RequestError[CauseErrorDetails]):
190
+ class RequestPanicError(RequestError):
188
191
  """Error due to a panic in the request processing.
189
192
 
190
193
  This indicates a bug in pyreqwest or one of its dependencies.
@@ -9,7 +9,7 @@ from pyreqwest._pyreqwest.http import (
9
9
  Url,
10
10
  )
11
11
 
12
- __all__ = [ # noqa: RUF022
12
+ __all__ = [
13
13
  "Url",
14
14
  "HeaderMap",
15
15
  "Mime",
@@ -0,0 +1,7 @@
1
+ """Logging utilities for pyreqwest."""
2
+
3
+ from pyreqwest._pyreqwest.logging import flush_logs
4
+
5
+ __all__ = [
6
+ "flush_logs",
7
+ ]
@@ -0,0 +1,4 @@
1
+ def flush_logs() -> None:
2
+ """Flush pending Rust-side log messages to Python logging handling immediately. Logs are normally flushed when a
3
+ request finishes or client closes.
4
+ """
@@ -20,7 +20,15 @@ from pyreqwest.pytest_plugin.types import (
20
20
  QueryMatcher,
21
21
  UrlMatcher,
22
22
  )
23
- from pyreqwest.request import BaseRequestBuilder, Request, RequestBody, RequestBuilder, SyncRequestBuilder
23
+ from pyreqwest.request import (
24
+ BaseRequestBuilder,
25
+ OneOffRequestBuilder,
26
+ Request,
27
+ RequestBody,
28
+ RequestBuilder,
29
+ SyncOneOffRequestBuilder,
30
+ SyncRequestBuilder,
31
+ )
24
32
  from pyreqwest.response import BaseResponse, Response, ResponseBuilder, SyncResponse
25
33
  from pyreqwest.types import HeadersType
26
34
 
@@ -383,8 +391,19 @@ class ClientMocker:
383
391
  monkeypatch.setattr(klass, "build", lambda slf: build_patch(slf, orig_build_consumed))
384
392
  monkeypatch.setattr(klass, "build_streamed", lambda slf: build_patch(slf, orig_build_streamed))
385
393
 
394
+ def setup_oneoff(klass: type[BaseRequestBuilder], *, is_async: bool) -> None:
395
+ orig_send = klass.send # type: ignore[attr-defined]
396
+
397
+ def send_patch(self: BaseRequestBuilder) -> Any:
398
+ middleware = mocker._create_middleware() if is_async else mocker._create_sync_middleware()
399
+ return orig_send(self.with_middleware(middleware)) # type: ignore[attr-defined]
400
+
401
+ monkeypatch.setattr(klass, "send", send_patch)
402
+
386
403
  setup(RequestBuilder, is_async=True)
387
404
  setup(SyncRequestBuilder, is_async=False)
405
+ setup_oneoff(OneOffRequestBuilder, is_async=True)
406
+ setup_oneoff(SyncOneOffRequestBuilder, is_async=False)
388
407
 
389
408
  return mocker
390
409
 
@@ -3,23 +3,27 @@
3
3
  from pyreqwest._pyreqwest.request import (
4
4
  BaseRequestBuilder,
5
5
  ConsumedRequest,
6
+ OneOffRequestBuilder,
6
7
  Request,
7
8
  RequestBody,
8
9
  RequestBuilder,
9
10
  StreamRequest,
10
11
  SyncConsumedRequest,
12
+ SyncOneOffRequestBuilder,
11
13
  SyncRequestBuilder,
12
14
  SyncStreamRequest,
13
15
  )
14
16
 
15
- __all__ = [ # noqa: RUF022
17
+ __all__ = [
18
+ "BaseRequestBuilder",
19
+ "RequestBuilder",
20
+ "SyncRequestBuilder",
21
+ "Request",
16
22
  "ConsumedRequest",
17
23
  "StreamRequest",
18
24
  "SyncConsumedRequest",
19
25
  "SyncStreamRequest",
20
- "Request",
21
- "RequestBuilder",
22
- "SyncRequestBuilder",
23
- "BaseRequestBuilder",
24
26
  "RequestBody",
27
+ "OneOffRequestBuilder",
28
+ "SyncOneOffRequestBuilder",
25
29
  ]
@@ -123,7 +123,7 @@ class RequestBody:
123
123
  """Copy body (Zero-copied bytes. Stream supplies its own copy)."""
124
124
 
125
125
  class BaseRequestBuilder:
126
- def error_for_status(self, enable: bool) -> Self:
126
+ def error_for_status(self, enable: bool = True) -> Self:
127
127
  """Enable automatic HTTP error raising (4xx/5xx)."""
128
128
 
129
129
  def header(self, name: str, value: str) -> Self:
@@ -182,7 +182,7 @@ class RequestBuilder(BaseRequestBuilder):
182
182
  """Set streaming request body."""
183
183
 
184
184
  def with_middleware(self, middleware: Middleware) -> Self:
185
- """Register a middleware component (added after client level middlewares, executed in chain order)."""
185
+ """Use a middleware component (added after client level middlewares, executed in chain order)."""
186
186
 
187
187
  class SyncRequestBuilder(BaseRequestBuilder):
188
188
  """Synchronous request builder. Use `build()` or `build_streamed()` to create the request to send."""
@@ -197,4 +197,22 @@ class SyncRequestBuilder(BaseRequestBuilder):
197
197
  """Set streaming request body."""
198
198
 
199
199
  def with_middleware(self, middleware: SyncMiddleware) -> Self:
200
- """Register a middleware component (added after client level middlewares, executed in chain order)."""
200
+ """Use a middleware component (added after client level middlewares, executed in chain order)."""
201
+
202
+ class OneOffRequestBuilder(BaseRequestBuilder):
203
+ """One-off request builder. Use `send()` to execute the request."""
204
+
205
+ async def send(self) -> Response:
206
+ """Execute the request returning a Response with fully read response body."""
207
+
208
+ def with_middleware(self, middleware: Middleware) -> Self:
209
+ """Use a middleware component."""
210
+
211
+ class SyncOneOffRequestBuilder(BaseRequestBuilder):
212
+ """Synchronous one-off request builder. Use `send()` to execute the request."""
213
+
214
+ def send(self) -> SyncResponse:
215
+ """Execute the request returning a Response with fully read response body."""
216
+
217
+ def with_middleware(self, middleware: SyncMiddleware) -> Self:
218
+ """Use a middleware component."""
@@ -9,10 +9,10 @@ from pyreqwest._pyreqwest.response import (
9
9
  SyncResponseBodyReader,
10
10
  )
11
11
 
12
- __all__ = [ # noqa: RUF022
12
+ __all__ = [
13
+ "BaseResponse",
13
14
  "Response",
14
15
  "SyncResponse",
15
- "BaseResponse",
16
16
  "ResponseBuilder",
17
17
  "ResponseBodyReader",
18
18
  "SyncResponseBodyReader",
@@ -101,13 +101,13 @@ class ResponseBuilder:
101
101
  def build_sync(self) -> SyncResponse:
102
102
  """Build synchronous response (disallows async streams)."""
103
103
 
104
- def status(self, value: int) -> Self:
104
+ def status(self, status: int) -> Self:
105
105
  """Set status code."""
106
106
 
107
- def version(self, value: str) -> Self:
107
+ def version(self, version: str) -> Self:
108
108
  """Set HTTP version string."""
109
109
 
110
- def header(self, name: str, value: str) -> Self:
110
+ def header(self, key: str, value: str) -> Self:
111
111
  """Append single header value (multiple allowed)."""
112
112
 
113
113
  def headers(self, headers: HeadersType) -> Self:
@@ -0,0 +1,15 @@
1
+ """Runtime configuration. See Tokio runtime documentation for details about config parameters."""
2
+
3
+ from pyreqwest._pyreqwest.runtime import (
4
+ runtime_blocking_thread_keep_alive,
5
+ runtime_max_blocking_threads,
6
+ runtime_multithreaded_default,
7
+ runtime_worker_threads,
8
+ )
9
+
10
+ __all__ = [
11
+ "runtime_multithreaded_default",
12
+ "runtime_worker_threads",
13
+ "runtime_max_blocking_threads",
14
+ "runtime_blocking_thread_keep_alive",
15
+ ]
@@ -0,0 +1,25 @@
1
+ from datetime import timedelta
2
+
3
+ def runtime_multithreaded_default(enable: bool | None) -> None:
4
+ """Enable to use multithreaded runtime by default. None uses default behavior which is to use single-threaded
5
+ runtime.
6
+ """
7
+
8
+ def runtime_worker_threads(threads: int | None) -> None:
9
+ """Set the number of worker threads for the multithreaded runtime. None uses default Tokio behavior which is the
10
+ number of cores available to the system.
11
+
12
+ Should be configured at startup. Can not be changed after multithreaded runtime has been initialized.
13
+ """
14
+
15
+ def runtime_max_blocking_threads(threads: int | None) -> None:
16
+ """Set the maximum number of blocking threads for the multithreaded runtime. None uses default Tokio behavior.
17
+
18
+ Should be configured at startup. Can not be changed after multithreaded runtime has been initialized.
19
+ """
20
+
21
+ def runtime_blocking_thread_keep_alive(duration: timedelta | None) -> None:
22
+ """Set the keep-alive time for blocking threads in the multithreaded runtime. None uses default Tokio behavior.
23
+
24
+ Should be configured at startup. Can not be changed after multithreaded runtime has been initialized.
25
+ """
@@ -0,0 +1 @@
1
+ """Simple interfaces for doing one-off requests."""
@@ -0,0 +1,21 @@
1
+ """Simple async interfaces for doing one-off requests."""
2
+
3
+ from pyreqwest._pyreqwest.simple.request import (
4
+ pyreqwest_delete,
5
+ pyreqwest_get,
6
+ pyreqwest_head,
7
+ pyreqwest_patch,
8
+ pyreqwest_post,
9
+ pyreqwest_put,
10
+ pyreqwest_request,
11
+ )
12
+
13
+ __all__ = [
14
+ "pyreqwest_request",
15
+ "pyreqwest_get",
16
+ "pyreqwest_post",
17
+ "pyreqwest_put",
18
+ "pyreqwest_patch",
19
+ "pyreqwest_delete",
20
+ "pyreqwest_head",
21
+ ]
@@ -0,0 +1,29 @@
1
+ from pyreqwest.http import Url
2
+ from pyreqwest.request import OneOffRequestBuilder
3
+
4
+ def pyreqwest_request(method: str, url: Url | str) -> OneOffRequestBuilder:
5
+ """Create a simple request with the given HTTP method and URL.
6
+
7
+ Returns a request builder, which will allow setting headers and the request body before sending.
8
+
9
+ NOTE: This is only recommended for simple scripting use-cases. Usually, the client should be reused for multiple
10
+ requests to benefit from connection pooling and other optimizations (via ClientBuilder).
11
+ """
12
+
13
+ def pyreqwest_get(url: Url | str) -> OneOffRequestBuilder:
14
+ """Same as `pyreqwest_request("GET", url)`."""
15
+
16
+ def pyreqwest_post(url: Url | str) -> OneOffRequestBuilder:
17
+ """Same as `pyreqwest_request("POST", url)`."""
18
+
19
+ def pyreqwest_put(url: Url | str) -> OneOffRequestBuilder:
20
+ """Same as `pyreqwest_request("PUT", url)`."""
21
+
22
+ def pyreqwest_patch(url: Url | str) -> OneOffRequestBuilder:
23
+ """Same as `pyreqwest_request("PATCH", url)`."""
24
+
25
+ def pyreqwest_delete(url: Url | str) -> OneOffRequestBuilder:
26
+ """Same as `pyreqwest_request("DELETE", url)`."""
27
+
28
+ def pyreqwest_head(url: Url | str) -> OneOffRequestBuilder:
29
+ """Same as `pyreqwest_request("HEAD", url)`."""
@@ -0,0 +1,21 @@
1
+ """Simple sync interfaces for doing one-off requests."""
2
+
3
+ from pyreqwest._pyreqwest.simple.sync_request import (
4
+ pyreqwest_delete,
5
+ pyreqwest_get,
6
+ pyreqwest_head,
7
+ pyreqwest_patch,
8
+ pyreqwest_post,
9
+ pyreqwest_put,
10
+ pyreqwest_request,
11
+ )
12
+
13
+ __all__ = [
14
+ "pyreqwest_request",
15
+ "pyreqwest_get",
16
+ "pyreqwest_post",
17
+ "pyreqwest_put",
18
+ "pyreqwest_patch",
19
+ "pyreqwest_delete",
20
+ "pyreqwest_head",
21
+ ]
@@ -0,0 +1,29 @@
1
+ from pyreqwest.http import Url
2
+ from pyreqwest.request import SyncOneOffRequestBuilder
3
+
4
+ def pyreqwest_request(method: str, url: Url | str) -> SyncOneOffRequestBuilder:
5
+ """Create a simple request with the given HTTP method and URL.
6
+
7
+ Returns a request builder, which will allow setting headers and the request body before sending.
8
+
9
+ NOTE: This is only recommended for simple scripting use-cases. Usually, the client should be reused for multiple
10
+ requests to benefit from connection pooling and other optimizations (via ClientBuilder).
11
+ """
12
+
13
+ def pyreqwest_get(url: Url | str) -> SyncOneOffRequestBuilder:
14
+ """Same as `pyreqwest_request("GET", url)`."""
15
+
16
+ def pyreqwest_post(url: Url | str) -> SyncOneOffRequestBuilder:
17
+ """Same as `pyreqwest_request("POST", url)`."""
18
+
19
+ def pyreqwest_put(url: Url | str) -> SyncOneOffRequestBuilder:
20
+ """Same as `pyreqwest_request("PUT", url)`."""
21
+
22
+ def pyreqwest_patch(url: Url | str) -> SyncOneOffRequestBuilder:
23
+ """Same as `pyreqwest_request("PATCH", url)`."""
24
+
25
+ def pyreqwest_delete(url: Url | str) -> SyncOneOffRequestBuilder:
26
+ """Same as `pyreqwest_request("DELETE", url)`."""
27
+
28
+ def pyreqwest_head(url: Url | str) -> SyncOneOffRequestBuilder:
29
+ """Same as `pyreqwest_request("HEAD", url)`."""
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pyreqwest
3
- Version: 0.6.0
3
+ Version: 0.10.1
4
4
  Classifier: Development Status :: 4 - Beta
5
5
  Classifier: Programming Language :: Python
6
6
  Classifier: Programming Language :: Python :: 3
@@ -100,6 +100,42 @@ def example_sync():
100
100
 
101
101
  Context manager usage is optional, but recommended. Also `close()` methods are available.
102
102
 
103
+ #### Mocking in pytest
104
+
105
+ ```python
106
+ from pyreqwest.client import ClientBuilder
107
+ from pyreqwest.pytest_plugin import ClientMocker
108
+
109
+ async def test_client(client_mocker: ClientMocker) -> None:
110
+ client_mocker.get(path="/api").with_body_text("Hello Mock")
111
+
112
+ async with ClientBuilder().build() as client:
113
+ response = await client.get("http://example.invalid/api").build().send()
114
+ assert response.status == 200 and await response.text() == "Hello Mock"
115
+ assert client_mocker.get_call_count() == 1
116
+ ```
117
+
118
+ Manual mocking is available via `ClientMocker.create_mocker(MonkeyPatch)`.
119
+
120
+ #### Simple request interface
121
+
122
+ This is only recommended for simple use-cases such as scripts. Usually, the full client API should be used which reuses
123
+ connections and has other optimizations.
124
+
125
+ ```python
126
+ # Sync example
127
+ from pyreqwest.simple.sync_request import pyreqwest_get
128
+ response = pyreqwest_get("https://httpbun.com/get").query({"q": "val"}).send()
129
+ print(response.json())
130
+ ```
131
+
132
+ ```python
133
+ # Async example
134
+ from pyreqwest.simple.request import pyreqwest_get
135
+ response = await pyreqwest_get("https://httpbun.com/get").query({"q": "val"}).send()
136
+ print(await response.json())
137
+ ```
138
+
103
139
  ## Documentation
104
140
 
105
141
  See [docs](https://markussintonen.github.io/pyreqwest/pyreqwest.html)
@@ -1,14 +1,10 @@
1
- pyreqwest-0.6.0.dist-info/METADATA,sha256=vWepMhQitXcL4ksYIzjgOpIp9OoL-HN8KGiqtIuMxB8,4678
2
- pyreqwest-0.6.0.dist-info/WHEEL,sha256=0p9RWqZ1tTIS4XVGVX-OqQSPs2Wp470cV_pQ0zUt98A,107
3
- pyreqwest-0.6.0.dist-info/entry_points.txt,sha256=x6BM9g8m805tw6VqKvSe_Kgd2qp4Eq3moyIoFnETeoE,61
4
- pyreqwest-0.6.0.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
5
1
  pyreqwest/__init__.py,sha256=AqtJmAtOEQ6kYGY2_Qzw2f_q5K3Q5PN-TpOmIKaeiEM,86
6
2
  pyreqwest/__init__.pyi,sha256=Y25n44pyE3vp92MiABKrcK3IWRyQ1JG1rZ4Ufqy2nC0,17
7
- pyreqwest/_pyreqwest.cpython-314-darwin.so,sha256=NXF4_HUhCzKpuZVmHMGVWgt4hZxEwGex2ZASwgE-Dgk,6717524
3
+ pyreqwest/_pyreqwest.cpython-314-darwin.so,sha256=uda6d-wGz24qisls7vVJWgIkBpZBMjDhF6hoYo-uFss,9218600
8
4
  pyreqwest/bytes/__init__.py,sha256=uzB8cxWbBizu0kyrdXhmnwWKWdwBcVIv4mgEhCR1LMs,465
9
5
  pyreqwest/bytes/__init__.pyi,sha256=bttN8uCg7K3gW90FBgPP4vbtNrBCOwqX4v7LAK-T1pU,4569
10
- pyreqwest/client/__init__.py,sha256=tPfCyh-HJJEepvGMvLSLjKkZySTKsATsnbJziT_P4IM,369
11
- pyreqwest/client/__init__.pyi,sha256=y9AfLH2Dhw8UOnnia1hk1qVGjAGW43LGT3dwqZfEVm4,14231
6
+ pyreqwest/client/__init__.py,sha256=37hK94Tz4MKvCJiYl9H_ZYVXF0CExX4Om-grcPIC9oY,325
7
+ pyreqwest/client/__init__.pyi,sha256=9QjOlirKKXAPqi49JpL8X0HOcumFXfchabUKlI9Jx5k,14832
12
8
  pyreqwest/client/types.py,sha256=CpfplqBGOyvpZNpwbOqal89dBztZlZTYuX-nM1Qrwrg,1475
13
9
  pyreqwest/compatibility/__init__.py,sha256=yJ4VD9iMzvSpYDjM6kEM-F2A_avMFCkOo1g5bgD2AGU,102
14
10
  pyreqwest/compatibility/httpx/__init__.py,sha256=Gc0jMCgmpSHkqQha_zAzxXjrbRSvS6KUOnHp4Z0UMDc,334
@@ -16,9 +12,11 @@ pyreqwest/compatibility/httpx/_internal.py,sha256=olu1ES7bV8AHUqtEMEmGHlejQCxAS3
16
12
  pyreqwest/compatibility/httpx/transport.py,sha256=2wuhREEvpWvcrCZcNv0mH_7MbuqwCO0_b9j7TMxkee8,6672
17
13
  pyreqwest/cookie/__init__.py,sha256=whcJaTtVHgqH2n_lvGYXYHP7D9BolDU6SvKjuKpewAs,128
18
14
  pyreqwest/cookie/__init__.pyi,sha256=YCOI79evRpc7xmSpY6q1MsQMCHSucGDpLmsk0ZqfXN4,6401
19
- pyreqwest/exceptions/__init__.py,sha256=LWD8I6hFsw0ogHwpobPVcO5tfFRhRg0rPF2Bs64XjuI,5319
20
- pyreqwest/http/__init__.py,sha256=cXbHvSjZhMc7Zi_8JWjEn9GVzT6HG6BBbuk0xwSqMiA,334
15
+ pyreqwest/exceptions/__init__.py,sha256=BiKq0hwV7nqu6f2K0Am_BXC9vvuD8snvWbkRLRFZm4Q,5360
16
+ pyreqwest/http/__init__.py,sha256=hyzkUQ8bj_xrPfOPYwUx0NpahQFFMWzpm2wKCmBe3ug,318
21
17
  pyreqwest/http/__init__.pyi,sha256=xmG6eD1Uz0Y1nRgPb_zxUMKc57rgxWq58W5nsCRg9V0,13798
18
+ pyreqwest/logging/__init__.py,sha256=KCmYt3ssr69rMe5u3ywFv2cbMOkj4Nz7qxdaBlu_CNc,125
19
+ pyreqwest/logging/__init__.pyi,sha256=b4Pl_LkY7jLUqidazrNFIrLB4kAAgUTdjT1Tr6_-2RQ,190
22
20
  pyreqwest/middleware/__init__.py,sha256=0i12zyrey3OmmKLtYRLTK4goC7QHWi0Di5erhe4VYHw,118
23
21
  pyreqwest/middleware/__init__.pyi,sha256=dkrwXkePVkvQNa4xe0l0-L-4WL3VsrNdJOO1-zNGApo,476
24
22
  pyreqwest/middleware/asgi/__init__.py,sha256=jLj4n6F4O2SKOl6HyufmSEvldDOQ1seWtcZPLOxZCyw,95
@@ -35,11 +33,22 @@ pyreqwest/pytest_plugin/internal/assert_eq.py,sha256=j4bEJPHWZvLAvSKqS3eCFViI0X8
35
33
  pyreqwest/pytest_plugin/internal/assert_message.py,sha256=oRkvzpIFw69rOaGTYBFGd8gP1Piut_RpG8G51OhYbes,4853
36
34
  pyreqwest/pytest_plugin/internal/matcher.py,sha256=aB08rUdI3rLQL2pMxerYAD-S8p1TeFUl36i0G2-tdgs,1221
37
35
  pyreqwest/pytest_plugin/internal/plugin.py,sha256=NkneUC5Ui-1ATlrG0q-R4_xdkA_Ou3UEF3t6qAlhS_M,448
38
- pyreqwest/pytest_plugin/mock.py,sha256=f3Zdy0CAlPc4RVZcSktPU6WfrhAmCtbzZnZyxizizqI,20315
36
+ pyreqwest/pytest_plugin/mock.py,sha256=0eFdaXQB4BsfBg3R5ctOShg5yCEgyLlm1mdI44Rynpo,20995
39
37
  pyreqwest/pytest_plugin/types.py,sha256=QyFxjkth7favATSwt3d8EtUBcVjqcUYQ5BxA617T54g,895
40
- pyreqwest/request/__init__.py,sha256=D5JI5nbfJgBgnGK_2fxCR1bPjGhy-yr1U4PoPY_RtsM,504
41
- pyreqwest/request/__init__.pyi,sha256=UB9IMIep6xwCvinv7OD9lNTNYLw-kkxdVMEqvVDRFkk,7149
42
- pyreqwest/response/__init__.py,sha256=u1M-aMKJdS3EQ9NqANnpnZ4S2XeWsM2ncd73Oj7T1_E,373
43
- pyreqwest/response/__init__.pyi,sha256=8hebHvfuWadg4zi0esEMJikTrXE296DlWHbYGGkLNfQ,5737
38
+ pyreqwest/request/__init__.py,sha256=zr4G_-kES2pN2HZ5nhbRbpwtEWooLJDX01KXrlUMET4,604
39
+ pyreqwest/request/__init__.pyi,sha256=eLbFMU9_dSMtfMhaWf79lr1TlFmXl8vRfUOq_v-LejU,7868
40
+ pyreqwest/response/__init__.py,sha256=40wLYwCOzIALl8qZecVLT-qj14Jf5EYTnW7CPVjIvzQ,357
41
+ pyreqwest/response/__init__.pyi,sha256=gfgXNg4q7GZfYgUesw_zyY4slwvso0bzNY-E8__iFZY,5739
42
+ pyreqwest/runtime/__init__.py,sha256=wdw_AyBkN9a98l3nmzoUhp5Wcfa1BIKB3PpGhAWY_eI,441
43
+ pyreqwest/runtime/__init__.pyi,sha256=ndUeESCWse43tDdg3yQa_7utPzEW4EImCvb5tyUXqs8,1168
44
+ pyreqwest/simple/__init__.py,sha256=kNB7FA92J7OlFnPMColUkUQjEQq_3GTiNWbE2BmHG7k,52
45
+ pyreqwest/simple/request/__init__.py,sha256=INoWzPcGE_O15wzfJ1tZwy5j0ua0GUAiPDcqwj1qI7Q,428
46
+ pyreqwest/simple/request/__init__.pyi,sha256=p9BSuuQh1rJk44xwdJhGV8apGPvdB0qAo2HWwqQYj8E,1227
47
+ pyreqwest/simple/sync_request/__init__.py,sha256=8Jv0wYehivbmscZvpOPkwHpIqNGEIY4x4hZPB5zv2rU,432
48
+ pyreqwest/simple/sync_request/__init__.pyi,sha256=heyLHDzLPuePzTeX7DLpc9IyTEEHeZKOSjXis0j6BF8,1259
44
49
  pyreqwest/types.py,sha256=10lGx5uugbo5awMz6nNOcuIsyeG3NIB7DqQHiPbOHLk,643
45
- pyreqwest-0.6.0.dist-info/RECORD,,
50
+ pyreqwest-0.10.1.dist-info/METADATA,sha256=0gUNNuHUolKXcl0-t3d5UoA3ZIjiDy4_pmUF9CgFq6o,5851
51
+ pyreqwest-0.10.1.dist-info/WHEEL,sha256=jyP0hJCe-fSX_gEscesIqqW7KerDJw7iyldGx-__w10,107
52
+ pyreqwest-0.10.1.dist-info/entry_points.txt,sha256=x6BM9g8m805tw6VqKvSe_Kgd2qp4Eq3moyIoFnETeoE,61
53
+ pyreqwest-0.10.1.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
54
+ pyreqwest-0.10.1.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: maturin (1.10.2)
2
+ Generator: maturin (1.11.5)
3
3
  Root-Is-Purelib: false
4
4
  Tag: cp314-cp314-macosx_10_12_x86_64