mm-std 0.3.22__py3-none-any.whl → 0.3.24__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.
mm_std/__init__.py CHANGED
@@ -46,6 +46,8 @@ from .random_ import random_str_choice as random_str_choice
46
46
  from .result import Err as Err
47
47
  from .result import Ok as Ok
48
48
  from .result import Result as Result
49
+ from .result import err as err
50
+ from .result import ok as ok
49
51
  from .result import try_ok as try_ok
50
52
  from .str import number_with_separator as number_with_separator
51
53
  from .str import str_contains_any as str_contains_any
mm_std/http_.py CHANGED
@@ -1,4 +1,3 @@
1
- import asyncio
2
1
  import json
3
2
  from dataclasses import asdict, dataclass, field
4
3
  from typing import Any
@@ -7,7 +6,6 @@ from urllib.parse import urlencode
7
6
  import aiohttp
8
7
  import pydash
9
8
  import requests
10
- import rich
11
9
  from aiohttp_socks import ProxyConnector
12
10
  from requests.auth import AuthBase
13
11
 
@@ -74,10 +72,10 @@ class HResponse:
74
72
  return self.error == "timeout"
75
73
 
76
74
  def is_proxy_error(self) -> bool:
77
- return self.error == "proxy_error"
75
+ return self.error == "proxy"
78
76
 
79
77
  def is_connection_error(self) -> bool:
80
- return self.error is not None and self.error.startswith("connection_error:")
78
+ return self.error is not None and self.error.startswith("connection:")
81
79
 
82
80
  def to_dict(self) -> dict[str, Any]:
83
81
  return pydash.omit(asdict(self), "_json_data")
