redc 0.1.1.dev1__cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_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.
redc/client.py ADDED
@@ -0,0 +1,796 @@
1
+ from urllib.parse import urlencode
2
+
3
+ from .callbacks import StreamCallback, ProgressCallback
4
+ from .redc_ext import RedC
5
+ from .response import Response
6
+ from .utils import json_dumps, parse_base_url, Headers
7
+
8
+ import asyncio
9
+ import redc
10
+
11
+
12
+ class Client:
13
+ """RedC client for making HTTP requests"""
14
+
15
+ def __init__(
16
+ self,
17
+ base_url: str = None,
18
+ buffer_size: int = 16384,
19
+ headers: dict = None,
20
+ timeout: tuple = (30.0, 0.0),
21
+ ca_cert_path: str = None,
22
+ force_verbose: bool = None,
23
+ raise_for_status: bool = False,
24
+ json_encoder=json_dumps,
25
+ ):
26
+ """
27
+ Initialize the RedC client
28
+
29
+ Example:
30
+ .. code-block:: python
31
+
32
+ >>> client = Client(base_url="https://example.com")
33
+ >>> response = await client.get("/api/data")
34
+
35
+ Parameters:
36
+ base_url (``str``, *optional*):
37
+ The base URL for the client. Default is ``None``
38
+
39
+ buffer_size (``int``, *optional*):
40
+ The buffer size for libcurl. Must be greater than ``1024`` bytes. Default is ``16384`` (16KB)
41
+
42
+ headers (``dict``, *optional*):
43
+ Headers to include in every request. Default is ``None``
44
+
45
+ timeout (``tuple``, *optional*):
46
+ A tuple of `(total_timeout, connect_timeout)` in seconds to include in every request. Default is ``(30.0, 0.0)``
47
+
48
+ ca_cert_path (``str``, *optional*):
49
+ Path to a CA certificate bundle file for SSL/TLS verification. Default is ``None``
50
+
51
+ force_verbose (``bool``, *optional*):
52
+ Force verbose output for all requests. Default is ``None``
53
+
54
+ raise_for_status (``bool``, *optional*):
55
+ If ``True``, automatically raises an :class:`redc.HTTPError` for responses with HTTP status codes
56
+ indicating an error (i.e., 4xx or 5xx) or for CURL errors (e.g., network issues, timeouts). Default is ``False``
57
+
58
+ json_encoder (``Callable`` , *optional*):
59
+ A callable for encoding JSON data. Default is :class:`redc.utils.json_dumps`
60
+ """
61
+
62
+ assert isinstance(base_url, (str, type(None))), "base_url must be string"
63
+ assert isinstance(buffer_size, int), "buffer_size must be int"
64
+ assert isinstance(ca_cert_path, (str, type(None))), (
65
+ "ca_cert_path must be string"
66
+ )
67
+ assert isinstance(timeout, tuple) and len(timeout) == 2, (
68
+ "timeout must be a tuple of (total_timeout, connect_timeout)"
69
+ )
70
+ assert isinstance(force_verbose, (bool, type(None))), (
71
+ "force_verbose must be bool or None"
72
+ )
73
+ assert isinstance(raise_for_status, bool), "raise_for_status must be bool"
74
+
75
+ assert buffer_size >= 1024, "buffer_size must be bigger than 1024 bytes"
76
+
77
+ self.force_verbose = force_verbose
78
+ self.raise_for_status = raise_for_status
79
+
80
+ self.__base_url = (
81
+ parse_base_url(base_url) if isinstance(base_url, str) else None
82
+ )
83
+ self.__default_headers = Headers(headers if isinstance(headers, dict) else {})
84
+ self.__timeout = timeout
85
+ self.__ca_cert_path = ca_cert_path if isinstance(ca_cert_path, str) else ""
86
+ self.__json_encoder = json_encoder
87
+ self.__loop = asyncio.get_event_loop()
88
+ self.__redc_ext = RedC(buffer_size)
89
+
90
+ self.__set_default_headers()
91
+
92
+ async def __aenter__(self):
93
+ return self
94
+
95
+ async def __aexit__(self, exc_type, exc_val, exc_tb):
96
+ await self.close()
97
+
98
+ @property
99
+ def is_running(self):
100
+ """Checks if RedC is currently running
101
+
102
+ Returns:
103
+ ``bool``: ``True`` if RedC is running, False otherwise
104
+ """
105
+
106
+ return self.__redc_ext.is_running()
107
+
108
+ @property
109
+ def default_headers(self):
110
+ """Returns default headers that are set on all requests"""
111
+
112
+ return self.__default_headers
113
+
114
+ async def request(
115
+ self,
116
+ method: str,
117
+ url: str,
118
+ form: dict = None,
119
+ json: dict = None,
120
+ data: dict[str, str] = None,
121
+ files: dict[str, str] = None,
122
+ headers: dict[str, str] = None,
123
+ timeout: tuple = None,
124
+ allow_redirect: bool = True,
125
+ proxy_url: str = "",
126
+ verify: bool = True,
127
+ stream_callback: StreamCallback = None,
128
+ progress_callback: ProgressCallback = None,
129
+ verbose: bool = False,
130
+ ):
131
+ """
132
+ Make an HTTP request with the specified method and parameters
133
+
134
+ Example:
135
+ .. code-block:: python
136
+
137
+ >>> response = await client.request("GET", "/api/data", headers={"Authorization": "Bearer token"})
138
+
139
+ Parameters:
140
+ method (``str``):
141
+ The HTTP method to use (e.g., "GET", "POST")
142
+
143
+ url (``str``):
144
+ The URL to send the request to or path if ``base_url`` is specified in ``Client``
145
+
146
+ form (``dict``, *optional*):
147
+ Form data to send in the request body. Default is ``None``
148
+
149
+ json (``dict``, *optional*):
150
+ JSON data to send in the request body. Default is ``None``
151
+
152
+ data (``dict[str, str]``, *optional*):
153
+ Multipart form data to send in the request body. Default is ``None``
154
+
155
+ files (``dict[str, str]``, *optional*):
156
+ A dictionary specifying files to upload as part of a multipart form request, ``key`` is the form field and ``value`` is string containing the file path
157
+
158
+ headers (``dict[str, str]``, *optional*):
159
+ Headers to include in the request. Default is ``None``
160
+
161
+ timeout (``tuple``, *optional*):
162
+ A tuple of ``(total_timeout, connect_timeout)`` in seconds to override the default timeout.
163
+ If ``None``, the default timeout specified in ``Client`` is used.
164
+
165
+ allow_redirect (``bool``, *optional*):
166
+ Whether to allow redirects. Default is ``True``
167
+
168
+ proxy_url (``str``, *optional*):
169
+ The proxy URL to use for the request
170
+
171
+ verify (``bool``, *optional*):
172
+ Whether to verify SSL certificates. Default is ``True``
173
+
174
+ stream_callback (:class:`redc.StreamCallback`, *optional*):
175
+ Callback for streaming response data. Default is ``None``
176
+
177
+ progress_callback (:class:`redc.ProgressCallback`, *optional*):
178
+ Callback for tracking upload and download progress. Default is ``None``
179
+
180
+ verbose (``bool``, *optional*):
181
+ Whether to enable verbose output for the request. Default is ``False``
182
+
183
+ Returns:
184
+ :class:`redc.Response`
185
+ """
186
+
187
+ if stream_callback is not None:
188
+ if not isinstance(stream_callback, StreamCallback):
189
+ raise TypeError("stream_callback must be of type StreamCallback")
190
+
191
+ stream_callback = stream_callback.callback
192
+
193
+ if progress_callback is not None:
194
+ if not isinstance(progress_callback, ProgressCallback):
195
+ raise TypeError("progress_callback must be of type ProgressCallback")
196
+
197
+ progress_callback = progress_callback.callback
198
+
199
+ if form is not None:
200
+ if isinstance(form, dict):
201
+ form = urlencode(form)
202
+ else:
203
+ raise TypeError("form must be of type dict[str, str]")
204
+
205
+ if json is not None:
206
+ if isinstance(json, dict):
207
+ json = self.__json_encoder(json)
208
+ if headers is None:
209
+ headers = {}
210
+ headers["Content-Type"] = "application/json"
211
+ else:
212
+ raise TypeError("json must be of type dict[str, str]")
213
+
214
+ if data is not None:
215
+ if not isinstance(data, dict):
216
+ raise TypeError("data must be of type dict[str, str]")
217
+
218
+ if files is not None:
219
+ if not isinstance(files, dict):
220
+ raise TypeError("files must be of type dict[str, str]")
221
+
222
+ timeout, connect_timeout = timeout if timeout is not None else self.__timeout
223
+
224
+ if timeout <= 0:
225
+ raise ValueError("timeout must be greater than 0")
226
+
227
+ if connect_timeout < 0:
228
+ raise ValueError("connect_timeout must be 0 or greater")
229
+ elif connect_timeout > timeout:
230
+ raise ValueError("connect_timeout must be less than `timeout` argument")
231
+
232
+ if headers is not None:
233
+ if isinstance(headers, dict):
234
+ headers = {**self.__default_headers, **headers}
235
+ headers = [f"{k}: {v}" for k, v in headers.items()]
236
+ else:
237
+ raise TypeError("headers must be of type dict[str, str]")
238
+ else:
239
+ headers = [f"{k}: {v}" for k, v in self.__default_headers.items()]
240
+
241
+ if self.__base_url:
242
+ url = f"{self.__base_url}{url.lstrip('/')}"
243
+
244
+ return Response(
245
+ *(
246
+ await self.__redc_ext.request(
247
+ method=method,
248
+ url=url,
249
+ raw_data=form or json or "",
250
+ data=data,
251
+ files=files,
252
+ headers=headers,
253
+ timeout_ms=int(timeout * 1000),
254
+ connect_timeout_ms=int(connect_timeout * 1000),
255
+ allow_redirect=allow_redirect,
256
+ proxy_url=proxy_url,
257
+ verify=verify,
258
+ ca_cert_path=self.__ca_cert_path,
259
+ stream_callback=stream_callback,
260
+ progress_callback=progress_callback,
261
+ verbose=self.force_verbose or verbose,
262
+ )
263
+ ),
264
+ raise_for_status=self.raise_for_status,
265
+ )
266
+
267
+ async def get(
268
+ self,
269
+ url: str,
270
+ headers: dict[str, str] = None,
271
+ timeout: tuple = None,
272
+ allow_redirect: bool = True,
273
+ proxy_url: str = "",
274
+ verify: bool = True,
275
+ stream_callback: StreamCallback = None,
276
+ progress_callback: ProgressCallback = None,
277
+ verbose: bool = False,
278
+ ):
279
+ """
280
+ Make a GET request
281
+
282
+ Example:
283
+ .. code-block:: python
284
+
285
+ >>> response = await client.get("/api/data", headers={"Authorization": "Bearer token"})
286
+
287
+ Parameters:
288
+ url (``str``):
289
+ The URL to send the GET request to or path if ``base_url`` is specified in ``Client``
290
+
291
+ headers (``dict[str, str]``, *optional*):
292
+ Headers to include in the request. Default is ``None``
293
+
294
+ timeout (``tuple``, *optional*):
295
+ A tuple of ``(total_timeout, connect_timeout)`` in seconds to override the default timeout.
296
+ If ``None``, the default timeout specified in ``Client`` is used.
297
+
298
+ allow_redirect (``bool``, *optional*):
299
+ Whether to allow redirects. Default is ``True``
300
+
301
+ proxy_url (``str``, *optional*):
302
+ The proxy URL to use for the request
303
+
304
+ verify (``bool``, *optional*):
305
+ Whether to verify SSL certificates. Default is ``True``
306
+
307
+ stream_callback (:class:`redc.StreamCallback`, *optional*):
308
+ Callback for streaming response data. Default is ``None``
309
+
310
+ progress_callback (:class:`redc.ProgressCallback`, *optional*):
311
+ Callback for tracking upload and download progress. Default is ``None``
312
+
313
+ verbose (``bool``, *optional*):
314
+ Whether to enable verbose output for the request. Default is ``False``
315
+
316
+ Returns:
317
+ :class:`redc.Response`
318
+ """
319
+
320
+ return await self.request(
321
+ method="GET",
322
+ url=url,
323
+ headers=headers,
324
+ timeout=timeout,
325
+ allow_redirect=allow_redirect,
326
+ proxy_url=proxy_url,
327
+ verify=verify,
328
+ stream_callback=stream_callback,
329
+ progress_callback=progress_callback,
330
+ verbose=self.force_verbose or verbose,
331
+ )
332
+
333
+ async def head(
334
+ self,
335
+ url: str,
336
+ headers: dict[str, str] = None,
337
+ timeout: tuple = None,
338
+ allow_redirect: bool = True,
339
+ proxy_url: str = "",
340
+ verify: bool = True,
341
+ verbose: bool = False,
342
+ ):
343
+ """
344
+ Make a HEAD request
345
+
346
+ Example:
347
+ .. code-block:: python
348
+
349
+ >>> response = await client.head("/api/data", headers={"Authorization": "Bearer token"})
350
+
351
+ Parameters:
352
+ url (``str``):
353
+ The URL to send the HEAD request to or path if ``base_url`` is specified in ``Client``
354
+
355
+ headers (``dict[str, str]``, *optional*):
356
+ Headers to include in the request. Default is ``None``
357
+
358
+ timeout (``tuple``, *optional*):
359
+ A tuple of ``(total_timeout, connect_timeout)`` in seconds to override the default timeout.
360
+ If ``None``, the default timeout specified in ``Client`` is used.
361
+
362
+ allow_redirect (``bool``, *optional*):
363
+ Whether to allow redirects. Default is ``True``
364
+
365
+ proxy_url (``str``, *optional*):
366
+ The proxy URL to use for the request
367
+
368
+ verify (``bool``, *optional*):
369
+ Whether to verify SSL certificates. Default is ``True``
370
+
371
+ verbose (``bool``, *optional*):
372
+ Whether to enable verbose output for the request. Default is ``False``
373
+
374
+ Returns:
375
+ :class:`redc.Response`
376
+ """
377
+
378
+ return await self.request(
379
+ method="HEAD",
380
+ url=url,
381
+ headers=headers,
382
+ timeout=timeout,
383
+ allow_redirect=allow_redirect,
384
+ proxy_url=proxy_url,
385
+ verify=verify,
386
+ verbose=self.force_verbose or verbose,
387
+ )
388
+
389
+ async def post(
390
+ self,
391
+ url: str,
392
+ form: dict = None,
393
+ json: dict = None,
394
+ data: dict[str, str] = None,
395
+ files: dict[str, str] = None,
396
+ headers: dict[str, str] = None,
397
+ timeout: tuple = None,
398
+ allow_redirect: bool = True,
399
+ proxy_url: str = "",
400
+ verify: bool = True,
401
+ stream_callback: StreamCallback = None,
402
+ progress_callback: ProgressCallback = None,
403
+ verbose: bool = False,
404
+ ):
405
+ """
406
+ Make a POST request
407
+
408
+ Example:
409
+ .. code-block:: python
410
+
411
+ >>> response = await client.post(
412
+ ... "/api/data",
413
+ ... json={"key": "value"},
414
+ ... headers={"Authorization": "Bearer token"}
415
+ ... )
416
+
417
+ Parameters:
418
+ url (``str``):
419
+ The URL to send the POST request to or path if ``base_url`` is specified in ``Client``
420
+
421
+ form (``dict``, *optional*):
422
+ Form data to send in the request body. Default is ``None``
423
+
424
+ json (``dict``, *optional*):
425
+ JSON data to send in the request body. Default is ``None``
426
+
427
+ data (``dict[str, str]``, *optional*):
428
+ Multipart form data to send in the request body. Default is ``None``
429
+
430
+ files (``dict[str, str]``, *optional*):
431
+ A dictionary specifying files to upload as part of a multipart form request, ``key`` is the form field and ``value`` is string containing the file path
432
+
433
+ headers (``dict[str, str]``, *optional*):
434
+ Headers to include in the request. Default is ``None``
435
+
436
+ timeout (``tuple``, *optional*):
437
+ A tuple of ``(total_timeout, connect_timeout)`` in seconds to override the default timeout.
438
+ If ``None``, the default timeout specified in ``Client`` is used.
439
+
440
+ allow_redirect (``bool``, *optional*):
441
+ Whether to allow redirects. Default is ``True``
442
+
443
+ proxy_url (``str``, *optional*):
444
+ The proxy URL to use for the request
445
+
446
+ verify (``bool``, *optional*):
447
+ Whether to verify SSL certificates. Default is ``True``
448
+
449
+ stream_callback (:class:`redc.StreamCallback`, *optional*):
450
+ Callback for streaming response data. Default is ``None``
451
+
452
+ progress_callback (:class:`redc.ProgressCallback`, *optional*):
453
+ Callback for tracking upload and download progress. Default is ``None``
454
+
455
+ verbose (``bool``, *optional*):
456
+ Whether to enable verbose output for the request. Default is ``False``
457
+
458
+ Returns:
459
+ :class:`redc.Response`
460
+ """
461
+
462
+ return await self.request(
463
+ method="POST",
464
+ url=url,
465
+ form=form,
466
+ json=json,
467
+ data=data,
468
+ files=files,
469
+ headers=headers,
470
+ timeout=timeout,
471
+ allow_redirect=allow_redirect,
472
+ proxy_url=proxy_url,
473
+ verify=verify,
474
+ stream_callback=stream_callback,
475
+ progress_callback=progress_callback,
476
+ verbose=self.force_verbose or verbose,
477
+ )
478
+
479
+ async def put(
480
+ self,
481
+ url: str,
482
+ form: dict = None,
483
+ json: dict = None,
484
+ data: dict[str, str] = None,
485
+ files: dict[str, str] = None,
486
+ headers: dict[str, str] = None,
487
+ timeout: tuple = None,
488
+ allow_redirect: bool = True,
489
+ proxy_url: str = "",
490
+ verify: bool = True,
491
+ stream_callback: StreamCallback = None,
492
+ progress_callback: ProgressCallback = None,
493
+ verbose: bool = False,
494
+ ):
495
+ """
496
+ Make a PUT request
497
+
498
+ Example:
499
+ .. code-block:: python
500
+
501
+ >>> response = await client.put(
502
+ ... "/api/data/1",
503
+ ... json={"key": "new_value"},
504
+ ... headers={"Authorization": "Bearer token"}
505
+ ... )
506
+
507
+ Parameters:
508
+ url (``str``):
509
+ The URL to send the PUT request to or path if ``base_url`` is specified in ``Client``
510
+
511
+ form (``dict``, *optional*):
512
+ Form data to send in the request body. Default is ``None``
513
+
514
+ json (``dict``, *optional*):
515
+ JSON data to send in the request body. Default is ``None``
516
+
517
+ data (``dict[str, str]``, *optional*):
518
+ Multipart form data to send in the request body. Default is ``None``
519
+
520
+ files (``dict[str, str]``, *optional*):
521
+ A dictionary specifying files to upload as part of a multipart form request, ``key`` is the form field and ``value`` is string containing the file path
522
+
523
+ headers (``dict[str, str]``, *optional*):
524
+ Headers to include in the request. Default is ``None``
525
+
526
+ timeout (``tuple``, *optional*):
527
+ A tuple of ``(total_timeout, connect_timeout)`` in seconds to override the default timeout.
528
+ If ``None``, the default timeout specified in ``Client`` is used.
529
+
530
+ allow_redirect (``bool``, *optional*):
531
+ Whether to allow redirects. Default is ``True``
532
+
533
+ proxy_url (``str``, *optional*):
534
+ The proxy URL to use for the request
535
+
536
+ verify (``bool``, *optional*):
537
+ Whether to verify SSL certificates. Default is ``True``
538
+
539
+ stream_callback (:class:`redc.StreamCallback`, *optional*):
540
+ Callback for streaming response data. Default is ``None``
541
+
542
+ progress_callback (:class:`redc.ProgressCallback`, *optional*):
543
+ Callback for tracking upload and download progress. Default is ``None``
544
+
545
+ verbose (``bool``, *optional*):
546
+ Whether to enable verbose output for the request. Default is ``False``
547
+
548
+ Returns:
549
+ :class:`redc.Response`
550
+ """
551
+
552
+ return await self.request(
553
+ method="PUT",
554
+ url=url,
555
+ form=form,
556
+ json=json,
557
+ data=data,
558
+ files=files,
559
+ headers=headers,
560
+ timeout=timeout,
561
+ allow_redirect=allow_redirect,
562
+ proxy_url=proxy_url,
563
+ verify=verify,
564
+ stream_callback=stream_callback,
565
+ progress_callback=progress_callback,
566
+ verbose=self.force_verbose or verbose,
567
+ )
568
+
569
+ async def patch(
570
+ self,
571
+ url: str,
572
+ form: dict = None,
573
+ json: dict = None,
574
+ data: dict[str, str] = None,
575
+ files: dict[str, str] = None,
576
+ headers: dict[str, str] = None,
577
+ timeout: tuple = None,
578
+ allow_redirect: bool = True,
579
+ proxy_url: str = "",
580
+ verify: bool = True,
581
+ stream_callback: StreamCallback = None,
582
+ progress_callback: ProgressCallback = None,
583
+ verbose: bool = False,
584
+ ):
585
+ """
586
+ Make a PATCH request
587
+
588
+ Example:
589
+ .. code-block:: python
590
+
591
+ >>> response = await client.patch(
592
+ ... "/api/data/1",
593
+ ... json={"key": "updated_value"},
594
+ ... headers={"Authorization": "Bearer token"}
595
+ ... )
596
+
597
+ Parameters:
598
+ url (``str``):
599
+ The URL to send the PATCH request to or path if ``base_url`` is specified in ``Client``
600
+
601
+ form (``dict``, *optional*):
602
+ Form data to send in the request body. Default is ``None``
603
+
604
+ json (``dict``, *optional*):
605
+ JSON data to send in the request body. Default is ``None``
606
+
607
+ data (``dict[str, str]``, *optional*):
608
+ Multipart form data to send in the request body. Default is ``None``
609
+
610
+ files (``dict[str, str]``, *optional*):
611
+ A dictionary specifying files to upload as part of a multipart form request, ``key`` is the form field and ``value`` is string containing the file path
612
+
613
+ headers (``dict[str, str]``, *optional*):
614
+ Headers to include in the request. Default is ``None``
615
+
616
+ timeout (``tuple``, *optional*):
617
+ A tuple of ``(total_timeout, connect_timeout)`` in seconds to override the default timeout.
618
+ If ``None``, the default timeout specified in ``Client`` is used.
619
+
620
+ allow_redirect (``bool``, *optional*):
621
+ Whether to allow redirects. Default is ``True``
622
+
623
+ proxy_url (``str``, *optional*):
624
+ The proxy URL to use for the request
625
+
626
+ verify (``bool``, *optional*):
627
+ Whether to verify SSL certificates. Default is ``True``
628
+
629
+ stream_callback (:class:`redc.StreamCallback`, *optional*):
630
+ Callback for streaming response data. Default is ``None``
631
+
632
+ progress_callback (:class:`redc.ProgressCallback`, *optional*):
633
+ Callback for tracking upload and download progress. Default is ``None``
634
+
635
+ verbose (``bool``, *optional*):
636
+ Whether to enable verbose output for the request. Default is ``False``
637
+
638
+ Returns:
639
+ :class:`redc.Response`
640
+ """
641
+
642
+ return await self.request(
643
+ method="PATCH",
644
+ url=url,
645
+ form=form,
646
+ json=json,
647
+ data=data,
648
+ files=files,
649
+ headers=headers,
650
+ timeout=timeout,
651
+ allow_redirect=allow_redirect,
652
+ proxy_url=proxy_url,
653
+ verify=verify,
654
+ stream_callback=stream_callback,
655
+ progress_callback=progress_callback,
656
+ verbose=self.force_verbose or verbose,
657
+ )
658
+
659
+ async def delete(
660
+ self,
661
+ url: str,
662
+ headers: dict[str, str] = None,
663
+ timeout: tuple = None,
664
+ allow_redirect: bool = True,
665
+ proxy_url: str = "",
666
+ verify: bool = True,
667
+ stream_callback: StreamCallback = None,
668
+ progress_callback: ProgressCallback = None,
669
+ verbose: bool = False,
670
+ ):
671
+ """
672
+ Make a DELETE request
673
+
674
+ Example:
675
+ .. code-block:: python
676
+
677
+ >>> response = await client.delete("/api/data/1", headers={"Authorization": "Bearer token"})
678
+
679
+ Parameters:
680
+ url (``str``):
681
+ The URL to send the DELETE request to or path if ``base_url`` is specified in ``Client``
682
+
683
+ headers (``dict[str, str]``, *optional*):
684
+ Headers to include in the request. Default is ``None``
685
+
686
+ timeout (``tuple``, *optional*):
687
+ A tuple of ``(total_timeout, connect_timeout)`` in seconds to override the default timeout.
688
+ If ``None``, the default timeout specified in ``Client`` is used.
689
+
690
+ allow_redirect (``bool``, *optional*):
691
+ Whether to allow redirects. Default is ``True``
692
+
693
+ proxy_url (``str``, *optional*):
694
+ The proxy URL to use for the request
695
+
696
+ verify (``bool``, *optional*):
697
+ Whether to verify SSL certificates. Default is ``True``
698
+
699
+ stream_callback (:class:`redc.StreamCallback`, *optional*):
700
+ Callback for streaming response data. Default is ``None``
701
+
702
+ progress_callback (:class:`redc.ProgressCallback`, *optional*):
703
+ Callback for tracking upload and download progress. Default is ``None``
704
+
705
+ verbose (``bool``, *optional*):
706
+ Whether to enable verbose output for the request. Default is ``False``
707
+
708
+ Returns:
709
+ :class:`redc.Response`
710
+ """
711
+
712
+ return await self.request(
713
+ method="DELETE",
714
+ url=url,
715
+ headers=headers,
716
+ timeout=timeout,
717
+ allow_redirect=allow_redirect,
718
+ proxy_url=proxy_url,
719
+ verify=verify,
720
+ stream_callback=stream_callback,
721
+ progress_callback=progress_callback,
722
+ verbose=self.force_verbose or verbose,
723
+ )
724
+
725
+ async def options(
726
+ self,
727
+ url: str,
728
+ headers: dict[str, str] = None,
729
+ timeout: tuple = None,
730
+ allow_redirect: bool = True,
731
+ proxy_url: str = "",
732
+ verify: bool = True,
733
+ verbose: bool = False,
734
+ ):
735
+ """
736
+ Make an OPTIONS request
737
+
738
+ Example:
739
+ .. code-block:: python
740
+
741
+ >>> response = await client.options("/api/data", headers={"Authorization": "Bearer token"})
742
+
743
+ Parameters:
744
+ url (``str``):
745
+ The URL to send the OPTIONS request to or path if ``base_url`` is specified in ``Client``
746
+
747
+ headers (``dict[str, str]``, *optional*):
748
+ Headers to include in the request. Default is ``None``
749
+
750
+ timeout (``tuple``, *optional*):
751
+ A tuple of ``(total_timeout, connect_timeout)`` in seconds to override the default timeout.
752
+ If ``None``, the default timeout specified in ``Client`` is used.
753
+
754
+ allow_redirect (``bool``, *optional*):
755
+ Whether to allow redirects. Default is ``True``
756
+
757
+ proxy_url (``str``, *optional*):
758
+ The proxy URL to use for the request
759
+
760
+ verify (``bool``, *optional*):
761
+ Whether to verify SSL certificates. Default is ``True``
762
+
763
+ verbose (``bool``, *optional*):
764
+ Whether to enable verbose output for the request. Default is ``False``
765
+
766
+ Returns:
767
+ :class:`redc.Response`
768
+ """
769
+
770
+ return await self.request(
771
+ method="OPTIONS",
772
+ url=url,
773
+ headers=headers,
774
+ timeout=timeout,
775
+ allow_redirect=allow_redirect,
776
+ proxy_url=proxy_url,
777
+ verify=verify,
778
+ verbose=self.force_verbose or verbose,
779
+ )
780
+
781
+ async def close(self):
782
+ """
783
+ Close the RedC client and free up resources.
784
+
785
+ This method must be called when the client is no longer needed to avoid memory leaks
786
+ or unexpected behavior
787
+ """
788
+
789
+ return await self.__loop.run_in_executor(None, self.__redc_ext.close)
790
+
791
+ def __set_default_headers(self):
792
+ if "user-agent" not in self.__default_headers:
793
+ self.__default_headers["user-agent"] = f"redc/{redc.__version__}"
794
+
795
+ if "connection" not in self.__default_headers:
796
+ self.__default_headers["connection"] = "keep-alive"