never-primp 1.0.1__cp38-abi3-win_amd64.whl → 1.0.2__cp38-abi3-win_amd64.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.

Potentially problematic release.


This version of never-primp might be problematic. Click here for more details.

never_primp/__init__.py CHANGED
@@ -3,7 +3,8 @@ from __future__ import annotations
3
3
  import asyncio
4
4
  import sys
5
5
  from functools import partial
6
- from typing import TYPE_CHECKING, TypedDict
6
+ from typing import TYPE_CHECKING, TypedDict, Iterator
7
+ from collections.abc import MutableMapping
7
8
 
8
9
  if sys.version_info <= (3, 11):
9
10
  from typing_extensions import Unpack
@@ -26,6 +27,112 @@ else:
26
27
  RequestParams = ClientRequestParams = TypedDict
27
28
 
28
29
 
30
+ class CookieJar(MutableMapping):
31
+ """
32
+ A dict-like container for managing HTTP cookies, compatible with requests.Session.cookies API.
33
+
34
+ Examples:
35
+ client = Client()
36
+
37
+ # Set cookies
38
+ client.cookies['session_id'] = 'abc123'
39
+ client.cookies['user_token'] = 'xyz789'
40
+
41
+ # Get cookies
42
+ value = client.cookies['session_id']
43
+ value = client.cookies.get('user_token', 'default')
44
+
45
+ # Update multiple cookies
46
+ client.cookies.update({'key1': 'value1', 'key2': 'value2'})
47
+
48
+ # Delete cookies
49
+ del client.cookies['session_id']
50
+
51
+ # Clear all cookies
52
+ client.cookies.clear()
53
+
54
+ # Check existence
55
+ if 'session_id' in client.cookies:
56
+ print("Session exists")
57
+
58
+ # Convert to dict
59
+ all_cookies = dict(client.cookies)
60
+ """
61
+
62
+ def __init__(self, client: RClient):
63
+ """Initialize CookieJar with a reference to the client."""
64
+ self._client = client
65
+
66
+ def __getitem__(self, name: str) -> str:
67
+ """Get a cookie value by name."""
68
+ value = self._client.get_cookie(name)
69
+ if value is None:
70
+ raise KeyError(name)
71
+ return value
72
+
73
+ def __setitem__(self, name: str, value: str) -> None:
74
+ """Set a cookie by name."""
75
+ self._client.set_cookie(name, value)
76
+
77
+ def __delitem__(self, name: str) -> None:
78
+ """Delete a cookie by name."""
79
+ # Check if cookie exists first
80
+ if self._client.get_cookie(name) is None:
81
+ raise KeyError(name)
82
+ self._client.delete_cookie(name)
83
+
84
+ def __iter__(self) -> Iterator[str]:
85
+ """Iterate over cookie names."""
86
+ return iter(self._client.get_all_cookies().keys())
87
+
88
+ def __len__(self) -> int:
89
+ """Return the number of cookies."""
90
+ return len(self._client.get_all_cookies())
91
+
92
+ def __contains__(self, name: object) -> bool:
93
+ """Check if a cookie exists."""
94
+ if not isinstance(name, str):
95
+ return False
96
+ return self._client.get_cookie(name) is not None
97
+
98
+ def __repr__(self) -> str:
99
+ """Return string representation of cookies."""
100
+ cookies = self._client.get_all_cookies()
101
+ return f"CookieJar({cookies})"
102
+
103
+ def get(self, name: str, default: str | None = None) -> str | None:
104
+ """Get a cookie value with a default fallback."""
105
+ value = self._client.get_cookie(name)
106
+ return value if value is not None else default
107
+
108
+ def update(self, cookies: dict[str, str], domain: str | None = None, path: str | None = None) -> None:
109
+ """
110
+ Update multiple cookies at once.
111
+
112
+ Args:
113
+ cookies: Dictionary of cookie names to values
114
+ domain: Optional domain for the cookies (e.g., ".example.com")
115
+ path: Optional path for the cookies (e.g., "/")
116
+ """
117
+ self._client.update_cookies(cookies, domain=domain, path=path)
118
+
119
+ def clear(self) -> None:
120
+ """Remove all cookies."""
121
+ self._client.clear_cookies()
122
+
123
+ def set(self, name: str, value: str, domain: str | None = None, path: str | None = None) -> None:
124
+ """
125
+ Set a single cookie with optional domain and path.
126
+
127
+ Args:
128
+ name: Cookie name
129
+ value: Cookie value
130
+ domain: Optional domain (e.g., ".example.com")
131
+ path: Optional path (e.g., "/")
132
+ """
133
+ self._client.set_cookie(name, value, domain=domain, path=path)
134
+
135
+
29
136
  class Client(RClient):