@@ -137,9 +135,9 @@ def hrequest(
137
135
  except requests.exceptions.Timeout:
138
136
  return HResponse(error="timeout")
139
137
  except requests.exceptions.ProxyError:
140
- return HResponse(error="proxy_error")
138
+ return HResponse(error="proxy")
141
139
  except requests.exceptions.RequestException as err:
142
- return HResponse(error=f"connection_error: {err}")
140
+ return HResponse(error=f"connection: {err}")
143
141
  except Exception as err:
144
142
  return HResponse(error=f"exception: {err}")
145
143
 
@@ -156,7 +154,6 @@ async def hrequest_async(
156
154
  user_agent: str | None = None,
157
155
  json_params: bool = True,
158
156
  auth: tuple[str, str] | None = None,
159
- verify: bool = True,
160
157
  ) -> HResponse:
161
158
  query_params: dict[str, Any] | None = None
162
159
  data: dict[str, Any] | None = None
@@ -175,55 +172,67 @@ async def hrequest_async(
175
172
  data = params
176
173
 
177
174
  try:
178
- # Configure connector based on proxy type
179
- if proxy:
180
- # HTTP proxy will be handled in request kwargs
181
- connector = ProxyConnector.from_url(proxy) if proxy.startswith("socks5://") else aiohttp.TCPConnector(ssl=verify)
175
+ request_kwargs: dict[str, Any] = {"headers": headers}
176
+ if query_params:
177
+ request_kwargs["params"] = query_params
178
+ if json_:
179
+ request_kwargs["json"] = json_
180
+ if data:
181
+ request_kwargs["data"] = data
182
+ if cookies:
183
+ request_kwargs["cookies"] = cookies
184
+ if auth and isinstance(auth, tuple) and len(auth) == 2:
185
+ request_kwargs["auth"] = aiohttp.BasicAuth(auth[0], auth[1])
186
+
187
+ if proxy and proxy.startswith("socks"):
188
+ res = await _aiohttp_socks5(url, method, proxy, request_kwargs, timeout)
182
189
  else:
183
- connector = aiohttp.TCPConnector(ssl=verify)
184
-
185
- timeout_obj = aiohttp.ClientTimeout(total=timeout)
186
-
187
- async with aiohttp.ClientSession(connector=connector, timeout=timeout_obj, cookies=cookies) as session:
188
- request_kwargs: dict[str, Any] = {"headers": headers}
189
-
190
- if query_params:
191
- request_kwargs["params"] = query_params
192
- if json_:
193
- request_kwargs["json"] = json_
194
- if data:
195
- request_kwargs["data"] = data
196
-
197
- if auth and isinstance(auth, tuple) and len(auth) == 2:
198
- request_kwargs["auth"] = aiohttp.BasicAuth(auth[0], auth[1])
199
-
200
- # Set HTTP proxy (not needed for SOCKS5)
201
- if proxy and not proxy.startswith("socks5://"):
202
- request_kwargs["proxy"] = proxy
203
-
204
- try:
205
- async with await asyncio.wait_for(session.request(method, url, **request_kwargs), timeout=timeout) as response:
206
- body = await response.text()
207
- return HResponse(code=response.status, body=body, headers=dict(response.headers))
208
- except TimeoutError:
209
- return HResponse(error="timeout")
210
- except (aiohttp.ClientProxyConnectionError, aiohttp.ClientHttpProxyError):
211
- return HResponse(error="proxy_error")
212
- except aiohttp.ClientConnectorError as err:
213
- return HResponse(error=f"connection_error: {err}")
214
- except aiohttp.ClientError as err:
215
- rich.inspect(err)
216
- return HResponse(error=f"connection_error: {err}")
217
- except Exception as err:
218
- if "couldn't connect to proxy" in str(err).lower():
219
- return HResponse(error="proxy_error")
220
- return HResponse(error=f"exception: {err}")
190
+ res = await _aiohttp(url, method, request_kwargs, timeout=timeout, proxy=proxy)
191
+
192
+ return HResponse(code=res.status, body=res.body, headers=res.headers)
221
193
  except TimeoutError:
222
194
  return HResponse(error="timeout")
195
+ except (aiohttp.ClientProxyConnectionError, aiohttp.ClientHttpProxyError):
196
+ return HResponse(error="proxy")
197
+ except aiohttp.ClientConnectorError as err:
198
+ return HResponse(error=f"connection: {err}")
199
+ except aiohttp.ClientError as err:
200
+ return HResponse(error=f"error: {err}")
223
201
  except Exception as err:
202
+ if "couldn't connect to proxy" in str(err).lower():
203
+ return HResponse(error="proxy")
224
204
  return HResponse(error=f"exception: {err}")
225
205
 
226
206
 
207
+ @dataclass
208
+ class AioHttpResponse:
209
+ status: int
210
+ body: str
211
+ headers: dict[str, str]
212
+
213
+
214
+ async def _aiohttp(
215
+ url: str, method: str, request_kwargs: dict[str, object], timeout: float | None = None, proxy: str | None = None
216
+ ) -> AioHttpResponse:
217
+ if proxy:
218
+ request_kwargs["proxy"] = proxy
219
+ client_timeout = aiohttp.ClientTimeout(total=timeout) if timeout else None
220
+ async with aiohttp.ClientSession(timeout=client_timeout) as session, session.request(method, url, **request_kwargs) as res: # type: ignore[arg-type]
221
+ return AioHttpResponse(status=res.status, headers=dict(res.headers), body=await res.text())
222
+
223
+
224
+ async def _aiohttp_socks5(
225
+ url: str, method: str, proxy: str, request_kwargs: dict[str, object], timeout: float | None = None
226
+ ) -> AioHttpResponse:
227
+ connector = ProxyConnector.from_url(proxy)
228
+ client_timeout = aiohttp.ClientTimeout(total=timeout) if timeout else None
229
+ async with (
230
+ aiohttp.ClientSession(connector=connector, timeout=client_timeout) as session,
231
+ session.request(method, url, **request_kwargs) as res, # type: ignore[arg-type]
232
+ ):
233
+ return AioHttpResponse(status=res.status, headers=dict(res.headers), body=await res.text())
234
+
235
+
227
236
  def add_query_params_to_url(url: str, params: dict[str, object]) -> str:
228
237
  query_params = urlencode({k: v for k, v in params.items() if v is not None})
229
238
  if query_params:
mm_std/result.py CHANGED
@@ -2,7 +2,7 @@ from __future__ import annotations
2
2
 
3
3
  import time
4
4
  from collections.abc import Callable
5
- from typing import Any, ClassVar, Literal, NoReturn, TypeVar, Union
5
+ from typing import Any, ClassVar, Literal, NoReturn, TypeGuard, TypeVar, Union
6
6
 
7
7
  from pydantic_core import core_schema
8
8
 
@@ -258,6 +258,16 @@ class UnwrapError(Exception):
258
258
  return self._result
259
259
 
260
260
 
261
+ def ok(result: Result[T]) -> TypeGuard[Ok[T]]:
262
+ """Used for type narrowing from `Result` to `Ok`."""
263
+ return isinstance(result, Ok)
264
+
265
+
266
+ def err(result: Result[T]) -> TypeGuard[Err]:
267
+ """Used for type narrowing from `Result` to `Err`."""
268
+ return isinstance(result, Err)
269
+
270
+
261
271
  def try_ok[T](fn: Callable[..., Result[T]], *, args: tuple[object], attempts: int, delay: float = 0) -> Result[T]:
262
272
  if attempts <= 0:
263
273
  raise ValueError("attempts must be more than zero")
@@ -1,12 +1,12 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mm-std
3
- Version: 0.3.22
3
+ Version: 0.3.24
4
4
  Requires-Python: >=3.12
5
5
  Requires-Dist: aiohttp-socks~=0.10.1
6
6
  Requires-Dist: aiohttp~=3.11.16
7
7
  Requires-Dist: cryptography~=44.0.2
8
8
  Requires-Dist: pydantic-settings>=2.8.1
9
- Requires-Dist: pydantic~=2.11.2
9
+ Requires-Dist: pydantic~=2.11.3
10
10
  Requires-Dist: pydash~=8.0.5
11
11
  Requires-Dist: python-dotenv~=1.1.0
12
12
  Requires-Dist: requests[socks]~=2.32.3
@@ -1,4 +1,4 @@
1
- mm_std/__init__.py,sha256=ETGLXQW17ZnV5i6kdhoNA-1MulHZixpzGIOLlYpiYx0,3040
1
+ mm_std/__init__.py,sha256=bdkBTX7_u4NYtTRdVDHgZUozQlFRBx3TTiMK7Cenup0,3100
2
2
  mm_std/command.py,sha256=ze286wjUjg0QSTgIu-2WZks53_Vclg69UaYYgPpQvCU,1283
3
3
  mm_std/config.py,sha256=4ox4D2CgGR76bvZ2n2vGQOYUDagFnlKEDb87to5zpxE,1871
4
4
  mm_std/crypto.py,sha256=jdk0_TCmeU0pPXMyz9xH6kQHSjjZ9GcGClBwQps5vBo,340
@@ -6,14 +6,14 @@ mm_std/date.py,sha256=976eEkSONuNqHQBgSRu8hrtH23tJqztbmHFHLdbP2TY,1879
6
6
  mm_std/dict.py,sha256=6GkhJPXD0LiJDxPcYe6jPdEDw-MN7P7mKu6U5XxwYDk,675
7
7
  mm_std/env.py,sha256=5zaR9VeIfObN-4yfgxoFeU5IM1GDeZZj9SuYf7t9sOA,125
8
8
  mm_std/fs.py,sha256=RwarNRJq3tIMG6LVX_g03hasfYpjYFh_O27oVDt5IPQ,291
9
- mm_std/http_.py,sha256=cozBUGZcbKp9sZuEnu7bklwa6lTE0RxEUVo_aNt1_kE,7468
9
+ mm_std/http_.py,sha256=A9SUidkmTEFYWXD9y-rX4MrUXtaZFiy84Ul8floYBn8,7700
10
10
  mm_std/json_.py,sha256=Naa6mBE4D0yiQGkPNRrFvndnUH3R7ovw3FeaejWV60o,1196
11
11
  mm_std/log.py,sha256=0TkTsAlUTt00gjgukvsvnZRIAGELq0MI6Lv8mKP-Wz4,2887
12
12
  mm_std/net.py,sha256=qdRCBIDneip6FaPNe5mx31UtYVmzqam_AoUF7ydEyjA,590
13
13
  mm_std/print_.py,sha256=zB7sVbSSF8RffMxvnOdbKCXjCKtKzKV3R68pBri4NkQ,1638
14
14
  mm_std/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
15
15
  mm_std/random_.py,sha256=OuUX4VJeSd13NZBya4qrGpR2TfN7_87tfebOY6DBUnI,1113
16
- mm_std/result.py,sha256=KLnPWjICYFkP6CAhq7Ifs22XSD-PQ9RkG6n1-cZcXkM,7625
16
+ mm_std/result.py,sha256=2cLa0Lb1W7IY1Kxn-r-9GyqDz3colabp00dcvr7AKbU,7917
17
17
  mm_std/str.py,sha256=BEjJ1p5O4-uSYK0h-enasSSDdwzkBbiwdQ4_dsrlEE8,3257
18
18
  mm_std/toml.py,sha256=CNznWKR0bpOxS6e3VB5LGS-Oa9lW-wterkcPUFtPcls,610
19
19
  mm_std/types_.py,sha256=9FGd2q47a8M9QQgsWJR1Kq34jLxBAkYSoJuwih4PPqg,257
@@ -25,6 +25,6 @@ mm_std/concurrency/async_task_runner.py,sha256=EN7tN2enkVYVgDbhSiAr-_W4o9m9wBXCv
25
25
  mm_std/concurrency/sync_decorators.py,sha256=syCQBOmN7qPO55yzgJB2rbkh10CVww376hmyvs6e5tA,1080
26
26
  mm_std/concurrency/sync_scheduler.py,sha256=j4tBL_cBI1spr0cZplTA7N2CoYsznuORMeRN8rpR6gY,2407
27
27
  mm_std/concurrency/sync_task_runner.py,sha256=s5JPlLYLGQGHIxy4oDS-PN7O9gcy-yPZFoNm8RQwzcw,1780
28
- mm_std-0.3.22.dist-info/METADATA,sha256=BN3U-377sfY6l7yYDzLyW3RRkYqAU581moSJAfIDU8c,415
29
- mm_std-0.3.22.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
30
- mm_std-0.3.22.dist-info/RECORD,,
28
+ mm_std-0.3.24.dist-info/METADATA,sha256=El91GJxSAEQMfJHtBogFAyAsXGcRJ3J9sfCPCNwIehA,415
29
+ mm_std-0.3.24.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
30
+ mm_std-0.3.24.dist-info/RECORD,,