yta-httpx 0.0.1__py3-none-any.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.
yta_httpx/__init__.py ADDED
@@ -0,0 +1,3 @@
1
+ """
2
+ The Youtube Autonomous Httpx Module
3
+ """
@@ -0,0 +1,596 @@
1
+ from yta_httpx.client.utils import _raise_exception_if_status_code, content_type_to_parse_mode
2
+ from yta_httpx.enums import RequestMethod, ResponseParseMode, ResponseTransportMode
3
+ from yta_httpx.exceptions import HttpRequestError
4
+ from yta_httpx.types import ParsedResponseType, ParsedCompleteResponseType, ParsedStreamResponseType
5
+ from typing import Any, Union
6
+
7
+ import httpx
8
+ import warnings
9
+
10
+
11
+ class HttpClient:
12
+ """
13
+ HttpClient to send requests.
14
+ """
15
+
16
+ def __init__(
17
+ self,
18
+ timeout: float = 60.0,
19
+ default_headers: Union[dict, None] = None
20
+ ):
21
+ self._client = httpx.AsyncClient(
22
+ timeout = timeout,
23
+ headers = default_headers
24
+ )
25
+ """
26
+ *For internal use only*
27
+
28
+ The `httpx.AsyncClient` instance to be used to
29
+ send the reqeusts we need.
30
+ """
31
+ self.get: _HttpClientMethodNamespace = _HttpClientMethodNamespace(
32
+ http_client = self,
33
+ method = RequestMethod.GET
34
+ )
35
+ """
36
+ Shortcut to send `GET` requests.
37
+ """
38
+ self.post: _HttpClientMethodNamespace = _HttpClientMethodNamespace(
39
+ http_client = self,
40
+ method = RequestMethod.POST
41
+ )
42
+ """
43
+ Shortcut to send `POST` requests.
44
+ """
45
+
46
+ async def close(
47
+ self
48
+ ):
49
+ """
50
+ *Asynchronous method*
51
+
52
+ Force the client to be closed asynchronously.
53
+ """
54
+ await self._client.aclose()
55
+
56
+ def __del__(
57
+ self
58
+ ):
59
+ if not self._client.is_closed:
60
+ warnings.warn(
61
+ 'HttpClient was not properly closed'
62
+ )
63
+
64
+ async def __aenter__(
65
+ self
66
+ ):
67
+ return self
68
+
69
+ async def __aexit__(
70
+ self,
71
+ exc_type,
72
+ exc,
73
+ tb
74
+ ):
75
+ await self.close()
76
+
77
+ async def request_complete(
78
+ self,
79
+ method: RequestMethod,
80
+ url: str,
81
+ *,
82
+ headers: Union[dict, None] = None,
83
+ params: Union[dict, None] = None,
84
+ json: Union[dict, None] = None,
85
+ data: Any = None,
86
+ content: Union[bytes, None] = None,
87
+ response_parse_mode: ResponseParseMode = ResponseParseMode.RESPONSE,
88
+ timeout: int = 60
89
+ ) -> ParsedCompleteResponseType:
90
+ """
91
+ *Asynchronous method*
92
+
93
+ Method to send a completely customizable request
94
+ that will return the whole response and will not
95
+ be streamed (using not the `stream=True` option).
96
+ """
97
+ return request_complete(
98
+ client = self._client,
99
+ method = method,
100
+ url = url,
101
+ # TODO: What about the '*' (?)
102
+ headers = headers,
103
+ params = params,
104
+ json = json,
105
+ data = data,
106
+ content = content,
107
+ response_parse_mode = response_parse_mode,
108
+ timeout = timeout
109
+ )
110
+
111
+ async def request_stream(
112
+ self,
113
+ method: RequestMethod,
114
+ url: str,
115
+ *,
116
+ headers: Union[dict, None] = None,
117
+ params: Union[dict, None] = None,
118
+ json: Union[dict, None] = None,
119
+ data: Any = None,
120
+ content: Union[bytes, None] = None,
121
+ response_parse_mode: ResponseParseMode = ResponseParseMode.RESPONSE,
122
+ chunk_size: int = 8192,
123
+ timeout: int = 60
124
+ ) -> ParsedCompleteResponseType:
125
+ """
126
+ *Asynchronous method*
127
+
128
+ Method to send a completely customizable request
129
+ that will return the response by chunks, as a
130
+ streamed response (using the `stream=True` option).
131
+ """
132
+ return request_stream(
133
+ client = self._client,
134
+ method = method,
135
+ url = url,
136
+ # TODO: What about the '*' (?)
137
+ headers = headers,
138
+ params = params,
139
+ json = json,
140
+ data = data,
141
+ content = content,
142
+ response_parse_mode = response_parse_mode,
143
+ chunk_size = chunk_size,
144
+ timeout = timeout
145
+ )
146
+
147
+ class _HttpClientMethodNamespace:
148
+ """
149
+ *For internal use only*
150
+
151
+ Class to include the funcionality related to
152
+ the method of the `HttpClient` requests.
153
+
154
+ Class to be used as a hierarchical system.
155
+ """
156
+
157
+ def __init__(
158
+ self,
159
+ http_client: HttpClient,
160
+ method: RequestMethod
161
+ ):
162
+ method = RequestMethod.to_enum(method)
163
+
164
+ self._http_client: 'HttpClient' = http_client
165
+ """
166
+ *For internal use only*
167
+
168
+ The reference to the father `HttpClient` instance.
169
+ """
170
+ self._method: RequestMethod = method
171
+ """
172
+ *For internal use only*
173
+
174
+ The method that will be used for the requests that
175
+ are made by this instance.
176
+ """
177
+ self.stream = _HttpClientTransportModeNamespace(
178
+ http_client = http_client,
179
+ method = method,
180
+ transport_mode = ResponseTransportMode.STREAM
181
+ )
182
+ """
183
+ Attribute to send a request that will be streamed.
184
+
185
+ If you are using a `stream`, check this code below
186
+ to handle the response:
187
+ ```
188
+ async for chunk in http_client.get.stream.as_bytes(...):
189
+ print(chunk)
190
+ ```
191
+ """
192
+ self.complete = _HttpClientTransportModeNamespace(
193
+ http_client = http_client,
194
+ method = method,
195
+ transport_mode = ResponseTransportMode.COMPLETE
196
+ )
197
+ """
198
+ Attribute to send a request that will not be streamed.
199
+ """
200
+
201
+ class _HttpClientTransportModeNamespace:
202
+ """
203
+ *For internal use only*
204
+
205
+ Class to include the funcionality related to
206
+ the transport mode of the `HttpClient` requests.
207
+
208
+ Class to be used as a hierarchical system.
209
+ """
210
+
211
+ def __init__(
212
+ self,
213
+ http_client: HttpClient,
214
+ method: RequestMethod,
215
+ transport_mode: ResponseTransportMode
216
+ ):
217
+ method = RequestMethod.to_enum(method)
218
+ transport_mode = ResponseTransportMode.to_enum(transport_mode)
219
+
220
+ self._http_client: 'HttpClient' = http_client
221
+ """
222
+ *For internal use only*
223
+
224
+ The reference to the father `HttpClient` instance.
225
+ """
226
+ self._method: RequestMethod = method
227
+ """
228
+ *For internal use only*
229
+
230
+ The method that will be used for the requests that
231
+ are made by this instance.
232
+ """
233
+ self._transport_mode: ResponseTransportMode = transport_mode
234
+ """
235
+ *For internal use only*
236
+
237
+ The transport mode that will be used for the requests
238
+ that are made by this instance.
239
+ """
240
+
241
+ self.as_json = _HttpClientParseModeNamespace(
242
+ http_client = http_client,
243
+ method = method,
244
+ transport_mode = transport_mode,
245
+ parse_mode = ResponseParseMode.JSON
246
+ )
247
+ """
248
+ Attribute to send a request that will parse the result
249
+ as a json.
250
+ """
251
+ self.as_text = _HttpClientParseModeNamespace(
252
+ http_client = http_client,
253
+ method = method,
254
+ transport_mode = transport_mode,
255
+ parse_mode = ResponseParseMode.TEXT
256
+ )
257
+ """
258
+ Attribute to send a request that will parse the result
259
+ as text.
260
+ """
261
+ self.as_bytes = _HttpClientParseModeNamespace(
262
+ http_client = http_client,
263
+ method = method,
264
+ transport_mode = transport_mode,
265
+ parse_mode = ResponseParseMode.BYTES
266
+ )
267
+ """
268
+ Attribute to send a request that will parse the result
269
+ as bytes.
270
+ """
271
+ self.as_lines = _HttpClientParseModeNamespace(
272
+ http_client = http_client,
273
+ method = method,
274
+ transport_mode = transport_mode,
275
+ parse_mode = ResponseParseMode.LINES
276
+ )
277
+ """
278
+ Attribute to send a request that will parse the result
279
+ as lines.
280
+ """
281
+ self.as_response = _HttpClientParseModeNamespace(
282
+ http_client = http_client,
283
+ method = method,
284
+ transport_mode = transport_mode,
285
+ parse_mode = ResponseParseMode.RESPONSE
286
+ )
287
+ """
288
+ Attribute to send a request that will return the
289
+ whole response as it is, as an object, parsed not.
290
+ """
291
+
292
+ class _HttpClientParseModeNamespace:
293
+ """
294
+ *For internal use only*
295
+
296
+ Class to include the funcionality related to
297
+ the parse mode of the `HttpClient` requests.
298
+
299
+ Class to be used as a hierarchical system.
300
+ """
301
+
302
+ def __init__(
303
+ self,
304
+ http_client: HttpClient,
305
+ method: RequestMethod,
306
+ transport_mode: ResponseTransportMode,
307
+ parse_mode: ResponseParseMode
308
+ ):
309
+ method = RequestMethod.to_enum(method)
310
+ transport_mode = ResponseTransportMode.to_enum(transport_mode)
311
+ parse_mode = ResponseParseMode.to_enum(parse_mode)
312
+
313
+ self._http_client: 'HttpClient' = http_client
314
+ """
315
+ *For internal use only*
316
+
317
+ The reference to the father `HttpClient` instance.
318
+ """
319
+ self._method: RequestMethod = method
320
+ """
321
+ *For internal use only*
322
+
323
+ The method that will be used for the requests that
324
+ are made by this instance.
325
+ """
326
+ self._transport_mode: ResponseTransportMode = transport_mode
327
+ """
328
+ *For internal use only*
329
+
330
+ The transport mode that will be used for the requests
331
+ that are made by this instance.
332
+ """
333
+ self._parse_mode: ResponseParseMode = parse_mode
334
+ """
335
+ *For internal use only*
336
+
337
+ The parse mode that will be used for the requests
338
+ that are made by this instance.
339
+ """
340
+
341
+ async def __call__(
342
+ self,
343
+ url: str,
344
+ headers: Union[dict, None] = None,
345
+ params: Union[dict, None] = None,
346
+ json: Union[dict, None] = None,
347
+ data: Any = None,
348
+ content: Union[bytes, None] = None,
349
+ chunk_size: int = 8196,
350
+ timeout: int = 60,
351
+ # TODO: No more specific args (?)
352
+ **kwargs
353
+ ):
354
+ if self._transport_mode == ResponseTransportMode.COMPLETE:
355
+ return await request_complete(
356
+ client = self._http_client._client,
357
+ method = self._method,
358
+ url = url,
359
+ headers = headers,
360
+ params = params,
361
+ json = json,
362
+ data = data,
363
+ content = content,
364
+ response_parse_mode = self._parse_mode,
365
+ timeout = timeout,
366
+ **kwargs
367
+ )
368
+
369
+ return request_stream(
370
+ client = self._http_client._client,
371
+ method = self._method,
372
+ url = url,
373
+ headers = headers,
374
+ params = params,
375
+ json = json,
376
+ data = data,
377
+ content = content,
378
+ response_parse_mode = self._parse_mode,
379
+ chunk_size = chunk_size,
380
+ timeout = timeout
381
+ )
382
+
383
+
384
+ # Utils below
385
+ async def request_complete(
386
+ client: 'AsyncClient',
387
+ method: RequestMethod,
388
+ url: str,
389
+ *,
390
+ headers: Union[dict, None] = None,
391
+ params: Union[dict, None] = None,
392
+ json: Union[dict, None] = None,
393
+ data: Any = None,
394
+ content: Union[bytes, None] = None,
395
+ response_parse_mode: ResponseParseMode = ResponseParseMode.RESPONSE,
396
+ timeout: int = 60
397
+ ) -> ParsedCompleteResponseType:
398
+ response = await client.request(
399
+ method = method.value,
400
+ url = url,
401
+ content = content,
402
+ data = data,
403
+ json = json,
404
+ params = params,
405
+ headers = headers,
406
+ timeout = timeout
407
+ )
408
+
409
+ await _raise_exception_if_status_code(response)
410
+
411
+ return await parse_response_content(
412
+ response = response,
413
+ transport_mode = ResponseTransportMode.COMPLETE,
414
+ parse_mode = response_parse_mode
415
+ )
416
+
417
+
418
+ async def request_stream(
419
+ client: 'AsyncClient',
420
+ method: RequestMethod,
421
+ url: str,
422
+ *,
423
+ headers: Union[dict, None] = None,
424
+ params: Union[dict, None] = None,
425
+ json: Union[dict, None] = None,
426
+ data: Any = None,
427
+ content: Union[bytes, None] = None,
428
+ response_parse_mode: ResponseParseMode = ResponseParseMode.RESPONSE,
429
+ chunk_size: int = 8192,
430
+ timeout: int = 60
431
+ ) -> ParsedStreamResponseType:
432
+ async with client.stream(
433
+ method = method.value,
434
+ url = url,
435
+ content = content,
436
+ data = data,
437
+ json = json,
438
+ params = params,
439
+ headers = headers,
440
+ timeout = timeout
441
+ ) as response:
442
+ await _raise_exception_if_status_code(response)
443
+
444
+ parsed_stream = await parse_response_content(
445
+ response = response,
446
+ transport_mode = ResponseTransportMode.STREAM,
447
+ parse_mode = response_parse_mode,
448
+ chunk_size = chunk_size
449
+ )
450
+
451
+ async for chunk in parsed_stream:
452
+ yield chunk
453
+
454
+
455
+ async def _parse_stream_response(
456
+ response: httpx.Response,
457
+ parse_mode: ResponseParseMode,
458
+ chunk_size: int = 8192
459
+ ) -> ParsedStreamResponseType:
460
+ """
461
+ *For internal use only*
462
+
463
+ Method used by the `parse_response_content`
464
+ to parse the content when the request has
465
+ been done as a stream request and not as
466
+ a complete request.
467
+ """
468
+ # TODO: Can we validate if it was streaming (?)
469
+ parse_mode = ResponseParseMode.to_enum(parse_mode)
470
+
471
+ if parse_mode == ResponseParseMode.BYTES:
472
+ async for chunk in response.aiter_bytes(chunk_size):
473
+ yield chunk
474
+ elif parse_mode == ResponseParseMode.TEXT:
475
+ async for chunk in response.aiter_text():
476
+ yield chunk
477
+ elif parse_mode == ResponseParseMode.LINES:
478
+ async for line in response.aiter_lines():
479
+ yield line
480
+ elif parse_mode == ResponseParseMode.JSON:
481
+ async for line in response.aiter_lines():
482
+ if not line:
483
+ continue
484
+ # TODO: Check this...
485
+ import json
486
+ # TODO: Check if possible or not (?)
487
+ yield json.loads(line)
488
+ elif parse_mode == ResponseParseMode.RESPONSE:
489
+ # TODO: Non-sense, but here it is, maybe exc instead (?)
490
+ yield response
491
+
492
+ async def _parse_complete_response(
493
+ response: httpx.Response,
494
+ parse_mode: ResponseParseMode,
495
+ ) -> ParsedCompleteResponseType:
496
+ """
497
+ *For internal use only*
498
+
499
+ Method used by the `parse_response_content`
500
+ to parse the content when the request has
501
+ been done as a complete request and not as
502
+ a stream request.
503
+ """
504
+ parse_mode = ResponseParseMode.to_enum(parse_mode)
505
+
506
+ if parse_mode == ResponseParseMode.JSON:
507
+ return _parse_response_content_as_json(response = response)
508
+ elif parse_mode == ResponseParseMode.TEXT:
509
+ return response.text
510
+ elif parse_mode == ResponseParseMode.BYTES:
511
+ return response.content
512
+ elif parse_mode == ResponseParseMode.LINES:
513
+ # TODO: Non-sense, but here it is, maybe exc instead (?)
514
+ return response.text.splitlines()
515
+ elif parse_mode == ResponseParseMode.RESPONSE:
516
+ return response
517
+
518
+ async def parse_response_content(
519
+ response: httpx.Response,
520
+ transport_mode: ResponseTransportMode = ResponseTransportMode.COMPLETE,
521
+ parse_mode: ResponseParseMode = ResponseParseMode.AUTO,
522
+ chunk_size: int = 8192
523
+ ) -> ParsedResponseType:
524
+ """
525
+ Parse the given `response` according to the
526
+ `transport_mode` given and the `parse_mode` also
527
+ provided.
528
+
529
+ If the `parse_mode` is `AUTO`, we need to detect
530
+ the real `parse_mode` we need to apply based on
531
+ the `content_type` of the `response` provided,
532
+ which will be autodetected by us.
533
+ """
534
+ parse_mode = ResponseParseMode.to_enum(parse_mode)
535
+ transport_mode = ResponseTransportMode.to_enum(transport_mode)
536
+
537
+ if parse_mode == ResponseParseMode.AUTO:
538
+ parse_mode = _resolve_parse_mode(
539
+ response = response,
540
+ parse_mode = parse_mode
541
+ )
542
+
543
+ # Complete
544
+ if transport_mode == ResponseTransportMode.COMPLETE:
545
+ return await _parse_complete_response(
546
+ response = response,
547
+ parse_mode = parse_mode
548
+ )
549
+
550
+ # Stream
551
+ return _parse_stream_response(
552
+ response = response,
553
+ parse_mode = parse_mode,
554
+ chunk_size = chunk_size
555
+ )
556
+
557
+ def _resolve_parse_mode(
558
+ response: 'Response',
559
+ parse_mode: ResponseParseMode
560
+ ) -> ResponseParseMode:
561
+ """
562
+ Method to resolve the `ResponseParseMode`
563
+ according to the `parse_mode` option provided
564
+ and the `content_type` of the `response`,
565
+ because if `ResponseParseMode.AUTO` is given it
566
+ will be autoselected based on it.
567
+ """
568
+ if parse_mode != ResponseParseMode.AUTO:
569
+ return parse_mode
570
+
571
+ content_type = response.headers.get(
572
+ 'content-type',
573
+ ''
574
+ ).lower()
575
+
576
+ return content_type_to_parse_mode(content_type)
577
+
578
+ def _parse_response_content_as_json(
579
+ response: httpx.Response
580
+ ) -> dict:
581
+ """
582
+ *For internal use only*
583
+
584
+ Method to try to obtain the `response` as a `JSON`,
585
+ raising an exception if something is wrong.
586
+ """
587
+ try:
588
+ return response.json()
589
+
590
+ except Exception as e:
591
+ raise HttpRequestError(
592
+ status_code = response.status_code,
593
+ message = f'Invalid JSON response: {e}',
594
+ response_text = response.text
595
+ )
596
+
@@ -0,0 +1,62 @@
1
+ from yta_httpx.enums import ResponseContentType, ResponseParseMode
2
+ from yta_httpx.exceptions import HttpRequestError
3
+
4
+
5
+ def content_type_to_parse_mode(
6
+ content_type: ResponseContentType
7
+ ) -> ResponseParseMode:
8
+ """
9
+ Transform the `content_type` provided into
10
+ the `ResponseParseMode` that has to be used
11
+ to parse that type of response.
12
+ """
13
+ try:
14
+ content_type = ResponseContentType.to_enum(content_type)
15
+ except:
16
+ print(f'The {content_type} is not registered in our system, ask the administrator to add it. Using "ResponseParseMode.BYTES" by default.')
17
+
18
+ return ResponseParseMode.BYTES
19
+
20
+ """
21
+ We must have all the `ResponseContentType` items
22
+ here with their corresponding mode, and if it is
23
+ not registered it will be detected above.
24
+ """
25
+ return {
26
+ ResponseContentType.APPLICATION_JSON: ResponseParseMode.JSON,
27
+ ResponseContentType.TEXT_PLAIN: ResponseParseMode.TEXT,
28
+ ResponseContentType.TEXT_HTML: ResponseParseMode.TEXT,
29
+ ResponseContentType.APPLICATION_XML: ResponseParseMode.TEXT,
30
+ ResponseContentType.IMAGE_JPEG: ResponseParseMode.BYTES,
31
+ ResponseContentType.VIDEO_MP4: ResponseParseMode.BYTES,
32
+ ResponseContentType.AUDIO_WAV: ResponseParseMode.BYTES,
33
+ ResponseContentType.TEXT_EVENT_STREAM: ResponseParseMode.LINES,
34
+ ResponseContentType.APPLICATION_XHTML_XML: ResponseParseMode.TEXT,
35
+ ResponseContentType.APPLICATION_JAVASCRIPT: ResponseParseMode.TEXT,
36
+ ResponseContentType.APPLICATION_PROBLEM_JSON: ResponseParseMode.JSON
37
+ }[content_type]
38
+
39
+ async def _raise_exception_if_status_code(
40
+ response: 'httpx.Response'
41
+ ):
42
+ """
43
+ *Asynchronous method*
44
+
45
+ *For internal use only*
46
+
47
+ Raise an exception if the `status_code` is
48
+ indicating the error extracted from the
49
+ response itself.
50
+ """
51
+ if response.status_code >= 400:
52
+ try:
53
+ text = await response.aread()
54
+ text = text.decode()
55
+ except:
56
+ text = None
57
+
58
+ raise HttpRequestError(
59
+ status_code = response.status_code,
60
+ message = 'Request failed',
61
+ response_text = text
62
+ )
yta_httpx/enums.py ADDED
@@ -0,0 +1,65 @@
1
+ from yta_constants.enum import YTAEnum as Enum
2
+
3
+
4
+ class RequestMethod(Enum):
5
+ """
6
+ The different methods of a request.
7
+ """
8
+ GET = 'GET'
9
+ POST = 'POST'
10
+
11
+ class ResponseTransportMode(Enum):
12
+ """
13
+ Enum class to indicate the way you want to load
14
+ and receive the content of the response, that
15
+ can be at once, or by chunks through an iterator
16
+ that is caused by an streamed response.
17
+ """
18
+ STREAM = 'stream'
19
+ """
20
+ The response content will be given chunk by chunk
21
+ with an iterator.
22
+ """
23
+ COMPLETE = 'complete'
24
+ """
25
+ The response content will be given all of it at
26
+ once.
27
+ """
28
+
29
+ class ResponseParseMode(Enum):
30
+ """
31
+ The way we want to parse the content that comes
32
+ as a result of a request.
33
+ """
34
+ AUTO = 'auto'
35
+ """
36
+ The way to parse the content will be chosen
37
+ according to the response content type.
38
+ """
39
+ JSON = 'json'
40
+ TEXT = 'text'
41
+ BYTES = 'bytes'
42
+ LINES = 'lines'
43
+ RESPONSE = 'response'
44
+ """
45
+ This mode will return the whole response and as
46
+ it was received, not only the content.
47
+ """
48
+
49
+ class ResponseContentType(Enum):
50
+ """
51
+ The `content_type` field that could come in a
52
+ request.
53
+ """
54
+ APPLICATION_JSON = 'application/json'
55
+ TEXT_PLAIN = 'text/plain'
56
+ TEXT_HTML = 'text/html'
57
+ APPLICATION_XML = 'application/xml'
58
+ IMAGE_JPEG = 'image/jpeg'
59
+ VIDEO_MP4 = 'video/mp4'
60
+ AUDIO_WAV = 'audio/wav'
61
+ APPLICATION_OCTET_STREAM = 'application/octet-stream'
62
+ TEXT_EVENT_STREAM = 'text/event-stream'
63
+ APPLICATION_XHTML_XML = 'application/xhtml+xml'
64
+ APPLICATION_JAVASCRIPT = 'application/javascript'
65
+ APPLICATION_PROBLEM_JSON = 'application/problem+json'
@@ -0,0 +1,15 @@
1
+ from typing import Union
2
+
3
+
4
+ class HttpRequestError(Exception):
5
+ def __init__(
6
+ self,
7
+ status_code: int,
8
+ message: str,
9
+ response_text: Union[str, None] = None
10
+ ):
11
+ self.status_code = status_code
12
+ self.message = message
13
+ self.response_text = response_text
14
+
15
+ super().__init__(f'{status_code} - {message}')
yta_httpx/types.py ADDED
@@ -0,0 +1,34 @@
1
+ from typing import Union, Any
2
+ from typing import Any, AsyncGenerator, Union
3
+
4
+ import httpx
5
+
6
+
7
+ JsonType = Union[
8
+ dict[str, Any],
9
+ list[Any]
10
+ ]
11
+
12
+ StreamChunkType = Union[
13
+ bytes,
14
+ str,
15
+ JsonType
16
+ ]
17
+
18
+ ParsedCompleteResponseType = Union[
19
+ JsonType,
20
+ str,
21
+ bytes,
22
+ httpx.Response
23
+ ]
24
+
25
+ ParsedStreamResponseType = AsyncGenerator[
26
+ StreamChunkType,
27
+ None
28
+ ]
29
+
30
+ ParsedResponseType = Union[
31
+ ParsedCompleteResponseType,
32
+ ParsedStreamResponseType
33
+ ]
34
+
@@ -0,0 +1,22 @@
1
+ Metadata-Version: 2.4
2
+ Name: yta-httpx
3
+ Version: 0.0.1
4
+ Summary: Youtube Autonomous Httpx Module.
5
+ License-File: LICENSE
6
+ Author: danialcala94
7
+ Author-email: danielalcalavalera@gmail.com
8
+ Requires-Python: >=3.8,<3.14
9
+ Classifier: Programming Language :: Python :: 3
10
+ Classifier: Programming Language :: Python :: 3.8
11
+ Classifier: Programming Language :: Python :: 3.9
12
+ Classifier: Programming Language :: Python :: 3.10
13
+ Classifier: Programming Language :: Python :: 3.11
14
+ Classifier: Programming Language :: Python :: 3.12
15
+ Classifier: Programming Language :: Python :: 3.13
16
+ Requires-Dist: httpx (>=0.0.1,<9999.9.9)
17
+ Requires-Dist: yta_constants (>=0.0.1,<1.0.0)
18
+ Description-Content-Type: text/markdown
19
+
20
+ # Youtube Autonomous Httpx Module
21
+
22
+ The module to implement Http clients to make requests easily.
@@ -0,0 +1,10 @@
1
+ yta_httpx/__init__.py,sha256=_kbCgTevMudl-5sKvCSG8BiUoqmkCVt4jSf7GaLranE,45
2
+ yta_httpx/client/__init__.py,sha256=uwZAkbGuIUsOeOEf_1iOOvlL2QgZbU8AaJwD6zlwNlQ,18056
3
+ yta_httpx/client/utils.py,sha256=fZh0-6xvXTD7q1vKDIU5d-b-QyNAiK3OzYmFGXUviSA,2244
4
+ yta_httpx/enums.py,sha256=-WU7oT8f3Dq1a_QX9WjAwuR2N5VRdfnnfduLEajTmuI,1772
5
+ yta_httpx/exceptions.py,sha256=eQXzOZjMVMOGiD4MyuIbZAZ-nimVkUHHVYaVtCAkUL0,378
6
+ yta_httpx/types.py,sha256=ZoExXSXgZQTMiQg2d69MyarmfXp5XPcG4Myei21DVwg,502
7
+ yta_httpx-0.0.1.dist-info/licenses/LICENSE,sha256=6kbiFSfobTZ7beWiKnHpN902HgBx-Jzgcme0SvKqhKY,1091
8
+ yta_httpx-0.0.1.dist-info/METADATA,sha256=WMO7BGB_KILBeYne9gasoJlSbAwFbsVwXhAM1EKdgek,787
9
+ yta_httpx-0.0.1.dist-info/WHEEL,sha256=M5asmiAlL6HEcOq52Yi5mmk9KmTVjY2RDPtO4p9DMrc,88
10
+ yta_httpx-0.0.1.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: poetry-core 2.2.0
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
@@ -0,0 +1,19 @@
1
+ Copyright (c) 2018 The Python Packaging Authority
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in all
11
+ copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
+ SOFTWARE.