mm-std 0.4.14__py3-none-any.whl → 0.4.16__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
@@ -17,7 +17,7 @@ from .date import parse_date as parse_date
17
17
  from .date import utc_delta as utc_delta
18
18
  from .date import utc_now as utc_now
19
19
  from .date import utc_random as utc_random
20
- from .dict import replace_empty_dict_values as replace_empty_dict_values
20
+ from .dict import replace_empty_dict_entries as replace_empty_dict_entries
21
21
  from .env import get_dotenv as get_dotenv
22
22
  from .http.http_request import http_request as http_request
23
23
  from .http.http_request_sync import http_request_sync as http_request_sync
mm_std/dict.py CHANGED
@@ -1,16 +1,49 @@
1
- def replace_empty_dict_values(
2
- data: dict[object, object],
3
- defaults: dict[object, object] | None = None,
1
+ from collections import defaultdict
2
+ from collections.abc import Mapping, MutableMapping
3
+ from typing import TypeVar, cast
4
+
5
+ K = TypeVar("K")
6
+ V = TypeVar("V")
7
+ DictType = TypeVar("DictType", bound=MutableMapping[K, V]) # type: ignore[valid-type]
8
+
9
+
10
+ def replace_empty_dict_entries(
11
+ data: DictType,
12
+ defaults: Mapping[K, V] | None = None,
4
13
  zero_is_empty: bool = False,
5
14
  false_is_empty: bool = False,
6
- ) -> dict[object, object]:
7
- """Replace empty values in a dictionary with provided default values, or remove them if no default exists."""
15
+ empty_string_is_empty: bool = True,
16
+ ) -> DictType:
17
+ """
18
+ Replace empty entries in a dictionary with provided default values,
19
+ or remove them if no default is available. Returns the same type as the input dictionary.
20
+ """
8
21
  if defaults is None:
9
22
  defaults = {}
10
- result = {}
23
+
24
+ try:
25
+ if isinstance(data, defaultdict):
26
+ result: MutableMapping[K, V] = defaultdict(data.default_factory)
27
+ else:
28
+ result = data.__class__()
29
+ except Exception:
30
+ result = {}
31
+
11
32
  for key, value in data.items():
12
- if value is None or value == "" or (zero_is_empty and value == 0) or (false_is_empty and value is False):
13
- value = defaults.get(key, None) # noqa: PLW2901
14
- if value is not None:
15
- result[key] = value
16
- return result
33
+ should_replace = (
34
+ value is None
35
+ or (empty_string_is_empty and value == "")
36
+ or (zero_is_empty and value == 0)
37
+ or (false_is_empty and value is False)
38
+ )
39
+
40
+ if should_replace:
41
+ if key in defaults:
42
+ new_value = defaults[key]
43
+ else:
44
+ continue # Skip the key if no default is available
45
+ else:
46
+ new_value = value
47
+
48
+ result[key] = new_value
49
+ return cast(DictType, result)
@@ -1,5 +1,5 @@
1
1
  import aiohttp
2
- from aiohttp import ClientHttpProxyError
2
+ from aiohttp import ClientHttpProxyError, InvalidUrlClientError
3
3
  from aiohttp.typedefs import LooseCookies, Query
4
4
  from aiohttp_socks import ProxyConnectionError, ProxyConnector
5
5
  from multidict import CIMultiDictProxy
