browserfetch 0.14.0__tar.gz → 0.15.0__tar.gz
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.
- {browserfetch-0.14.0 → browserfetch-0.15.0}/PKG-INFO +2 -2
- {browserfetch-0.14.0 → browserfetch-0.15.0}/browserfetch/__init__.py +20 -74
- {browserfetch-0.14.0 → browserfetch-0.15.0}/browserfetch/browserfetch.js +34 -8
- {browserfetch-0.14.0 → browserfetch-0.15.0}/pyproject.toml +3 -2
- {browserfetch-0.14.0 → browserfetch-0.15.0}/README.rst +0 -0
- {browserfetch-0.14.0 → browserfetch-0.15.0}/browserfetch/__main__.py +0 -0
- {browserfetch-0.14.0 → browserfetch-0.15.0}/browserfetch/browserfetch.egg-info/PKG-INFO +0 -0
- {browserfetch-0.14.0 → browserfetch-0.15.0}/browserfetch/browserfetch.egg-info/SOURCES.txt +0 -0
- {browserfetch-0.14.0 → browserfetch-0.15.0}/browserfetch/browserfetch.egg-info/dependency_links.txt +0 -0
- {browserfetch-0.14.0 → browserfetch-0.15.0}/browserfetch/browserfetch.egg-info/not-zip-safe +0 -0
- {browserfetch-0.14.0 → browserfetch-0.15.0}/browserfetch/browserfetch.egg-info/requires.txt +0 -0
- {browserfetch-0.14.0 → browserfetch-0.15.0}/browserfetch/browserfetch.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: browserfetch
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.15.0
|
|
4
4
|
Summary: fetch in Python using your browser!
|
|
5
5
|
Keywords: browser,fetch,python,cookies
|
|
6
6
|
License: GNU General Public License v3 (GPLv3)
|
|
@@ -8,7 +8,7 @@ Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3)
|
|
|
8
8
|
Requires-Dist: aiohttp
|
|
9
9
|
Requires-Dist: pyperclip
|
|
10
10
|
Requires-Dist: cyclopts
|
|
11
|
-
Requires-Python: >=3.
|
|
11
|
+
Requires-Python: >=3.13
|
|
12
12
|
Project-URL: Homepage, https://github.com/5j9/browserfetch
|
|
13
13
|
Description-Content-Type: text/x-rst
|
|
14
14
|
|
|
@@ -1,11 +1,9 @@
|
|
|
1
|
-
__version__ = '0.
|
|
1
|
+
__version__ = '0.15.0'
|
|
2
2
|
__all__ = [
|
|
3
3
|
'BrowserError',
|
|
4
4
|
'Response',
|
|
5
5
|
'evaluate',
|
|
6
6
|
'fetch',
|
|
7
|
-
'get',
|
|
8
|
-
'post',
|
|
9
7
|
'start_server',
|
|
10
8
|
]
|
|
11
9
|
import atexit
|
|
@@ -23,7 +21,6 @@ from html import escape
|
|
|
23
21
|
from json import dumps as _dumps, loads as _loads
|
|
24
22
|
from logging import getLogger
|
|
25
23
|
from typing import Any as _Any
|
|
26
|
-
from urllib.parse import parse_qsl, urlencode, urlparse, urlunparse
|
|
27
24
|
|
|
28
25
|
from aiohttp import ClientSession, ClientWebSocketResponse
|
|
29
26
|
from aiohttp.web import (
|
|
@@ -260,23 +257,29 @@ async def evaluate(
|
|
|
260
257
|
async def fetch(
|
|
261
258
|
url: str,
|
|
262
259
|
*,
|
|
260
|
+
method: str | None = None,
|
|
263
261
|
params: dict | None = None,
|
|
264
262
|
data: _Any = None,
|
|
265
263
|
form: dict | None = None,
|
|
266
264
|
timeout: int | float = 95,
|
|
267
|
-
|
|
265
|
+
headers: dict | None = None,
|
|
268
266
|
host: str | None = None,
|
|
267
|
+
options: dict | None = None,
|
|
269
268
|
) -> Response:
|
|
270
269
|
"""Fetch using browser fetch API available on host.
|
|
271
270
|
|
|
272
|
-
This
|
|
273
|
-
|
|
274
|
-
similar to Playwright's API.
|
|
271
|
+
This function tries to be similar to Playwright's API.
|
|
272
|
+
(but it's not identical)
|
|
275
273
|
|
|
276
274
|
:param url: the URL of the resource you want to fetch.
|
|
277
275
|
:param params: parameters to be url-encoded and added to url.
|
|
278
276
|
:param data: the JSON-serializable body of the request.
|
|
277
|
+
If data is str or bytes, `application/octet-stream` content-type
|
|
278
|
+
header will be set. Otherwise, the object will be encoded and sent as
|
|
279
|
+
`application/json`.
|
|
279
280
|
:param form: a dict of form data to be url-encoded.
|
|
281
|
+
Passing `form` will automatically set
|
|
282
|
+
`application/x-www-form-urlencoded` header.
|
|
280
283
|
:param timeout: timeout in seconds (do not add to options).
|
|
281
284
|
:param options: See https://developer.mozilla.org/en-US/docs/Web/API/fetch
|
|
282
285
|
:param host: `location.host` of the tab that is supposed to handle this
|
|
@@ -288,40 +291,28 @@ async def fetch(
|
|
|
288
291
|
assert form is None
|
|
289
292
|
if isinstance(data, str):
|
|
290
293
|
body = data.encode()
|
|
294
|
+
content_type = 'application/octet-stream'
|
|
291
295
|
elif isinstance(data, bytes):
|
|
292
296
|
body = data
|
|
297
|
+
content_type = 'application/octet-stream'
|
|
293
298
|
else:
|
|
294
299
|
body = _jdumps(data).encode()
|
|
295
|
-
|
|
296
|
-
options = {}
|
|
297
|
-
headers = options.setdefault('headers', {})
|
|
298
|
-
headers['Content-Type'] = 'application/json'
|
|
299
|
-
elif form is not None:
|
|
300
|
-
body = urlencode(form).encode()
|
|
301
|
-
if options is None:
|
|
302
|
-
options = {}
|
|
303
|
-
headers = options.setdefault('headers', {})
|
|
304
|
-
headers['Content-Type'] = 'application/x-www-form-urlencoded'
|
|
300
|
+
content_type = 'application/json'
|
|
305
301
|
else:
|
|
306
|
-
body = None
|
|
307
|
-
|
|
308
|
-
if params is not None:
|
|
309
|
-
parsed_url = urlparse(url)
|
|
310
|
-
url = urlunparse(
|
|
311
|
-
parsed_url._replace(
|
|
312
|
-
query=urlencode(
|
|
313
|
-
[*parse_qsl(parsed_url.query), *params.items()]
|
|
314
|
-
)
|
|
315
|
-
)
|
|
316
|
-
)
|
|
302
|
+
content_type = body = None
|
|
317
303
|
|
|
318
304
|
d = await _request(
|
|
319
305
|
host,
|
|
320
306
|
{
|
|
321
307
|
'action': 'fetch',
|
|
322
308
|
'url': url,
|
|
309
|
+
'method': method,
|
|
310
|
+
'headers': headers,
|
|
323
311
|
'options': options,
|
|
324
312
|
'timeout': timeout,
|
|
313
|
+
'params': params,
|
|
314
|
+
'form': form,
|
|
315
|
+
'content_type': content_type,
|
|
325
316
|
},
|
|
326
317
|
body,
|
|
327
318
|
)
|
|
@@ -332,51 +323,6 @@ async def fetch(
|
|
|
332
323
|
return Response(**d)
|
|
333
324
|
|
|
334
325
|
|
|
335
|
-
async def get(
|
|
336
|
-
url: str,
|
|
337
|
-
*,
|
|
338
|
-
params: dict | None = None,
|
|
339
|
-
options: dict | None = None,
|
|
340
|
-
host: str | None = None,
|
|
341
|
-
timeout: int | float = 95,
|
|
342
|
-
) -> Response:
|
|
343
|
-
"""Convenience function for a GET request."""
|
|
344
|
-
if options is None:
|
|
345
|
-
options = {'method': 'GET'}
|
|
346
|
-
else:
|
|
347
|
-
options['method'] = 'GET'
|
|
348
|
-
return await fetch(
|
|
349
|
-
url, options=options, host=host, timeout=timeout, params=params
|
|
350
|
-
)
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
async def post(
|
|
354
|
-
url: str,
|
|
355
|
-
*,
|
|
356
|
-
params: dict | None = None,
|
|
357
|
-
data: _Any = None,
|
|
358
|
-
form: dict | None = None,
|
|
359
|
-
timeout: int | float = 95,
|
|
360
|
-
options: dict | None = None,
|
|
361
|
-
host: str | None = None,
|
|
362
|
-
) -> Response:
|
|
363
|
-
"""Convenience function for a POST request."""
|
|
364
|
-
if options is None:
|
|
365
|
-
options = {'method': 'POST'}
|
|
366
|
-
else:
|
|
367
|
-
options['method'] = 'POST'
|
|
368
|
-
|
|
369
|
-
return await fetch(
|
|
370
|
-
url,
|
|
371
|
-
options=options,
|
|
372
|
-
host=host,
|
|
373
|
-
timeout=timeout,
|
|
374
|
-
params=params,
|
|
375
|
-
data=data,
|
|
376
|
-
form=form,
|
|
377
|
-
)
|
|
378
|
-
|
|
379
|
-
|
|
380
326
|
app = Application()
|
|
381
327
|
app.add_routes(routes)
|
|
382
328
|
app_runner = AppRunner(app)
|
|
@@ -7,16 +7,42 @@
|
|
|
7
7
|
// @ts-check
|
|
8
8
|
(async () => {
|
|
9
9
|
/**
|
|
10
|
-
* @param {Uint8Array | null} body
|
|
10
|
+
* @param {Uint8Array | URLSearchParams | null} body
|
|
11
11
|
* @param {any} req
|
|
12
12
|
* @returns {Promise<Blob>}
|
|
13
13
|
*/
|
|
14
14
|
async function doFetch(req, body) {
|
|
15
|
-
var returnData, response;
|
|
16
|
-
var
|
|
15
|
+
var returnData, response, headers;
|
|
16
|
+
var url = req.url;
|
|
17
|
+
var options = req.options || {};
|
|
17
18
|
|
|
18
|
-
if (req
|
|
19
|
-
options.
|
|
19
|
+
if (req.method) {
|
|
20
|
+
options.method = req.method;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
if (req.headers) {
|
|
24
|
+
headers = { ...options.headers, ...req.headers };
|
|
25
|
+
} else {
|
|
26
|
+
headers = options.headers || {};
|
|
27
|
+
}
|
|
28
|
+
options.headers = headers;
|
|
29
|
+
|
|
30
|
+
if (req.params) {
|
|
31
|
+
url = new URL(url);
|
|
32
|
+
for (const [key, value] of Object.entries(req.params)) {
|
|
33
|
+
url.searchParams.set(key, value);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
if (req.form) {
|
|
38
|
+
body = new URLSearchParams(req.form);
|
|
39
|
+
headers['Content-Type'] = 'application/x-www-form-urlencoded';
|
|
40
|
+
} else if (req.content_type) {
|
|
41
|
+
headers['Content-Type'] = req.content_type;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
if (req.timeout) {
|
|
45
|
+
options.signal = AbortSignal.timeout(req.timeout * 1000);
|
|
20
46
|
}
|
|
21
47
|
|
|
22
48
|
if (body !== null) {
|
|
@@ -24,9 +50,9 @@
|
|
|
24
50
|
}
|
|
25
51
|
|
|
26
52
|
try {
|
|
27
|
-
var r = await fetch(
|
|
53
|
+
var r = await fetch(url, options);
|
|
28
54
|
returnData = {
|
|
29
|
-
'event_id': req
|
|
55
|
+
'event_id': req.event_id,
|
|
30
56
|
'headers': Object.fromEntries([...r.headers]),
|
|
31
57
|
'ok': r.ok,
|
|
32
58
|
'redirected': r.redirected,
|
|
@@ -38,7 +64,7 @@
|
|
|
38
64
|
response = await r.blob();
|
|
39
65
|
} catch (/**@type {any} */err) {
|
|
40
66
|
returnData = {
|
|
41
|
-
'event_id': req
|
|
67
|
+
'event_id': req.event_id,
|
|
42
68
|
'error': err.toString()
|
|
43
69
|
};
|
|
44
70
|
response = "";
|
|
@@ -9,13 +9,13 @@ keywords = ["browser", "fetch", "python", "cookies"]
|
|
|
9
9
|
classifiers = [
|
|
10
10
|
"License :: OSI Approved :: GNU General Public License v3 (GPLv3)",
|
|
11
11
|
]
|
|
12
|
-
requires-python = ">=3.
|
|
12
|
+
requires-python = ">=3.13"
|
|
13
13
|
dependencies = [
|
|
14
14
|
"aiohttp",
|
|
15
15
|
"pyperclip",
|
|
16
16
|
"cyclopts",
|
|
17
17
|
]
|
|
18
|
-
version = "0.
|
|
18
|
+
version = "0.15.0"
|
|
19
19
|
|
|
20
20
|
[[authors]]
|
|
21
21
|
name = "5j9"
|
|
@@ -76,5 +76,6 @@ module-name = "browserfetch"
|
|
|
76
76
|
dev = [
|
|
77
77
|
"playwright>=1.52.0",
|
|
78
78
|
"pytest>=8.4.0",
|
|
79
|
+
"pytest-aiohttp>=1.1.0",
|
|
79
80
|
"pytest-asyncio>=1.0.0",
|
|
80
81
|
]
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{browserfetch-0.14.0 → browserfetch-0.15.0}/browserfetch/browserfetch.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{browserfetch-0.14.0 → browserfetch-0.15.0}/browserfetch/browserfetch.egg-info/top_level.txt
RENAMED
|
File without changes
|