rapydscript-ns 0.9.0 → 0.9.1
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 +8 -0
- package/README.md +6 -5
- package/TODO.md +1 -3
- package/language-service/index.js +4 -4
- package/package.json +1 -1
- package/release/compiler.js +2 -2
- package/release/signatures.json +3 -3
- package/src/lib/contextlib.pyj +379 -0
- package/src/lib/datetime.pyj +712 -0
- package/src/lib/io.pyj +500 -0
- package/src/lib/json.pyj +227 -0
- package/src/monaco-language-service/diagnostics.js +2 -2
- package/src/tokenizer.pyj +1 -1
- package/test/contextlib.pyj +362 -0
- package/test/datetime.pyj +500 -0
- package/test/debugger_stmt.pyj +41 -0
- package/test/io.pyj +316 -0
- package/test/json.pyj +196 -0
- package/test/unit/web-repl.js +533 -0
- package/web-repl/rapydscript.js +2 -2
package/package.json
CHANGED
package/release/compiler.js
CHANGED
|
@@ -15126,7 +15126,7 @@ return this.__repr__();
|
|
|
15126
15126
|
WHITESPACE_CHARS = make_predicate(characters(" \n\r\t\f\u000b \u202f "));
|
|
15127
15127
|
PUNC_BEFORE_EXPRESSION = make_predicate(characters("[{(,.;:"));
|
|
15128
15128
|
PUNC_CHARS = make_predicate(characters("[]{}(),;:?"));
|
|
15129
|
-
KEYWORDS = "as assert async await break class continue def del do elif else except finally for from global if import in is lambda new nonlocal pass raise return yield try while with or and not";
|
|
15129
|
+
KEYWORDS = "as assert async await break class continue debugger def del do elif else except finally for from global if import in is lambda new nonlocal pass raise return yield try while with or and not";
|
|
15130
15130
|
KEYWORDS_ATOM = "False None True";
|
|
15131
15131
|
RESERVED_WORDS = "break case class catch const continue debugger default delete do else export extends finally for function if import in instanceof new return switch this throw try typeof var void while with yield implements static private package let public protected interface await null true false";
|
|
15132
15132
|
KEYWORDS_BEFORE_EXPRESSION = "return yield new del raise elif else if";
|
|
@@ -16244,7 +16244,7 @@ return this.__repr__();
|
|
|
16244
16244
|
var is_token = ρσ_modules.tokenizer.is_token;
|
|
16245
16245
|
var RESERVED_WORDS = ρσ_modules.tokenizer.RESERVED_WORDS;
|
|
16246
16246
|
|
|
16247
|
-
COMPILER_VERSION = "
|
|
16247
|
+
COMPILER_VERSION = "146ab479438eea3efe2870440ee9a4ef2bdd4319";
|
|
16248
16248
|
PYTHON_FLAGS = (function(){
|
|
16249
16249
|
var ρσ_d = Object.create(null);
|
|
16250
16250
|
ρσ_d["dict_literals"] = true;
|
package/release/signatures.json
CHANGED
|
@@ -26,9 +26,9 @@
|
|
|
26
26
|
"output/utils": "595968f96f6fdcc51eb41c34d64c92bb595e3cb1",
|
|
27
27
|
"parse": "0643834ed3c98d350ceb9ec71179f8923974c08c",
|
|
28
28
|
"string_interpolation": "bff1cc76d772d24d35707f6c794f38734ca08376",
|
|
29
|
-
"tokenizer": "
|
|
29
|
+
"tokenizer": "79cf9d42ec2613b409b4dc6ed0e3ce112e4bd8c0",
|
|
30
30
|
"unicode_aliases": "79ac6eaa5e6be44a5397d62c561f854a8fe7528e",
|
|
31
31
|
"utils": "c1666db819aa7c8db38697e34e18362e3cb45869",
|
|
32
|
-
"#compiler#": "
|
|
33
|
-
"#compiled_with#": "
|
|
32
|
+
"#compiler#": "fb53a74e155394a3b3834df62d3bbb2778d92ea7",
|
|
33
|
+
"#compiled_with#": "fb53a74e155394a3b3834df62d3bbb2778d92ea7"
|
|
34
34
|
}
|
|
@@ -0,0 +1,379 @@
|
|
|
1
|
+
# vim:fileencoding=utf-8
|
|
2
|
+
# License: BSD
|
|
3
|
+
# RapydScript implementation of Python's contextlib standard library.
|
|
4
|
+
#
|
|
5
|
+
# Supported:
|
|
6
|
+
# AbstractContextManager — base class with default __enter__ (returns self)
|
|
7
|
+
# @contextmanager — turn a generator function into a context manager
|
|
8
|
+
# closing(thing) — calls thing.close() on exit
|
|
9
|
+
# nullcontext(val) — no-op context manager; __enter__ returns val
|
|
10
|
+
# suppress(*excs) — silently swallow specified exception types
|
|
11
|
+
# ExitStack — dynamic LIFO stack of context managers / callbacks
|
|
12
|
+
#
|
|
13
|
+
# Usage:
|
|
14
|
+
# from contextlib import contextmanager, suppress, closing, nullcontext, ExitStack
|
|
15
|
+
#
|
|
16
|
+
# @contextmanager
|
|
17
|
+
# def managed(name):
|
|
18
|
+
# print('enter', name)
|
|
19
|
+
# try:
|
|
20
|
+
# yield name.upper()
|
|
21
|
+
# finally:
|
|
22
|
+
# print('exit', name)
|
|
23
|
+
#
|
|
24
|
+
# with managed('hello') as val:
|
|
25
|
+
# print(val) # HELLO
|
|
26
|
+
# # prints: enter hello / HELLO / exit hello
|
|
27
|
+
#
|
|
28
|
+
# with suppress(ValueError):
|
|
29
|
+
# int('not-a-number')
|
|
30
|
+
# # no exception raised
|
|
31
|
+
#
|
|
32
|
+
# stack = ExitStack()
|
|
33
|
+
# with stack:
|
|
34
|
+
# f = stack.enter_context(some_cm())
|
|
35
|
+
#
|
|
36
|
+
# Implementation notes:
|
|
37
|
+
# - contextmanager uses the JS generator protocol (.next() / .throw()).
|
|
38
|
+
# Since 'throw' is a reserved JS keyword it cannot appear as a bare
|
|
39
|
+
# identifier in RapydScript method-call syntax; the call is made via a
|
|
40
|
+
# verbatim v"""...""" block.
|
|
41
|
+
# - The with-statement machinery in RapydScript calls __exit__() (0 args)
|
|
42
|
+
# when no exception occurred and __exit__(exc_type, exc_val, exc_tb)
|
|
43
|
+
# (3 args) when one did. All __exit__ implementations here use default
|
|
44
|
+
# parameters (=None) so both signatures work transparently.
|
|
45
|
+
# - ExitStack.__exit__ may raise a new exception that replaces the original;
|
|
46
|
+
# the with-statement machinery propagates whatever __exit__ throws.
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
# RuntimeError is not defined in the RapydScript baselib; define it here so
|
|
50
|
+
# that the contextmanager helpers can raise it for protocol violations.
|
|
51
|
+
class RuntimeError(Exception):
|
|
52
|
+
pass
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
class AbstractContextManager:
|
|
56
|
+
"""
|
|
57
|
+
ABC for context managers that provides a default __enter__ returning self.
|
|
58
|
+
|
|
59
|
+
Subclasses must override __exit__. A default no-op __exit__ is also
|
|
60
|
+
provided so that plain subclasses work without override if no cleanup is
|
|
61
|
+
needed.
|
|
62
|
+
|
|
63
|
+
Example::
|
|
64
|
+
|
|
65
|
+
class Timed(AbstractContextManager):
|
|
66
|
+
def __enter__(self):
|
|
67
|
+
self._start = Date.now()
|
|
68
|
+
return self
|
|
69
|
+
def __exit__(self, exc_type=None, exc_val=None, exc_tb=None):
|
|
70
|
+
print('elapsed:', Date.now() - self._start, 'ms')
|
|
71
|
+
return False
|
|
72
|
+
"""
|
|
73
|
+
|
|
74
|
+
def __enter__(self):
|
|
75
|
+
return self
|
|
76
|
+
|
|
77
|
+
def __exit__(self, exc_type=None, exc_val=None, exc_tb=None):
|
|
78
|
+
return None
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
class closing:
|
|
82
|
+
"""
|
|
83
|
+
Context manager that calls thing.close() when the block exits.
|
|
84
|
+
|
|
85
|
+
Equivalent to Python's contextlib.closing.
|
|
86
|
+
|
|
87
|
+
Example::
|
|
88
|
+
|
|
89
|
+
from contextlib import closing
|
|
90
|
+
|
|
91
|
+
with closing(open_connection()) as conn:
|
|
92
|
+
conn.send(data)
|
|
93
|
+
# conn.close() is guaranteed to be called
|
|
94
|
+
"""
|
|
95
|
+
|
|
96
|
+
def __init__(self, thing):
|
|
97
|
+
self.thing = thing
|
|
98
|
+
|
|
99
|
+
def __enter__(self):
|
|
100
|
+
return self.thing
|
|
101
|
+
|
|
102
|
+
def __exit__(self, exc_type=None, exc_val=None, exc_tb=None):
|
|
103
|
+
self.thing.close()
|
|
104
|
+
return False
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
class nullcontext:
|
|
108
|
+
"""
|
|
109
|
+
No-op context manager. __enter__ returns enter_result (default None).
|
|
110
|
+
|
|
111
|
+
Useful as a conditional stand-in when you optionally want a real context
|
|
112
|
+
manager::
|
|
113
|
+
|
|
114
|
+
cm = open_lock() if need_lock else nullcontext()
|
|
115
|
+
with cm:
|
|
116
|
+
do_work()
|
|
117
|
+
|
|
118
|
+
Also handy for parameterised tests::
|
|
119
|
+
|
|
120
|
+
with nullcontext(42) as val:
|
|
121
|
+
assert val == 42
|
|
122
|
+
"""
|
|
123
|
+
|
|
124
|
+
def __init__(self, enter_result=None):
|
|
125
|
+
self.enter_result = enter_result
|
|
126
|
+
|
|
127
|
+
def __enter__(self):
|
|
128
|
+
return self.enter_result
|
|
129
|
+
|
|
130
|
+
def __exit__(self, exc_type=None, exc_val=None, exc_tb=None):
|
|
131
|
+
return None
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
class suppress:
|
|
135
|
+
"""
|
|
136
|
+
Context manager that silently suppresses the listed exception types.
|
|
137
|
+
|
|
138
|
+
If a listed exception is raised inside the block the block is exited
|
|
139
|
+
and execution continues after the with statement. Any other exception
|
|
140
|
+
type propagates normally.
|
|
141
|
+
|
|
142
|
+
Example::
|
|
143
|
+
|
|
144
|
+
from contextlib import suppress
|
|
145
|
+
|
|
146
|
+
with suppress(KeyError, ValueError):
|
|
147
|
+
d = {}
|
|
148
|
+
_ = d['missing'] # KeyError suppressed
|
|
149
|
+
# execution continues here
|
|
150
|
+
"""
|
|
151
|
+
|
|
152
|
+
def __init__(self, *exceptions):
|
|
153
|
+
self._exceptions = exceptions
|
|
154
|
+
|
|
155
|
+
def __enter__(self):
|
|
156
|
+
return self
|
|
157
|
+
|
|
158
|
+
def __exit__(self, exc_type=None, exc_val=None, exc_tb=None):
|
|
159
|
+
if exc_type is None:
|
|
160
|
+
return False
|
|
161
|
+
for exc_class in self._exceptions:
|
|
162
|
+
if isinstance(exc_val, exc_class):
|
|
163
|
+
return True
|
|
164
|
+
return False
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
def contextmanager(func):
|
|
168
|
+
"""
|
|
169
|
+
Decorator that turns a generator function into a context manager.
|
|
170
|
+
|
|
171
|
+
The decorated function must contain exactly one ``yield`` expression.
|
|
172
|
+
Everything before the yield is the __enter__ body; everything after is
|
|
173
|
+
the __exit__ body. The yielded value is bound to the ``as`` target.
|
|
174
|
+
|
|
175
|
+
Exception handling works as in Python: if an exception is raised inside
|
|
176
|
+
the with block it is thrown into the generator at the yield point. The
|
|
177
|
+
generator may catch and suppress it (by not re-raising) or let it
|
|
178
|
+
propagate.
|
|
179
|
+
|
|
180
|
+
Example::
|
|
181
|
+
|
|
182
|
+
from contextlib import contextmanager
|
|
183
|
+
|
|
184
|
+
@contextmanager
|
|
185
|
+
def temp_value(d, key, val):
|
|
186
|
+
old = d.get(key)
|
|
187
|
+
d[key] = val
|
|
188
|
+
try:
|
|
189
|
+
yield val
|
|
190
|
+
finally:
|
|
191
|
+
if old is None:
|
|
192
|
+
del d[key]
|
|
193
|
+
else:
|
|
194
|
+
d[key] = old
|
|
195
|
+
|
|
196
|
+
d = {}
|
|
197
|
+
with temp_value(d, 'x', 99) as v:
|
|
198
|
+
assert v == 99
|
|
199
|
+
assert d['x'] == 99
|
|
200
|
+
assert 'x' not in d
|
|
201
|
+
"""
|
|
202
|
+
|
|
203
|
+
def _make_cm(*args, **kwargs):
|
|
204
|
+
gen = func(*args, **kwargs)
|
|
205
|
+
|
|
206
|
+
class _GeneratorContextManager:
|
|
207
|
+
|
|
208
|
+
def __enter__(self):
|
|
209
|
+
r = gen.next()
|
|
210
|
+
if r.done:
|
|
211
|
+
raise RuntimeError('generator did not yield')
|
|
212
|
+
return r.value
|
|
213
|
+
|
|
214
|
+
def __exit__(self, exc_type=None, exc_val=None, exc_tb=None):
|
|
215
|
+
if exc_type is None:
|
|
216
|
+
# No-exception path: advance the generator to completion.
|
|
217
|
+
r = gen.next()
|
|
218
|
+
if not r.done:
|
|
219
|
+
raise RuntimeError('generator did not stop after yield')
|
|
220
|
+
return False
|
|
221
|
+
# Exception path: throw exc_val into the generator.
|
|
222
|
+
# 'throw' is a reserved JS keyword so we use verbatim JS.
|
|
223
|
+
v"""
|
|
224
|
+
var ρσ_cm_result;
|
|
225
|
+
try {
|
|
226
|
+
ρσ_cm_result = gen.throw(exc_val);
|
|
227
|
+
} catch (ρσ_cm_err) {
|
|
228
|
+
// Generator did not catch the exception (re-raised or threw a
|
|
229
|
+
// different one). If it's the same object, return false so
|
|
230
|
+
// the with-machinery re-raises it. Otherwise let the new
|
|
231
|
+
// exception propagate from __exit__.
|
|
232
|
+
if (ρσ_cm_err === exc_val) {
|
|
233
|
+
return false;
|
|
234
|
+
}
|
|
235
|
+
throw ρσ_cm_err;
|
|
236
|
+
}
|
|
237
|
+
// Generator caught the exception and returned normally.
|
|
238
|
+
if (!ρσ_cm_result.done) {
|
|
239
|
+
throw new RuntimeError('generator did not stop after throw()');
|
|
240
|
+
}
|
|
241
|
+
return true;
|
|
242
|
+
"""
|
|
243
|
+
|
|
244
|
+
return _GeneratorContextManager()
|
|
245
|
+
|
|
246
|
+
return _make_cm
|
|
247
|
+
|
|
248
|
+
|
|
249
|
+
class ExitStack:
|
|
250
|
+
"""
|
|
251
|
+
Context manager for dynamic stacks of context managers and callbacks.
|
|
252
|
+
|
|
253
|
+
Maintains a LIFO stack of registered cleanup actions. All registered
|
|
254
|
+
actions are guaranteed to run on exit, even if earlier ones raise.
|
|
255
|
+
|
|
256
|
+
Key methods:
|
|
257
|
+
enter_context(cm) — enter *cm* and push its __exit__ for cleanup
|
|
258
|
+
push(exit_cb) — push a raw (exc_type, exc_val, exc_tb) callback
|
|
259
|
+
or a context manager (its __exit__ is pushed)
|
|
260
|
+
callback(func, *a, **kw) — push func(*a, **kw) as a no-exc callback
|
|
261
|
+
close() — trigger exit immediately (convenience)
|
|
262
|
+
|
|
263
|
+
Example::
|
|
264
|
+
|
|
265
|
+
from contextlib import ExitStack
|
|
266
|
+
|
|
267
|
+
with ExitStack() as stack:
|
|
268
|
+
files = [stack.enter_context(open_file(name)) for name in names]
|
|
269
|
+
# all files closed on exit, even if some raises
|
|
270
|
+
|
|
271
|
+
# Manually-built stack:
|
|
272
|
+
stack = ExitStack()
|
|
273
|
+
conn = stack.enter_context(get_connection())
|
|
274
|
+
stack.callback(log, 'connection cleaned up')
|
|
275
|
+
try:
|
|
276
|
+
use(conn)
|
|
277
|
+
finally:
|
|
278
|
+
stack.close()
|
|
279
|
+
"""
|
|
280
|
+
|
|
281
|
+
def __init__(self):
|
|
282
|
+
self._exit_callbacks = []
|
|
283
|
+
|
|
284
|
+
def __enter__(self):
|
|
285
|
+
return self
|
|
286
|
+
|
|
287
|
+
def push(self, exit_or_cm):
|
|
288
|
+
"""
|
|
289
|
+
Register an exit callback or a context manager.
|
|
290
|
+
|
|
291
|
+
If *exit_or_cm* has an ``__exit__`` attribute it is treated as a
|
|
292
|
+
context manager (its __exit__ is registered but __enter__ is NOT
|
|
293
|
+
called — use enter_context() if you need that). Otherwise it must be
|
|
294
|
+
a callable with the ``(exc_type, exc_val, exc_tb)`` signature.
|
|
295
|
+
|
|
296
|
+
Returns *exit_or_cm* unchanged, so it can be used as a decorator.
|
|
297
|
+
"""
|
|
298
|
+
if hasattr(exit_or_cm, '__exit__'):
|
|
299
|
+
_cm = exit_or_cm
|
|
300
|
+
def _cm_exit(exc_type=None, exc_val=None, exc_tb=None):
|
|
301
|
+
return _cm.__exit__(exc_type, exc_val, exc_tb)
|
|
302
|
+
self._exit_callbacks.append(_cm_exit)
|
|
303
|
+
else:
|
|
304
|
+
self._exit_callbacks.append(exit_or_cm)
|
|
305
|
+
return exit_or_cm
|
|
306
|
+
|
|
307
|
+
def enter_context(self, cm):
|
|
308
|
+
"""
|
|
309
|
+
Enter a context manager and push its __exit__ for cleanup.
|
|
310
|
+
|
|
311
|
+
Returns the value returned by cm.__enter__().
|
|
312
|
+
"""
|
|
313
|
+
result = cm.__enter__()
|
|
314
|
+
_cm2 = cm
|
|
315
|
+
def _cm2_exit(exc_type=None, exc_val=None, exc_tb=None):
|
|
316
|
+
return _cm2.__exit__(exc_type, exc_val, exc_tb)
|
|
317
|
+
self._exit_callbacks.append(_cm2_exit)
|
|
318
|
+
return result
|
|
319
|
+
|
|
320
|
+
def callback(self, func, *args, **kwargs):
|
|
321
|
+
"""
|
|
322
|
+
Register a plain callback to run on exit, ignoring exception info.
|
|
323
|
+
|
|
324
|
+
The callback is called as func(*args, **kwargs) and its return value
|
|
325
|
+
is ignored. Returns *func* unchanged.
|
|
326
|
+
"""
|
|
327
|
+
stored_args = args
|
|
328
|
+
stored_kwargs = kwargs
|
|
329
|
+
def _plain_cb(exc_type=None, exc_val=None, exc_tb=None):
|
|
330
|
+
func(*stored_args, **stored_kwargs)
|
|
331
|
+
return False
|
|
332
|
+
self._exit_callbacks.append(_plain_cb)
|
|
333
|
+
return func
|
|
334
|
+
|
|
335
|
+
def __exit__(self, exc_type=None, exc_val=None, exc_tb=None):
|
|
336
|
+
"""
|
|
337
|
+
Run all registered cleanups in LIFO order.
|
|
338
|
+
|
|
339
|
+
Returns True if an active exception was suppressed by any cleanup.
|
|
340
|
+
If a cleanup raises, that exception becomes the active exception for
|
|
341
|
+
subsequent cleanups; if it is still active at the end it propagates
|
|
342
|
+
from __exit__ (replacing the original).
|
|
343
|
+
"""
|
|
344
|
+
received_exc = exc_type is not None
|
|
345
|
+
suppressed = False
|
|
346
|
+
|
|
347
|
+
current_type = exc_type
|
|
348
|
+
current_val = exc_val
|
|
349
|
+
current_tb = exc_tb
|
|
350
|
+
|
|
351
|
+
new_exc = None
|
|
352
|
+
raised_new = False
|
|
353
|
+
|
|
354
|
+
while len(self._exit_callbacks) > 0:
|
|
355
|
+
cb = self._exit_callbacks.pop()
|
|
356
|
+
try:
|
|
357
|
+
result = cb(current_type, current_val, current_tb)
|
|
358
|
+
if result:
|
|
359
|
+
suppressed = True
|
|
360
|
+
current_type = None
|
|
361
|
+
current_val = None
|
|
362
|
+
current_tb = None
|
|
363
|
+
except Exception as e:
|
|
364
|
+
# Cleanup raised — this becomes the active exception.
|
|
365
|
+
new_exc = e
|
|
366
|
+
raised_new = True
|
|
367
|
+
current_type = e.__class__
|
|
368
|
+
current_val = e
|
|
369
|
+
current_tb = None
|
|
370
|
+
suppressed = False
|
|
371
|
+
|
|
372
|
+
if raised_new:
|
|
373
|
+
raise new_exc
|
|
374
|
+
|
|
375
|
+
return received_exc and suppressed
|
|
376
|
+
|
|
377
|
+
def close(self):
|
|
378
|
+
"""Exit the stack without an active exception."""
|
|
379
|
+
self.__exit__(None, None, None)
|