@@ -57,6 +57,8 @@ async def http_request(
57
57
  return HttpResponse(error=HttpError.TIMEOUT, error_message=str(err))
58
58
  except (aiohttp.ClientProxyConnectionError, ProxyConnectionError, ClientHttpProxyError) as err:
59
59
  return HttpResponse(error=HttpError.PROXY, error_message=str(err))
60
+ except InvalidUrlClientError as e:
61
+ return HttpResponse(error=HttpError.INVALID_URL, error_message=str(e))
60
62
  except Exception as err:
61
63
  return HttpResponse(error=HttpError.ERROR, error_message=str(err))
62
64
 
@@ -1,7 +1,7 @@
1
1
  from typing import Any
2
2
 
3
3
  import requests
4
- from requests.exceptions import ProxyError
4
+ from requests.exceptions import InvalidSchema, MissingSchema, ProxyError
5
5
 
6
6
  from mm_std.http.http_response import HttpError, HttpResponse
7
7
 
@@ -53,9 +53,11 @@ def http_request_sync(
53
53
  body=res.text,
54
54
  headers=dict(res.headers),
55
55
  )
56
- except requests.Timeout as err:
57
- return HttpResponse(error=HttpError.TIMEOUT, error_message=str(err))
58
- except ProxyError as err:
59
- return HttpResponse(error=HttpError.PROXY, error_message=str(err))
60
- except Exception as err:
61
- return HttpResponse(error=HttpError.ERROR, error_message=str(err))
56
+ except requests.Timeout as e:
57
+ return HttpResponse(error=HttpError.TIMEOUT, error_message=str(e))
58
+ except ProxyError as e:
59
+ return HttpResponse(error=HttpError.PROXY, error_message=str(e))
60
+ except (InvalidSchema, MissingSchema) as e:
61
+ return HttpResponse(error=HttpError.INVALID_URL, error_message=str(e))
62
+ except Exception as e:
63
+ return HttpResponse(error=HttpError.ERROR, error_message=str(e))
@@ -15,6 +15,7 @@ from mm_std.result import Result
15
15
  class HttpError(str, enum.Enum):
16
16
  TIMEOUT = "timeout"
17
17
  PROXY = "proxy"
18
+ INVALID_URL = "invalid_url"
18
19
  CONNECTION = "connection"
19
20
  ERROR = "error"
20
21
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mm-std
3
- Version: 0.4.14
3
+ Version: 0.4.16
4
4
  Requires-Python: >=3.12
5
5
  Requires-Dist: aiohttp-socks~=0.10.1
6
6
  Requires-Dist: aiohttp~=3.11.18
@@ -1,9 +1,9 @@
1
- mm_std/__init__.py,sha256=SlfY7KoSiv9YEkeBrjUksIUtLkkG17Ii-DYpC1TGphY,2886
1
+ mm_std/__init__.py,sha256=atBLjXR-O2osgfiZru7mA2SSAPb60fRRDFqxf1soMZM,2888
2
2
  mm_std/command.py,sha256=ze286wjUjg0QSTgIu-2WZks53_Vclg69UaYYgPpQvCU,1283
3
3
  mm_std/config.py,sha256=3-FxFCtOffY2t9vuu9adojwbzTPwdAH2P6qDaZnHLbY,3206
4
4
  mm_std/crypto.py,sha256=jdk0_TCmeU0pPXMyz9xH6kQHSjjZ9GcGClBwQps5vBo,340
5
5
  mm_std/date.py,sha256=976eEkSONuNqHQBgSRu8hrtH23tJqztbmHFHLdbP2TY,1879
6
- mm_std/dict.py,sha256=6GkhJPXD0LiJDxPcYe6jPdEDw-MN7P7mKu6U5XxwYDk,675
6
+ mm_std/dict.py,sha256=DxFbZnl5KK4vJ4wLH_pCT0PWzfaIL3YyLNpRsVexfjw,1465
7
7
  mm_std/env.py,sha256=5zaR9VeIfObN-4yfgxoFeU5IM1GDeZZj9SuYf7t9sOA,125
8
8
  mm_std/fs.py,sha256=RwarNRJq3tIMG6LVX_g03hasfYpjYFh_O27oVDt5IPQ,291
9
9
  mm_std/json_.py,sha256=YVvROb5egcF1aQ2fXzyWG8Yw0JvYwpNBwtcBzsOADPo,1133
@@ -25,9 +25,9 @@ mm_std/concurrency/sync_decorators.py,sha256=syCQBOmN7qPO55yzgJB2rbkh10CVww376hm
25
25
  mm_std/concurrency/sync_scheduler.py,sha256=j4tBL_cBI1spr0cZplTA7N2CoYsznuORMeRN8rpR6gY,2407
26
26
  mm_std/concurrency/sync_task_runner.py,sha256=s5JPlLYLGQGHIxy4oDS-PN7O9gcy-yPZFoNm8RQwzcw,1780
27
27
  mm_std/http/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
28
- mm_std/http/http_request.py,sha256=pPLQk6tIbMLSgkua9kQjij08sC1tabIRLwzVoApIa8M,3947
29
- mm_std/http/http_request_sync.py,sha256=b2ieX-scqFTj1QQduvKttU5Ja1pgd2OkUGAJ4zlpmJ0,1690
30
- mm_std/http/http_response.py,sha256=vrRv7Rjr5_kTUGllfW5oJ8ZqkcfiXc9T8PlBGAr-TBM,3884
31
- mm_std-0.4.14.dist-info/METADATA,sha256=iq8ucYUAh63VvnankDUPCIyAiLmGL9C1iveVI1xarc8,415
32
- mm_std-0.4.14.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
33
- mm_std-0.4.14.dist-info/RECORD,,
28
+ mm_std/http/http_request.py,sha256=6bg3t49c3dG0jKRFxhcceeYb5yKrMoZwuyb25zBG3tY,4088
29
+ mm_std/http/http_request_sync.py,sha256=zXLeDplYWTFIwaD1Ydyg9yTi37WcI-fReLM0mVnuvhM,1835
30
+ mm_std/http/http_response.py,sha256=7ZllZFPKJ9s6m-18Dfhrm7hwc2XFnyX7ppt0O8gNmlE,3916
31
+ mm_std-0.4.16.dist-info/METADATA,sha256=_cSVs-cNmY9lZicgVuawtbNuG5vDmpn6rrFQY_bzwI4,415
32
+ mm_std-0.4.16.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
33
+ mm_std-0.4.16.dist-info/RECORD,,