browserfetch 0.8.0__tar.gz → 0.9.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.
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.3
2
2
  Name: browserfetch
3
- Version: 0.8.0
3
+ Version: 0.9.0
4
4
  Summary: fetch in Python using your browser!
5
5
  Keywords: browser,fetch,python,cookies
6
6
  Requires-Python: >=3.11
@@ -1,4 +1,4 @@
1
- __version__ = '0.8.0'
1
+ __version__ = '0.9.0'
2
2
 
3
3
  import atexit
4
4
  from asyncio import (
@@ -137,6 +137,7 @@ async def _(request):
137
137
  except TypeError:
138
138
  logger.info('host WebSocket was closed')
139
139
  hosts[host] = Event()
140
+ return ws
140
141
 
141
142
 
142
143
  @routes.get('/relay')
@@ -202,11 +203,11 @@ async def evaluate(
202
203
  async def fetch(
203
204
  url: str,
204
205
  *,
205
- params: dict = None,
206
- body: bytes = None,
206
+ params: dict | None = None,
207
+ body: bytes | None = None,
207
208
  timeout: int | float = 95,
208
- options: dict = None,
209
- host=None,
209
+ options: dict | None = None,
210
+ host: str | None = None,
210
211
  ) -> Response:
211
212
  """Fetch using browser fetch API available on host.
212
213
 
@@ -242,9 +243,9 @@ async def fetch(
242
243
  async def get(
243
244
  url: str,
244
245
  *,
245
- params: dict = None,
246
- options: dict = None,
247
- host: str = None,
246
+ params: dict | None = None,
247
+ options: dict | None = None,
248
+ host: str | None = None,
248
249
  timeout: int | float = 95,
249
250
  ) -> Response:
250
251
  if options is None:
@@ -259,28 +260,31 @@ async def get(
259
260
  async def post(
260
261
  url: str,
261
262
  *,
262
- params: dict = None,
263
- body: bytes = None,
264
- data: dict = None,
265
- json=None,
263
+ params: dict | None = None,
264
+ data: bytes | dict | str | None = None,
265
+ form: dict | None = None,
266
266
  timeout: int | float = 95,
267
- options: dict = None,
268
- host: str = None,
267
+ options: dict | None = None,
268
+ host: str | None = None,
269
269
  ) -> Response:
270
270
  if options is None:
271
271
  options: dict[str, Any] = {'method': 'POST'}
272
272
  else:
273
273
  options['method'] = 'POST'
274
274
 
275
- if json is not None:
276
- assert body is None
277
- body = dumps(json).encode()
278
- headers = options.setdefault('headers', {})
279
- headers['Content-Type'] = 'application/json'
280
-
281
275
  if data is not None:
282
- assert body is None
283
- body = urlencode(data).encode()
276
+ if isinstance(data, str):
277
+ body = data.encode()
278
+ elif isinstance(data, bytes):
279
+ body = data
280
+ else:
281
+ body = dumps(data).encode()
282
+ headers = options.setdefault('headers', {})
283
+ headers['Content-Type'] = 'application/json'
284
+
285
+ if form is not None:
286
+ assert data is None
287
+ body = urlencode(form).encode()
284
288
  headers = options.setdefault('headers', {})
285
289
  headers['Content-Type'] = 'application/x-www-form-urlencoded'
286
290
 
@@ -4,10 +4,11 @@
4
4
  // @match https://example.com/
5
5
  // @grant GM_registerMenuCommand
6
6
  // ==/UserScript==
7
+ // @ts-check
7
8
  (() => {
8
9
  /**
9
- * @param {Blob} body
10
- * @param {j} Object
10
+ * @param {Uint8Array | null} body
11
+ * @param {Object} req
11
12
  * @returns {Promise<Blob>}
12
13
  */
13
14
  async function doFetch(req, body) {
@@ -47,16 +48,27 @@
47
48
 
48
49
  /**
49
50
  *
50
- * @param {String} s
51
+ * @param {Object} req
51
52
  * @returns {Promise<Uint8Array>}
52
53
  */
53
54
  async function doEval(req) {
54
55
  var evalled, resp;
55
56
  try {
56
57
  evalled = eval(req['string']);
57
- resp = {'result': evalled, 'event_id': req['event_id']};
58
+ switch (evalled.constructor.name) {
59
+ case 'AsyncFunction':
60
+ evalled = await evalled;
61
+ break;
62
+ case 'Promise':
63
+ evalled = await evalled;
64
+ break;
65
+ case 'Function':
66
+ evalled = evalled();
67
+ break;
68
+ }
69
+ resp = { 'result': evalled, 'event_id': req['event_id'] };
58
70
  } catch (err) {
59
- resp = {'result': err.toString(), 'event_id': req['event_id']};
71
+ resp = { 'result': err.toString(), 'event_id': req['event_id'] };
60
72
  }
61
73
  return new TextEncoder().encode(JSON.stringify(resp));
62
74
  }
@@ -64,7 +76,7 @@
64
76
  /**
65
77
  *
66
78
  * @param {ArrayBuffer} d
67
- * @returns {Array.<{binaryPart: Uint8Array, jsonPart: Object}>}
79
+ * @returns {[Uint8Array | null, Object]}
68
80
  */
69
81
  function parseData(d) {
70
82
  var blob, jArray;
@@ -91,12 +103,12 @@
91
103
  }
92
104
 
93
105
  ws.onclose = () => {
94
- console.error('browserfetch: WebSocket was closed; will retry in 5 seconds');
106
+ console.error('WebSocket was closed; will retry in 5 seconds');
95
107
  setTimeout(connect, 5000);
96
108
  };
97
109
 
98
110
  ws.onmessage = async (evt) => {
99
- var result, j, b;
111
+ var /**@type {Uint8Array | Blob} */ result, j, b;
100
112
  [b, j] = parseData(evt.data);
101
113
  switch (j['action']) {
102
114
  case 'fetch':
@@ -104,12 +116,21 @@
104
116
  break;
105
117
  case 'eval':
106
118
  result = await doEval(j);
119
+ break;
120
+ default:
121
+ result = new TextEncoder().encode(JSON.stringify({
122
+ 'event_id': j['event_id'],
123
+ 'error': `Action ${j['action']} is not defined.`
124
+ }));
125
+ break;
107
126
  }
108
127
  ws.send(result);
109
128
  }
110
129
  };
111
130
 
131
+ // @ts-ignore
112
132
  if (window.GM_registerMenuCommand) {
133
+ // @ts-ignore
113
134
  GM_registerMenuCommand(
114
135
  'connect to browserfetch',
115
136
  connect
@@ -35,13 +35,22 @@ line-length = 79
35
35
  format.quote-style = 'single'
36
36
  lint.isort.combine-as-imports = true
37
37
  lint.extend-select = [
38
+ 'FA', # flake8-future-annotations
38
39
  'I', # isort
39
40
  'UP', # pyupgrade
40
41
  ]
41
42
  lint.ignore = [
42
- 'UP027', # list comprehensions are faster than generator expressions
43
43
  'E721', # Do not compare types, use `isinstance()`
44
44
  ]
45
45
 
46
46
  [tool.pytest.ini_options]
47
47
  addopts = '--quiet --tb=short'
48
+
49
+ [tool.pyright]
50
+ typeCheckingMode = 'standard'
51
+ reportDeprecated = "warning"
52
+ reportPropertyTypeMismatch = "warning"
53
+ reportUnnecessaryCast = "warning"
54
+ reportUnnecessaryContains = "warning"
55
+ reportUnnecessaryIsInstance = "warning"
56
+ reportUnnecessaryTypeIgnoreComment = true
File without changes
File without changes