rapydscript-ns 0.9.1 → 0.9.3
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.
- package/CHANGELOG.md +22 -1
- package/PYTHON_GAPS.md +420 -0
- package/README.md +154 -30
- package/TODO.md +22 -7
- package/language-service/index.js +241 -12
- package/language-service/language-service.d.ts +1 -1
- package/memory/project_string_impl.md +43 -0
- package/package.json +6 -2
- package/release/baselib-plain-pretty.js +248 -38
- package/release/baselib-plain-ugly.js +8 -8
- package/release/compiler.js +821 -305
- package/release/signatures.json +15 -15
- package/src/ast.pyj +4 -1
- package/src/baselib-builtins.pyj +56 -2
- package/src/baselib-containers.pyj +2 -0
- package/src/baselib-errors.pyj +7 -3
- package/src/baselib-internal.pyj +51 -6
- package/src/baselib-str.pyj +5 -3
- package/src/lib/asyncio.pyj +534 -0
- package/src/lib/base64.pyj +399 -0
- package/src/lib/bisect.pyj +73 -0
- package/src/lib/collections.pyj +1 -1
- package/src/lib/csv.pyj +494 -0
- package/src/lib/heapq.pyj +98 -0
- package/src/lib/html.pyj +382 -0
- package/src/lib/http/__init__.pyj +98 -0
- package/src/lib/http/client.pyj +304 -0
- package/src/lib/http/cookies.pyj +236 -0
- package/src/lib/logging.pyj +672 -0
- package/src/lib/pythonize.pyj +1 -1
- package/src/lib/string.pyj +357 -0
- package/src/lib/textwrap.pyj +329 -0
- package/src/lib/urllib/__init__.pyj +14 -0
- package/src/lib/urllib/error.pyj +66 -0
- package/src/lib/urllib/parse.pyj +475 -0
- package/src/lib/urllib/request.pyj +86 -0
- package/src/monaco-language-service/analyzer.js +5 -2
- package/src/monaco-language-service/completions.js +26 -0
- package/src/monaco-language-service/diagnostics.js +204 -5
- package/src/monaco-language-service/index.js +2 -2
- package/src/monaco-language-service/scope.js +1 -0
- package/src/output/functions.pyj +152 -6
- package/src/output/loops.pyj +26 -2
- package/src/output/modules.pyj +1 -1
- package/src/output/operators.pyj +15 -0
- package/src/output/stream.pyj +0 -1
- package/src/parse.pyj +80 -17
- package/src/tokenizer.pyj +1 -1
- package/test/async_generators.pyj +144 -0
- package/test/asyncio.pyj +307 -0
- package/test/base64.pyj +202 -0
- package/test/bisect.pyj +178 -0
- package/test/csv.pyj +405 -0
- package/test/float_special.pyj +64 -0
- package/test/heapq.pyj +174 -0
- package/test/html.pyj +212 -0
- package/test/http.pyj +259 -0
- package/test/imports.pyj +7 -0
- package/test/logging.pyj +356 -0
- package/test/long.pyj +130 -0
- package/test/parenthesized_with.pyj +141 -0
- package/test/python_compat.pyj +3 -5
- package/test/python_modulo.pyj +76 -0
- package/test/python_modulo_off.pyj +21 -0
- package/test/str.pyj +14 -0
- package/test/string.pyj +245 -0
- package/test/textwrap.pyj +172 -0
- package/test/type_display.pyj +48 -0
- package/test/type_enforcement.pyj +164 -0
- package/test/unit/index.js +80 -6
- package/test/unit/language-service-completions.js +119 -0
- package/test/unit/language-service-scope.js +32 -0
- package/test/unit/language-service.js +128 -4
- package/test/unit/run-language-service.js +17 -3
- package/test/unit/web-repl.js +2094 -29
- package/test/urllib.pyj +193 -0
- package/tools/compile.js +1 -1
- package/tools/compiler.d.ts +367 -0
- package/tools/embedded_compiler.js +7 -7
- package/web-repl/main.js +1 -1
- package/web-repl/rapydscript.js +3 -3
- package/test/omit_function_metadata.pyj +0 -20
|
@@ -0,0 +1,534 @@
|
|
|
1
|
+
###########################################################
|
|
2
|
+
# RapydScript Standard Library
|
|
3
|
+
# asyncio — Python-compatible async I/O module
|
|
4
|
+
###########################################################
|
|
5
|
+
#
|
|
6
|
+
# Maps Python asyncio APIs to JavaScript's native Promise/async-await model.
|
|
7
|
+
#
|
|
8
|
+
# async def / await syntax compiles directly to JS:
|
|
9
|
+
# async def main(): → async function main() {
|
|
10
|
+
# result = await coro() → let result = await coro()
|
|
11
|
+
#
|
|
12
|
+
# asyncio.run(coro) returns the Promise; it cannot block (JS single-threaded).
|
|
13
|
+
# async with / async for are not supported in the compiler; use
|
|
14
|
+
# .acquire()/.release() / .get()/.put() explicitly instead.
|
|
15
|
+
# No real event-loop management: JS always has exactly one event loop.
|
|
16
|
+
|
|
17
|
+
# ---------------------------------------------------------------------------
|
|
18
|
+
# Constants
|
|
19
|
+
# ---------------------------------------------------------------------------
|
|
20
|
+
|
|
21
|
+
FIRST_COMPLETED = 'FIRST_COMPLETED'
|
|
22
|
+
FIRST_EXCEPTION = 'FIRST_EXCEPTION'
|
|
23
|
+
ALL_COMPLETED = 'ALL_COMPLETED'
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
# ---------------------------------------------------------------------------
|
|
27
|
+
# Exceptions
|
|
28
|
+
# ---------------------------------------------------------------------------
|
|
29
|
+
|
|
30
|
+
class CancelledError(Exception):
|
|
31
|
+
pass
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class TimeoutError(Exception):
|
|
35
|
+
pass
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class InvalidStateError(Exception):
|
|
39
|
+
pass
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
class QueueEmpty(Exception):
|
|
43
|
+
pass
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
class QueueFull(Exception):
|
|
47
|
+
pass
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
class RuntimeError(Exception):
|
|
51
|
+
pass
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
# ---------------------------------------------------------------------------
|
|
55
|
+
# Core coroutine functions
|
|
56
|
+
# ---------------------------------------------------------------------------
|
|
57
|
+
|
|
58
|
+
def sleep(seconds):
|
|
59
|
+
"""Return a Promise that resolves after `seconds` seconds.
|
|
60
|
+
|
|
61
|
+
Equivalent to Python's asyncio.sleep(). Accepts fractional seconds.
|
|
62
|
+
A value of 0 yields control to the event loop once (next microtask tick
|
|
63
|
+
in practice, since setTimeout(0) is used).
|
|
64
|
+
"""
|
|
65
|
+
v"""return new Promise(function(resolve) { setTimeout(resolve, (seconds || 0) * 1000); });"""
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def gather(*coros, **kwargs):
|
|
69
|
+
"""Wait for multiple coroutines/Promises to complete.
|
|
70
|
+
|
|
71
|
+
Returns a Promise that resolves with a list of all results (in order).
|
|
72
|
+
If any coroutine raises, the returned Promise rejects (unless
|
|
73
|
+
return_exceptions=True is passed, in which case exceptions are returned
|
|
74
|
+
as values in the result list rather than propagating).
|
|
75
|
+
|
|
76
|
+
Equivalent to Python's asyncio.gather().
|
|
77
|
+
"""
|
|
78
|
+
v"""
|
|
79
|
+
var _re = kwargs && kwargs.return_exceptions;
|
|
80
|
+
if (_re) {
|
|
81
|
+
return Promise.allSettled(coros).then(function(results) {
|
|
82
|
+
return results.map(function(r) {
|
|
83
|
+
return r.status === 'fulfilled' ? r.value : r.reason;
|
|
84
|
+
});
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
return Promise.all(coros);
|
|
88
|
+
"""
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def create_task(coro):
|
|
92
|
+
"""Schedule a coroutine to run and return it.
|
|
93
|
+
|
|
94
|
+
In JS, Promises start executing immediately when created, so this is a
|
|
95
|
+
no-op that just returns the Promise. Equivalent to asyncio.create_task().
|
|
96
|
+
"""
|
|
97
|
+
return coro
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def ensure_future(coro):
|
|
101
|
+
"""Wrap a coroutine in a Task. Alias for create_task()."""
|
|
102
|
+
return coro
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
def run(coro):
|
|
106
|
+
"""Run a top-level coroutine (returns the underlying Promise).
|
|
107
|
+
|
|
108
|
+
In Python this blocks until the coroutine finishes. In JS there is no
|
|
109
|
+
blocking, so this simply returns the Promise. The JS event loop handles
|
|
110
|
+
it automatically.
|
|
111
|
+
"""
|
|
112
|
+
return coro
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
def shield(coro):
|
|
116
|
+
"""Protect a coroutine from external cancellation.
|
|
117
|
+
|
|
118
|
+
Returns a new Promise that resolves/rejects exactly when `coro` does, but
|
|
119
|
+
is otherwise independent (cancelling the wrapper does not cancel `coro`).
|
|
120
|
+
"""
|
|
121
|
+
v"""
|
|
122
|
+
return new Promise(function(resolve, reject) {
|
|
123
|
+
Promise.resolve(coro).then(resolve, reject);
|
|
124
|
+
});
|
|
125
|
+
"""
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
def wait_for(coro, timeout):
|
|
129
|
+
"""Wait for a coroutine to complete with a timeout.
|
|
130
|
+
|
|
131
|
+
Rejects with TimeoutError if the coroutine does not complete within
|
|
132
|
+
`timeout` seconds. Equivalent to Python's asyncio.wait_for().
|
|
133
|
+
"""
|
|
134
|
+
_TimeoutError = TimeoutError
|
|
135
|
+
v"""
|
|
136
|
+
return new Promise(function(resolve, reject) {
|
|
137
|
+
var done = false;
|
|
138
|
+
var timer = setTimeout(function() {
|
|
139
|
+
if (!done) {
|
|
140
|
+
done = true;
|
|
141
|
+
reject(new _TimeoutError('wait_for timed out after ' + timeout + 's'));
|
|
142
|
+
}
|
|
143
|
+
}, (timeout || 0) * 1000);
|
|
144
|
+
Promise.resolve(coro).then(
|
|
145
|
+
function(v) { if (!done) { done = true; clearTimeout(timer); resolve(v); } },
|
|
146
|
+
function(e) { if (!done) { done = true; clearTimeout(timer); reject(e); } }
|
|
147
|
+
);
|
|
148
|
+
});
|
|
149
|
+
"""
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
def wait(aws, return_when=ALL_COMPLETED):
|
|
153
|
+
"""Wait for the Promises in `aws` to complete.
|
|
154
|
+
|
|
155
|
+
Returns a Promise that resolves with {done, pending} sets.
|
|
156
|
+
`return_when` controls when the function returns:
|
|
157
|
+
ALL_COMPLETED — wait for all (default)
|
|
158
|
+
FIRST_COMPLETED — return as soon as one completes
|
|
159
|
+
FIRST_EXCEPTION — return as soon as one raises (not yet fully supported)
|
|
160
|
+
"""
|
|
161
|
+
_first = FIRST_COMPLETED
|
|
162
|
+
v"""
|
|
163
|
+
var promises = Array.isArray(aws) ? aws.slice() : Array.from(aws);
|
|
164
|
+
if (return_when === _first) {
|
|
165
|
+
return Promise.race(promises).then(function(v) {
|
|
166
|
+
return { done: [v], pending: [] };
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
return Promise.allSettled(promises).then(function(results) {
|
|
170
|
+
var done = [], pending = [];
|
|
171
|
+
results.forEach(function(r) {
|
|
172
|
+
done.push(r.status === 'fulfilled' ? r.value : r.reason);
|
|
173
|
+
});
|
|
174
|
+
return { done: done, pending: pending };
|
|
175
|
+
});
|
|
176
|
+
"""
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
# ---------------------------------------------------------------------------
|
|
180
|
+
# Introspection helpers
|
|
181
|
+
# ---------------------------------------------------------------------------
|
|
182
|
+
|
|
183
|
+
def iscoroutine(obj):
|
|
184
|
+
"""Return True if obj is a coroutine/Promise (has a .then method)."""
|
|
185
|
+
v"""return obj !== null && obj !== undefined && typeof obj === 'object' && typeof obj.then === 'function';"""
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
def iscoroutinefunction(fn):
|
|
189
|
+
"""Return True if fn is an async function."""
|
|
190
|
+
v"""return typeof fn === 'function' && fn.constructor && fn.constructor.name === 'AsyncFunction';"""
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
def current_task():
|
|
194
|
+
"""Return the currently running Task, or None.
|
|
195
|
+
|
|
196
|
+
Always returns None in the JS implementation (no task tracking).
|
|
197
|
+
"""
|
|
198
|
+
return None
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
def all_tasks():
|
|
202
|
+
"""Return all running Tasks.
|
|
203
|
+
|
|
204
|
+
Always returns an empty set in the JS implementation.
|
|
205
|
+
"""
|
|
206
|
+
return set()
|
|
207
|
+
|
|
208
|
+
|
|
209
|
+
# ---------------------------------------------------------------------------
|
|
210
|
+
# Event loop stubs (API-compatibility shims)
|
|
211
|
+
# ---------------------------------------------------------------------------
|
|
212
|
+
|
|
213
|
+
class AbstractEventLoop:
|
|
214
|
+
"""Minimal event-loop shim for API compatibility.
|
|
215
|
+
|
|
216
|
+
In JS there is always exactly one event loop; these methods are either
|
|
217
|
+
no-ops or thin wrappers around the equivalent JS mechanisms.
|
|
218
|
+
"""
|
|
219
|
+
def run_until_complete(self, coro):
|
|
220
|
+
"""Start executing `coro` and return it (cannot block in JS)."""
|
|
221
|
+
return coro
|
|
222
|
+
|
|
223
|
+
def run_forever(self):
|
|
224
|
+
pass
|
|
225
|
+
|
|
226
|
+
def stop(self):
|
|
227
|
+
pass
|
|
228
|
+
|
|
229
|
+
def close(self):
|
|
230
|
+
pass
|
|
231
|
+
|
|
232
|
+
def is_closed(self):
|
|
233
|
+
return False
|
|
234
|
+
|
|
235
|
+
def is_running(self):
|
|
236
|
+
return True
|
|
237
|
+
|
|
238
|
+
def create_task(self, coro):
|
|
239
|
+
return coro
|
|
240
|
+
|
|
241
|
+
def call_soon(self, callback, *args):
|
|
242
|
+
v"""setTimeout(function() { callback.apply(null, args); }, 0);"""
|
|
243
|
+
|
|
244
|
+
def call_later(self, delay, callback, *args):
|
|
245
|
+
v"""setTimeout(function() { callback.apply(null, args); }, (delay || 0) * 1000);"""
|
|
246
|
+
|
|
247
|
+
def call_soon_threadsafe(self, callback, *args):
|
|
248
|
+
v"""setTimeout(function() { callback.apply(null, args); }, 0);"""
|
|
249
|
+
|
|
250
|
+
|
|
251
|
+
class _EventLoop(AbstractEventLoop):
|
|
252
|
+
pass
|
|
253
|
+
|
|
254
|
+
|
|
255
|
+
_the_loop = _EventLoop()
|
|
256
|
+
|
|
257
|
+
|
|
258
|
+
def get_event_loop():
|
|
259
|
+
"""Return the running event loop."""
|
|
260
|
+
return _the_loop
|
|
261
|
+
|
|
262
|
+
|
|
263
|
+
def get_running_loop():
|
|
264
|
+
"""Return the running event loop (same as get_event_loop() in JS)."""
|
|
265
|
+
return _the_loop
|
|
266
|
+
|
|
267
|
+
|
|
268
|
+
def new_event_loop():
|
|
269
|
+
"""Create and return a new event loop object."""
|
|
270
|
+
return _EventLoop()
|
|
271
|
+
|
|
272
|
+
|
|
273
|
+
# ---------------------------------------------------------------------------
|
|
274
|
+
# Synchronization primitives
|
|
275
|
+
# ---------------------------------------------------------------------------
|
|
276
|
+
|
|
277
|
+
class Lock:
|
|
278
|
+
"""Mutual-exclusion lock.
|
|
279
|
+
|
|
280
|
+
Usage (since async with is not supported):
|
|
281
|
+
lock = asyncio.Lock()
|
|
282
|
+
await lock.acquire()
|
|
283
|
+
try:
|
|
284
|
+
...critical section...
|
|
285
|
+
finally:
|
|
286
|
+
lock.release()
|
|
287
|
+
"""
|
|
288
|
+
def __init__(self):
|
|
289
|
+
self._locked = False
|
|
290
|
+
self._waiters = []
|
|
291
|
+
|
|
292
|
+
async def acquire(self):
|
|
293
|
+
"""Acquire the lock, waiting if necessary."""
|
|
294
|
+
if not self._locked:
|
|
295
|
+
self._locked = True
|
|
296
|
+
return True
|
|
297
|
+
_self = self
|
|
298
|
+
v"""await new Promise(function(resolve) { _self._waiters.push(resolve); });"""
|
|
299
|
+
return True
|
|
300
|
+
|
|
301
|
+
def release(self):
|
|
302
|
+
"""Release the lock."""
|
|
303
|
+
if not self._locked:
|
|
304
|
+
raise RuntimeError("Lock is not acquired")
|
|
305
|
+
if self._waiters.length > 0:
|
|
306
|
+
waiter = self._waiters.shift()
|
|
307
|
+
waiter()
|
|
308
|
+
else:
|
|
309
|
+
self._locked = False
|
|
310
|
+
|
|
311
|
+
def locked(self):
|
|
312
|
+
"""Return True if the lock is currently held."""
|
|
313
|
+
return self._locked
|
|
314
|
+
|
|
315
|
+
|
|
316
|
+
class Event:
|
|
317
|
+
"""Async event flag that coroutines can wait on.
|
|
318
|
+
|
|
319
|
+
Usage:
|
|
320
|
+
event = asyncio.Event()
|
|
321
|
+
# In one coroutine:
|
|
322
|
+
await event.wait()
|
|
323
|
+
# In another:
|
|
324
|
+
event.set()
|
|
325
|
+
"""
|
|
326
|
+
def __init__(self):
|
|
327
|
+
self._is_set = False
|
|
328
|
+
self._waiters = []
|
|
329
|
+
|
|
330
|
+
def set(self):
|
|
331
|
+
"""Set the event, releasing all waiting coroutines."""
|
|
332
|
+
self._is_set = True
|
|
333
|
+
for waiter in self._waiters:
|
|
334
|
+
waiter()
|
|
335
|
+
self._waiters = []
|
|
336
|
+
|
|
337
|
+
def clear(self):
|
|
338
|
+
"""Reset the event to unset."""
|
|
339
|
+
self._is_set = False
|
|
340
|
+
|
|
341
|
+
def is_set(self):
|
|
342
|
+
"""Return True if the event is set."""
|
|
343
|
+
return self._is_set
|
|
344
|
+
|
|
345
|
+
async def wait(self):
|
|
346
|
+
"""Wait until the event is set, then return True."""
|
|
347
|
+
if self._is_set:
|
|
348
|
+
return True
|
|
349
|
+
_self = self
|
|
350
|
+
v"""await new Promise(function(resolve) { _self._waiters.push(resolve); });"""
|
|
351
|
+
return True
|
|
352
|
+
|
|
353
|
+
|
|
354
|
+
class Semaphore:
|
|
355
|
+
"""Counting semaphore for limiting concurrent access.
|
|
356
|
+
|
|
357
|
+
Usage:
|
|
358
|
+
sem = asyncio.Semaphore(3)
|
|
359
|
+
await sem.acquire()
|
|
360
|
+
try:
|
|
361
|
+
...
|
|
362
|
+
finally:
|
|
363
|
+
sem.release()
|
|
364
|
+
"""
|
|
365
|
+
def __init__(self, value=1):
|
|
366
|
+
if value < 0:
|
|
367
|
+
raise ValueError("Semaphore initial value must be >= 0")
|
|
368
|
+
self._value = value
|
|
369
|
+
self._waiters = []
|
|
370
|
+
|
|
371
|
+
async def acquire(self):
|
|
372
|
+
"""Acquire one permit, waiting if the count is zero."""
|
|
373
|
+
if self._value > 0:
|
|
374
|
+
self._value -= 1
|
|
375
|
+
return True
|
|
376
|
+
_self = self
|
|
377
|
+
v"""await new Promise(function(resolve) { _self._waiters.push(resolve); });"""
|
|
378
|
+
return True
|
|
379
|
+
|
|
380
|
+
def release(self):
|
|
381
|
+
"""Release one permit, waking a waiting coroutine if any."""
|
|
382
|
+
if self._waiters.length > 0:
|
|
383
|
+
waiter = self._waiters.shift()
|
|
384
|
+
waiter()
|
|
385
|
+
else:
|
|
386
|
+
self._value += 1
|
|
387
|
+
|
|
388
|
+
def locked(self):
|
|
389
|
+
"""Return True if the semaphore cannot be acquired without waiting."""
|
|
390
|
+
return self._value == 0
|
|
391
|
+
|
|
392
|
+
|
|
393
|
+
class BoundedSemaphore(Semaphore):
|
|
394
|
+
"""Semaphore that raises ValueError if released more times than acquired."""
|
|
395
|
+
def __init__(self, value=1):
|
|
396
|
+
Semaphore.__init__(self, value)
|
|
397
|
+
self._bound_value = value
|
|
398
|
+
|
|
399
|
+
def release(self):
|
|
400
|
+
if self._waiters.length == 0 and self._value >= self._bound_value:
|
|
401
|
+
raise ValueError("BoundedSemaphore released too many times")
|
|
402
|
+
Semaphore.release(self)
|
|
403
|
+
|
|
404
|
+
|
|
405
|
+
# ---------------------------------------------------------------------------
|
|
406
|
+
# Async queues
|
|
407
|
+
# ---------------------------------------------------------------------------
|
|
408
|
+
|
|
409
|
+
class Queue:
|
|
410
|
+
"""First-in, first-out async queue.
|
|
411
|
+
|
|
412
|
+
Usage:
|
|
413
|
+
q = asyncio.Queue()
|
|
414
|
+
await q.put(item)
|
|
415
|
+
item = await q.get()
|
|
416
|
+
q.task_done()
|
|
417
|
+
await q.join() # wait until all items are processed
|
|
418
|
+
"""
|
|
419
|
+
def __init__(self, maxsize=0):
|
|
420
|
+
self._maxsize = maxsize
|
|
421
|
+
self._queue = []
|
|
422
|
+
self._getters = []
|
|
423
|
+
self._putters = []
|
|
424
|
+
self._unfinished_tasks = 0
|
|
425
|
+
self._join_waiters = []
|
|
426
|
+
|
|
427
|
+
def qsize(self):
|
|
428
|
+
"""Return the number of items currently in the queue."""
|
|
429
|
+
return self._queue.length
|
|
430
|
+
|
|
431
|
+
def empty(self):
|
|
432
|
+
"""Return True if the queue has no items."""
|
|
433
|
+
return self._queue.length == 0
|
|
434
|
+
|
|
435
|
+
def full(self):
|
|
436
|
+
"""Return True if the queue is at maxsize (always False if maxsize=0)."""
|
|
437
|
+
if self._maxsize <= 0:
|
|
438
|
+
return False
|
|
439
|
+
return self._queue.length >= self._maxsize
|
|
440
|
+
|
|
441
|
+
async def put(self, item):
|
|
442
|
+
"""Put an item into the queue, waiting if the queue is full."""
|
|
443
|
+
if self.full():
|
|
444
|
+
_self = self
|
|
445
|
+
_item = item
|
|
446
|
+
v"""await new Promise(function(resolve) { _self._putters.push({resolve: resolve, item: _item}); });"""
|
|
447
|
+
else:
|
|
448
|
+
self._put_nowait_internal(item)
|
|
449
|
+
self._unfinished_tasks += 1
|
|
450
|
+
|
|
451
|
+
def put_nowait(self, item):
|
|
452
|
+
"""Put an item without waiting; raise QueueFull if the queue is full."""
|
|
453
|
+
if self.full():
|
|
454
|
+
raise QueueFull("Queue is full")
|
|
455
|
+
self._put_nowait_internal(item)
|
|
456
|
+
self._unfinished_tasks += 1
|
|
457
|
+
|
|
458
|
+
def _put_nowait_internal(self, item):
|
|
459
|
+
if self._getters.length > 0:
|
|
460
|
+
getter = self._getters.shift()
|
|
461
|
+
getter(item)
|
|
462
|
+
else:
|
|
463
|
+
self._queue.push(item)
|
|
464
|
+
|
|
465
|
+
async def get(self):
|
|
466
|
+
"""Remove and return an item, waiting if the queue is empty."""
|
|
467
|
+
if self._queue.length > 0:
|
|
468
|
+
return self._get_nowait_internal()
|
|
469
|
+
_self = self
|
|
470
|
+
v"""return await new Promise(function(resolve) { _self._getters.push(resolve); });"""
|
|
471
|
+
|
|
472
|
+
def get_nowait(self):
|
|
473
|
+
"""Remove and return an item; raise QueueEmpty if the queue is empty."""
|
|
474
|
+
if self.empty():
|
|
475
|
+
raise QueueEmpty("Queue is empty")
|
|
476
|
+
return self._get_nowait_internal()
|
|
477
|
+
|
|
478
|
+
def _get_nowait_internal(self):
|
|
479
|
+
item = self._queue.shift()
|
|
480
|
+
if self._putters.length > 0:
|
|
481
|
+
putter = self._putters.shift()
|
|
482
|
+
self._queue.push(putter.item)
|
|
483
|
+
putter.resolve()
|
|
484
|
+
return item
|
|
485
|
+
|
|
486
|
+
def task_done(self):
|
|
487
|
+
"""Mark a formerly enqueued item as processed.
|
|
488
|
+
|
|
489
|
+
Raises ValueError if called more times than there have been puts.
|
|
490
|
+
"""
|
|
491
|
+
if self._unfinished_tasks <= 0:
|
|
492
|
+
raise ValueError("task_done() called too many times")
|
|
493
|
+
self._unfinished_tasks -= 1
|
|
494
|
+
if self._unfinished_tasks == 0:
|
|
495
|
+
for waiter in self._join_waiters:
|
|
496
|
+
waiter()
|
|
497
|
+
self._join_waiters = []
|
|
498
|
+
|
|
499
|
+
async def join(self):
|
|
500
|
+
"""Block until all items which have been put into the queue are processed."""
|
|
501
|
+
if self._unfinished_tasks > 0:
|
|
502
|
+
_self = self
|
|
503
|
+
v"""await new Promise(function(resolve) { _self._join_waiters.push(resolve); });"""
|
|
504
|
+
|
|
505
|
+
|
|
506
|
+
class LifoQueue(Queue):
|
|
507
|
+
"""Last-in, first-out variant of Queue."""
|
|
508
|
+
def _get_nowait_internal(self):
|
|
509
|
+
item = self._queue.pop()
|
|
510
|
+
if self._putters.length > 0:
|
|
511
|
+
putter = self._putters.shift()
|
|
512
|
+
self._queue.push(putter.item)
|
|
513
|
+
putter.resolve()
|
|
514
|
+
return item
|
|
515
|
+
|
|
516
|
+
|
|
517
|
+
class PriorityQueue(Queue):
|
|
518
|
+
"""Priority queue where the smallest item is retrieved first."""
|
|
519
|
+
def _put_nowait_internal(self, item):
|
|
520
|
+
if self._getters.length > 0:
|
|
521
|
+
getter = self._getters.shift()
|
|
522
|
+
getter(item)
|
|
523
|
+
else:
|
|
524
|
+
self._queue.push(item)
|
|
525
|
+
self._queue.sort()
|
|
526
|
+
|
|
527
|
+
def _get_nowait_internal(self):
|
|
528
|
+
item = self._queue.shift()
|
|
529
|
+
if self._putters.length > 0:
|
|
530
|
+
putter = self._putters.shift()
|
|
531
|
+
self._queue.push(putter.item)
|
|
532
|
+
self._queue.sort()
|
|
533
|
+
putter.resolve()
|
|
534
|
+
return item
|