30
137
  """Initializes an HTTP client that can impersonate web browsers."""
31
138
 
@@ -103,6 +210,35 @@ class Client(RClient):
103
210
  http2_only: if true - use only HTTP/2, if false - use only HTTP/1. Default is False.
104
211
  """
105
212
  super().__init__()
213
+ self._cookies_jar: CookieJar | None = None
214
+
215
+ @property
216
+ def cookies(self) -> CookieJar:
217
+ """
218
+ Access the cookie jar for dict-like cookie management.
219
+
220
+ Returns:
221
+ CookieJar: A dict-like container for managing cookies.
222
+
223
+ Examples:
224
+ # Set cookies
225
+ client.cookies['session_id'] = 'abc123'
226
+
227
+ # Get cookies
228
+ value = client.cookies['session_id']
229
+
230
+ # Update cookies
231
+ client.cookies.update({'key': 'value'})
232
+
233
+ # Delete cookies
234
+ del client.cookies['session_id']
235
+
236
+ # Clear all
237
+ client.cookies.clear()
238
+ """
239
+ if self._cookies_jar is None:
240
+ self._cookies_jar = CookieJar(self)
241
+ return self._cookies_jar
106
242
 
107
243
  def __enter__(self) -> Client:
108
244
  return self
Binary file
@@ -38,6 +38,7 @@ class RequestParams(TypedDict, total=False):
38
38
  auth_bearer: str | None
39
39
  params: dict[str, str] | None
40
40
  headers: dict[str, str] | None
41
+ ordered_headers: dict[str, str] | None
41
42
  cookies: dict[str, str] | None
42
43
  timeout: float | None
43
44
  content: bytes | None
@@ -82,8 +83,10 @@ class RClient:
82
83
  auth_bearer: str | None = None,
83
84
  params: dict[str, str] | None = None,
84
85
  headers: dict[str, str] | None = None,
86
+ ordered_headers: dict[str, str] | None = None,
85
87
  timeout: float | None = None,
86
88
  cookie_store: bool | None = True,
89
+ split_cookies: bool | None = False,
87
90
  referer: bool | None = True,
88
91
  proxy: str | None = None,
89
92
  impersonate: IMPERSONATE | None = None,
@@ -94,14 +97,59 @@ class RClient:
94
97
  ca_cert_file: str | None = None,
95
98
  https_only: bool | None = False,
96
99
  http2_only: bool | None = False,
100
+ pool_idle_timeout: float | None = None,
101
+ pool_max_idle_per_host: int | None = None,
102
+ tcp_nodelay: bool | None = None,
103
+ tcp_keepalive: float | None = None,
104
+ retry_count: int | None = None,
105
+ retry_backoff: float | None = None,
97
106
  ): ...
98
107
  @property
99
108
  def headers(self) -> dict[str, str]: ...
100
109
  @headers.setter
101
110
  def headers(self, headers: dict[str, str]) -> None: ...
102
111
  def headers_update(self, headers: dict[str, str]) -> None: ...
103
- def get_cookies(self, url: str) -> dict[str, str]: ...
104
- def set_cookies(self, url: str, cookies: dict[str, str]) -> None: ...
112
+ @property
113
+ def ordered_headers(self) -> dict[str, str]: ...
114
+ @ordered_headers.setter
115
+ def ordered_headers(self, ordered_headers: dict[str, str]) -> None: ...
116
+ def ordered_headers_update(self, ordered_headers: dict[str, str]) -> None: ...
117
+ # Cookie management methods (no URL required)
118
+ def get_all_cookies(self) -> dict[str, str]: ...
119
+ def set_cookie(self, name: str, value: str, domain: str | None = None, path: str | None = None) -> None: ...
120
+ def get_cookie(self, name: str) -> str | None: ...
121
+ def update_cookies(self, cookies: dict[str, str], domain: str | None = None, path: str | None = None) -> None: ...
122
+ def delete_cookie(self, name: str) -> None: ...
123
+ def clear_cookies(self) -> None: ...
124
+ # Client properties
125
+ @property
126
+ def auth(self) -> tuple[str, str | None] | None: ...
127
+ @auth.setter
128
+ def auth(self, auth: tuple[str, str | None] | None) -> None: ...
129
+ @property
130
+ def auth_bearer(self) -> str | None: ...
131
+ @auth_bearer.setter
132
+ def auth_bearer(self, auth_bearer: str | None) -> None: ...
133
+ @property
134
+ def params(self) -> dict[str, str] | None: ...
135
+ @params.setter
136
+ def params(self, params: dict[str, str] | None) -> None: ...
137
+ @property
138
+ def timeout(self) -> float | None: ...
139
+ @timeout.setter
140
+ def timeout(self, timeout: float | None) -> None: ...
141
+ @property
142
+ def split_cookies(self) -> bool | None: ...
143
+ @split_cookies.setter
144
+ def split_cookies(self, split_cookies: bool | None) -> None: ...
145
+ @property
146
+ def retry_count(self) -> int | None: ...
147
+ @retry_count.setter
148
+ def retry_count(self, retry_count: int | None) -> None: ...
149
+ @property
150
+ def retry_backoff(self) -> float | None: ...
151
+ @retry_backoff.setter
152
+ def retry_backoff(self, retry_backoff: float | None) -> None: ...
105
153
  @property
106
154
  def proxy(self) -> str | None: ...
107
155
  @proxy.setter
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: never_primp
3
- Version: 1.0.1
3
+ Version: 1.0.2
4
4
  Classifier: Development Status :: 5 - Production/Stable
5
5
  Classifier: Intended Audience :: Developers
6
6
  Classifier: License :: OSI Approved :: MIT License
@@ -0,0 +1,8 @@
1
+ never_primp-1.0.2.dist-info/METADATA,sha256=OypnoTJVQ-gguQjVpLBGpnoepNWIY92MhlCAOSXHJwE,22313
2
+ never_primp-1.0.2.dist-info/WHEEL,sha256=CG8OzNtm0LMpJ2zhrjswlO8N-965OeMLklsQAG-nMvQ,94
3
+ never_primp-1.0.2.dist-info/licenses/LICENSE,sha256=O15TIxUAXq6sSpPu0K3CJu_dT5ZzCgIk7hQtZsf0lEk,1084
4
+ never_primp/__init__.py,sha256=KIXkg0XwGRBw889rtgMMr_lVCpXABihqDu5eVjxp8wA,18209
5
+ never_primp/never_primp.pyd,sha256=s1pse_cZvns2ogDZLtWEcPsKgXIXOMAM7jjnGjUDIgY,7859712
6
+ never_primp/never_primp.pyi,sha256=f3GNfXXLG5mS32djn56NVztEmnH5oUl_jefPiArZlkI,8001
7
+ never_primp/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
8
+ never_primp-1.0.2.dist-info/RECORD,,
@@ -1,8 +0,0 @@
1
- never_primp-1.0.1.dist-info/METADATA,sha256=XhOOmBjktcET3fVdb6Xwp6j05fUAP4tMp2fs7RUsQJE,22313
2
- never_primp-1.0.1.dist-info/WHEEL,sha256=CG8OzNtm0LMpJ2zhrjswlO8N-965OeMLklsQAG-nMvQ,94
3
- never_primp-1.0.1.dist-info/licenses/LICENSE,sha256=O15TIxUAXq6sSpPu0K3CJu_dT5ZzCgIk7hQtZsf0lEk,1084
4
- never_primp/__init__.py,sha256=RuWR5idNc3rc0Naih8oGxAd05a7P59sygZ8Amjt79Nk,13775
5
- never_primp/never_primp.pyd,sha256=ruikT36dM_5Upup7y_Tr8AJFAialOi0RWnOh5WYgDHM,7844864
6
- never_primp/never_primp.pyi,sha256=A3HZEoz6yvXOacM0JEcXF4hXOd6RTe53Sgmz9N7-Cho,5864
7
- never_primp/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
8
- never_primp-1.0.1.dist-info/RECORD,,