rapydscript-ns 0.8.4 → 0.9.0
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/.agignore +1 -1
- package/.github/workflows/ci.yml +38 -38
- package/=template.pyj +5 -5
- package/CHANGELOG.md +18 -0
- package/HACKING.md +103 -103
- package/LICENSE +24 -24
- package/README.md +715 -169
- package/TODO.md +9 -2
- package/add-toc-to-readme +2 -2
- package/bin/export +75 -75
- package/bin/rapydscript +70 -70
- package/bin/web-repl-export +102 -102
- package/build +2 -2
- package/language-service/index.js +36 -27
- package/package.json +1 -1
- package/publish.py +37 -37
- package/release/baselib-plain-pretty.js +2358 -168
- package/release/baselib-plain-ugly.js +73 -3
- package/release/compiler.js +6282 -3092
- package/release/signatures.json +31 -30
- package/session.vim +4 -4
- package/setup.cfg +2 -2
- package/src/ast.pyj +1 -0
- package/src/baselib-builtins.pyj +340 -2
- package/src/baselib-bytes.pyj +664 -0
- package/src/baselib-errors.pyj +1 -1
- package/src/baselib-internal.pyj +267 -60
- package/src/baselib-itertools.pyj +110 -97
- package/src/baselib-str.pyj +22 -4
- package/src/compiler.pyj +36 -36
- package/src/errors.pyj +30 -30
- package/src/lib/abc.pyj +317 -0
- package/src/lib/aes.pyj +646 -646
- package/src/lib/copy.pyj +120 -120
- package/src/lib/dataclasses.pyj +532 -0
- package/src/lib/elementmaker.pyj +83 -83
- package/src/lib/encodings.pyj +126 -126
- package/src/lib/enum.pyj +125 -0
- package/src/lib/gettext.pyj +569 -569
- package/src/lib/itertools.pyj +580 -580
- package/src/lib/math.pyj +193 -193
- package/src/lib/operator.pyj +11 -11
- package/src/lib/pythonize.pyj +20 -20
- package/src/lib/random.pyj +118 -118
- package/src/lib/re.pyj +504 -470
- package/src/lib/react.pyj +74 -74
- package/src/lib/traceback.pyj +63 -63
- package/src/lib/typing.pyj +577 -0
- package/src/lib/uuid.pyj +77 -77
- package/src/monaco-language-service/builtins.js +14 -4
- package/src/monaco-language-service/diagnostics.js +19 -20
- package/src/monaco-language-service/dts.js +550 -550
- package/src/output/classes.pyj +62 -26
- package/src/output/comments.pyj +45 -45
- package/src/output/exceptions.pyj +201 -201
- package/src/output/functions.pyj +78 -5
- package/src/output/jsx.pyj +164 -164
- package/src/output/loops.pyj +5 -2
- package/src/output/operators.pyj +100 -34
- package/src/output/treeshake.pyj +182 -182
- package/src/output/utils.pyj +72 -72
- package/src/parse.pyj +80 -16
- package/src/string_interpolation.pyj +72 -72
- package/src/tokenizer.pyj +9 -4
- package/src/unicode_aliases.pyj +576 -576
- package/src/utils.pyj +192 -192
- package/test/_import_one.pyj +37 -37
- package/test/_import_two/__init__.pyj +11 -11
- package/test/_import_two/level2/deep.pyj +4 -4
- package/test/_import_two/other.pyj +6 -6
- package/test/_import_two/sub.pyj +13 -13
- package/test/abc.pyj +291 -0
- package/test/aes_vectors.pyj +421 -421
- package/test/annotations.pyj +80 -80
- package/test/arithmetic_nostrict.pyj +88 -0
- package/test/arithmetic_types.pyj +169 -0
- package/test/baselib.pyj +91 -0
- package/test/bytes.pyj +467 -0
- package/test/classes.pyj +1 -0
- package/test/comparison_ops.pyj +173 -0
- package/test/dataclasses.pyj +253 -0
- package/test/decorators.pyj +77 -77
- package/test/docstrings.pyj +39 -39
- package/test/elementmaker_test.pyj +45 -45
- package/test/enum.pyj +134 -0
- package/test/eval_exec.pyj +56 -0
- package/test/format.pyj +148 -0
- package/test/functions.pyj +151 -151
- package/test/generators.pyj +41 -41
- package/test/generic.pyj +370 -370
- package/test/imports.pyj +72 -72
- package/test/internationalization.pyj +73 -73
- package/test/lint.pyj +164 -164
- package/test/loops.pyj +85 -85
- package/test/numpy.pyj +734 -734
- package/test/object.pyj +64 -0
- package/test/omit_function_metadata.pyj +20 -20
- package/test/python_compat.pyj +17 -15
- package/test/python_features.pyj +70 -15
- package/test/regexp.pyj +83 -55
- package/test/repl.pyj +121 -121
- package/test/scoped_flags.pyj +76 -76
- package/test/tuples.pyj +96 -0
- package/test/typing.pyj +469 -0
- package/test/unit/index.js +116 -7
- package/test/unit/language-service-dts.js +543 -543
- package/test/unit/language-service-hover.js +455 -455
- package/test/unit/language-service.js +84 -0
- package/test/unit/web-repl.js +804 -1
- package/test/vars_locals_globals.pyj +94 -0
- package/tools/cli.js +558 -547
- package/tools/compile.js +224 -219
- package/tools/completer.js +131 -131
- package/tools/embedded_compiler.js +262 -251
- package/tools/gettext.js +185 -185
- package/tools/ini.js +65 -65
- package/tools/lint.js +16 -19
- package/tools/msgfmt.js +187 -187
- package/tools/repl.js +223 -223
- package/tools/test.js +118 -118
- package/tools/utils.js +128 -128
- package/tools/web_repl.js +95 -95
- package/try +41 -41
- package/web-repl/env.js +196 -196
- package/web-repl/index.html +163 -163
- package/web-repl/main.js +252 -252
- package/web-repl/prism.css +139 -139
- package/web-repl/prism.js +113 -113
- package/web-repl/rapydscript.js +224 -224
- package/web-repl/sha1.js +25 -25
- package/PYTHON_DIFFERENCES_REPORT.md +0 -291
- package/PYTHON_FEATURE_COVERAGE.md +0 -200
package/src/lib/elementmaker.pyj
CHANGED
|
@@ -1,83 +1,83 @@
|
|
|
1
|
-
# vim:fileencoding=utf-8
|
|
2
|
-
# License: GPL v3 Copyright: 2015, Kovid Goyal <kovid at kovidgoyal.net>
|
|
3
|
-
|
|
4
|
-
html_elements = {
|
|
5
|
-
'a', 'abbr', 'acronym', 'address', 'area',
|
|
6
|
-
'article', 'aside', 'audio', 'b', 'base', 'big', 'body', 'blockquote', 'br', 'button',
|
|
7
|
-
'canvas', 'caption', 'center', 'cite', 'code', 'col', 'colgroup',
|
|
8
|
-
'command', 'datagrid', 'datalist', 'dd', 'del', 'details', 'dfn',
|
|
9
|
-
'dialog', 'dir', 'div', 'dl', 'dt', 'em', 'event-source', 'fieldset',
|
|
10
|
-
'figcaption', 'figure', 'footer', 'font', 'form', 'header', 'h1',
|
|
11
|
-
'h2', 'h3', 'h4', 'h5', 'h6', 'hr', 'head', 'i', 'iframe', 'img', 'input', 'ins',
|
|
12
|
-
'keygen', 'kbd', 'label', 'legend', 'li', 'm', 'map', 'menu', 'meter',
|
|
13
|
-
'multicol', 'nav', 'nextid', 'ol', 'output', 'optgroup', 'option',
|
|
14
|
-
'p', 'pre', 'progress', 'q', 's', 'samp', 'script', 'section', 'select',
|
|
15
|
-
'small', 'sound', 'source', 'spacer', 'span', 'strike', 'strong', 'style',
|
|
16
|
-
'sub', 'sup', 'table', 'tbody', 'td', 'textarea', 'time', 'tfoot',
|
|
17
|
-
'th', 'thead', 'tr', 'tt', 'u', 'ul', 'var', 'video'
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
mathml_elements = {
|
|
21
|
-
'maction', 'math', 'merror', 'mfrac', 'mi',
|
|
22
|
-
'mmultiscripts', 'mn', 'mo', 'mover', 'mpadded', 'mphantom',
|
|
23
|
-
'mprescripts', 'mroot', 'mrow', 'mspace', 'msqrt', 'mstyle', 'msub',
|
|
24
|
-
'msubsup', 'msup', 'mtable', 'mtd', 'mtext', 'mtr', 'munder',
|
|
25
|
-
'munderover', 'none'
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
svg_elements = {
|
|
29
|
-
'a', 'animate', 'animateColor', 'animateMotion',
|
|
30
|
-
'animateTransform', 'clipPath', 'circle', 'defs', 'desc', 'ellipse',
|
|
31
|
-
'font-face', 'font-face-name', 'font-face-src', 'g', 'glyph', 'hkern',
|
|
32
|
-
'linearGradient', 'line', 'marker', 'metadata', 'missing-glyph',
|
|
33
|
-
'mpath', 'path', 'polygon', 'polyline', 'radialGradient', 'rect',
|
|
34
|
-
'set', 'stop', 'svg', 'switch', 'text', 'title', 'tspan', 'use'
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
html5_tags = html_elements.union(mathml_elements).union(svg_elements)
|
|
38
|
-
|
|
39
|
-
def _makeelement(tag, *args, **kwargs):
|
|
40
|
-
ans = this.createElement(tag)
|
|
41
|
-
|
|
42
|
-
for attr in kwargs:
|
|
43
|
-
vattr = str.replace(str.rstrip(attr, '_'), '_', '-')
|
|
44
|
-
val = kwargs[attr]
|
|
45
|
-
if callable(val):
|
|
46
|
-
if str.startswith(attr, 'on'):
|
|
47
|
-
attr = attr[2:]
|
|
48
|
-
ans.addEventListener(attr, val)
|
|
49
|
-
elif val is True:
|
|
50
|
-
ans.setAttribute(vattr, vattr)
|
|
51
|
-
elif jstype(val) is 'string':
|
|
52
|
-
ans.setAttribute(vattr, val)
|
|
53
|
-
|
|
54
|
-
for arg in args:
|
|
55
|
-
if jstype(arg) is 'string':
|
|
56
|
-
arg = this.createTextNode(arg)
|
|
57
|
-
ans.appendChild(arg)
|
|
58
|
-
return ans
|
|
59
|
-
|
|
60
|
-
def maker_for_document(document):
|
|
61
|
-
# Create an elementmaker to be used with the specified document
|
|
62
|
-
E = _makeelement.bind(document)
|
|
63
|
-
Object.defineProperties(E, {
|
|
64
|
-
tag: {
|
|
65
|
-
'value':_makeelement.bind(document, tag)
|
|
66
|
-
} for tag in html5_tags
|
|
67
|
-
})
|
|
68
|
-
return E
|
|
69
|
-
|
|
70
|
-
if jstype(document) is 'undefined':
|
|
71
|
-
E = maker_for_document({
|
|
72
|
-
'createTextNode': def(value): return value;,
|
|
73
|
-
'createElement': def(name):
|
|
74
|
-
return {
|
|
75
|
-
'name':name,
|
|
76
|
-
'children':[],
|
|
77
|
-
'attributes':{},
|
|
78
|
-
'setAttribute': def(name, val): this.attributes[name] = val;,
|
|
79
|
-
'appendChild': def(child): this.children.push(child);,
|
|
80
|
-
}
|
|
81
|
-
})
|
|
82
|
-
else:
|
|
83
|
-
E = maker_for_document(document)
|
|
1
|
+
# vim:fileencoding=utf-8
|
|
2
|
+
# License: GPL v3 Copyright: 2015, Kovid Goyal <kovid at kovidgoyal.net>
|
|
3
|
+
|
|
4
|
+
html_elements = {
|
|
5
|
+
'a', 'abbr', 'acronym', 'address', 'area',
|
|
6
|
+
'article', 'aside', 'audio', 'b', 'base', 'big', 'body', 'blockquote', 'br', 'button',
|
|
7
|
+
'canvas', 'caption', 'center', 'cite', 'code', 'col', 'colgroup',
|
|
8
|
+
'command', 'datagrid', 'datalist', 'dd', 'del', 'details', 'dfn',
|
|
9
|
+
'dialog', 'dir', 'div', 'dl', 'dt', 'em', 'event-source', 'fieldset',
|
|
10
|
+
'figcaption', 'figure', 'footer', 'font', 'form', 'header', 'h1',
|
|
11
|
+
'h2', 'h3', 'h4', 'h5', 'h6', 'hr', 'head', 'i', 'iframe', 'img', 'input', 'ins',
|
|
12
|
+
'keygen', 'kbd', 'label', 'legend', 'li', 'm', 'map', 'menu', 'meter',
|
|
13
|
+
'multicol', 'nav', 'nextid', 'ol', 'output', 'optgroup', 'option',
|
|
14
|
+
'p', 'pre', 'progress', 'q', 's', 'samp', 'script', 'section', 'select',
|
|
15
|
+
'small', 'sound', 'source', 'spacer', 'span', 'strike', 'strong', 'style',
|
|
16
|
+
'sub', 'sup', 'table', 'tbody', 'td', 'textarea', 'time', 'tfoot',
|
|
17
|
+
'th', 'thead', 'tr', 'tt', 'u', 'ul', 'var', 'video'
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
mathml_elements = {
|
|
21
|
+
'maction', 'math', 'merror', 'mfrac', 'mi',
|
|
22
|
+
'mmultiscripts', 'mn', 'mo', 'mover', 'mpadded', 'mphantom',
|
|
23
|
+
'mprescripts', 'mroot', 'mrow', 'mspace', 'msqrt', 'mstyle', 'msub',
|
|
24
|
+
'msubsup', 'msup', 'mtable', 'mtd', 'mtext', 'mtr', 'munder',
|
|
25
|
+
'munderover', 'none'
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
svg_elements = {
|
|
29
|
+
'a', 'animate', 'animateColor', 'animateMotion',
|
|
30
|
+
'animateTransform', 'clipPath', 'circle', 'defs', 'desc', 'ellipse',
|
|
31
|
+
'font-face', 'font-face-name', 'font-face-src', 'g', 'glyph', 'hkern',
|
|
32
|
+
'linearGradient', 'line', 'marker', 'metadata', 'missing-glyph',
|
|
33
|
+
'mpath', 'path', 'polygon', 'polyline', 'radialGradient', 'rect',
|
|
34
|
+
'set', 'stop', 'svg', 'switch', 'text', 'title', 'tspan', 'use'
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
html5_tags = html_elements.union(mathml_elements).union(svg_elements)
|
|
38
|
+
|
|
39
|
+
def _makeelement(tag, *args, **kwargs):
|
|
40
|
+
ans = this.createElement(tag)
|
|
41
|
+
|
|
42
|
+
for attr in kwargs:
|
|
43
|
+
vattr = str.replace(str.rstrip(attr, '_'), '_', '-')
|
|
44
|
+
val = kwargs[attr]
|
|
45
|
+
if callable(val):
|
|
46
|
+
if str.startswith(attr, 'on'):
|
|
47
|
+
attr = attr[2:]
|
|
48
|
+
ans.addEventListener(attr, val)
|
|
49
|
+
elif val is True:
|
|
50
|
+
ans.setAttribute(vattr, vattr)
|
|
51
|
+
elif jstype(val) is 'string':
|
|
52
|
+
ans.setAttribute(vattr, val)
|
|
53
|
+
|
|
54
|
+
for arg in args:
|
|
55
|
+
if jstype(arg) is 'string':
|
|
56
|
+
arg = this.createTextNode(arg)
|
|
57
|
+
ans.appendChild(arg)
|
|
58
|
+
return ans
|
|
59
|
+
|
|
60
|
+
def maker_for_document(document):
|
|
61
|
+
# Create an elementmaker to be used with the specified document
|
|
62
|
+
E = _makeelement.bind(document)
|
|
63
|
+
Object.defineProperties(E, {
|
|
64
|
+
tag: {
|
|
65
|
+
'value':_makeelement.bind(document, tag)
|
|
66
|
+
} for tag in html5_tags
|
|
67
|
+
})
|
|
68
|
+
return E
|
|
69
|
+
|
|
70
|
+
if jstype(document) is 'undefined':
|
|
71
|
+
E = maker_for_document({
|
|
72
|
+
'createTextNode': def(value): return value;,
|
|
73
|
+
'createElement': def(name):
|
|
74
|
+
return {
|
|
75
|
+
'name':name,
|
|
76
|
+
'children':[],
|
|
77
|
+
'attributes':{},
|
|
78
|
+
'setAttribute': def(name, val): this.attributes[name] = val;,
|
|
79
|
+
'appendChild': def(child): this.children.push(child);,
|
|
80
|
+
}
|
|
81
|
+
})
|
|
82
|
+
else:
|
|
83
|
+
E = maker_for_document(document)
|
package/src/lib/encodings.pyj
CHANGED
|
@@ -1,126 +1,126 @@
|
|
|
1
|
-
# vim:fileencoding=utf-8
|
|
2
|
-
# License: BSD Copyright: 2016, Kovid Goyal <kovid at kovidgoyal.net>
|
|
3
|
-
|
|
4
|
-
def base64encode(bytes, altchars, pad_char):
|
|
5
|
-
# Convert an array of bytes into a base-64 encoded string
|
|
6
|
-
l = bytes.length
|
|
7
|
-
remainder = l % 3
|
|
8
|
-
main_length = l - remainder
|
|
9
|
-
encodings = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789' + (altchars or '+/')
|
|
10
|
-
pad_char = '=' if pad_char is undefined else pad_char
|
|
11
|
-
ans = v'[]'
|
|
12
|
-
for v'var i = 0; i < main_length; i += 3':
|
|
13
|
-
chunk = (bytes[i] << 16) | (bytes[i + 1] << 8) | bytes[i + 2]
|
|
14
|
-
ans.push(encodings[(chunk & 16515072) >> 18], encodings[(chunk & 258048) >> 12], encodings[(chunk & 4032) >> 6], encodings[chunk & 63])
|
|
15
|
-
if remainder is 1:
|
|
16
|
-
chunk = bytes[main_length]
|
|
17
|
-
ans.push(encodings[(chunk & 252) >> 2], encodings[(chunk & 3) << 4], pad_char, pad_char)
|
|
18
|
-
elif remainder is 2:
|
|
19
|
-
chunk = (bytes[main_length] << 8) | bytes[main_length + 1]
|
|
20
|
-
ans.push(encodings[(chunk & 64512) >> 10], encodings[(chunk & 1008) >> 4], encodings[(chunk & 15) << 2], pad_char)
|
|
21
|
-
return ans.join('')
|
|
22
|
-
|
|
23
|
-
def base64decode(string):
|
|
24
|
-
# convert the output of base64encode back into an array of bytes
|
|
25
|
-
# (Uint8Array) only works with the standard altchars and pad_char
|
|
26
|
-
if jstype(window) is not 'undefined':
|
|
27
|
-
chars = window.atob(string)
|
|
28
|
-
else:
|
|
29
|
-
chars = new Buffer(string, 'base64').toString('binary') # noqa: undef
|
|
30
|
-
ans = Uint8Array(chars.length)
|
|
31
|
-
for i in range(ans.length):
|
|
32
|
-
ans[i] = chars.charCodeAt(i)
|
|
33
|
-
return ans
|
|
34
|
-
|
|
35
|
-
def urlsafe_b64encode(bytes, pad_char):
|
|
36
|
-
return base64encode(bytes, '-_', pad_char)
|
|
37
|
-
|
|
38
|
-
def urlsafe_b64decode(string):
|
|
39
|
-
string = String.prototype.replace.call(string, /[_-]/g, def(m): return '+' if m is '-' else '/';)
|
|
40
|
-
return base64decode(string)
|
|
41
|
-
|
|
42
|
-
def hexlify(bytes):
|
|
43
|
-
ans = v'[]'
|
|
44
|
-
for v'var i = 0; i < bytes.length; i++':
|
|
45
|
-
x = bytes[i].toString(16)
|
|
46
|
-
if x.length is 1:
|
|
47
|
-
x = '0' + x
|
|
48
|
-
ans.push(x)
|
|
49
|
-
return ans.join('')
|
|
50
|
-
|
|
51
|
-
def unhexlify(string):
|
|
52
|
-
num = string.length // 2
|
|
53
|
-
if num * 2 is not string.length:
|
|
54
|
-
raise ValueError('string length is not a multiple of two')
|
|
55
|
-
ans = Uint8Array(num)
|
|
56
|
-
for v'var i = 0; i < num; i++':
|
|
57
|
-
x = parseInt(string[i*2:i*2+2], 16)
|
|
58
|
-
if isNaN(x):
|
|
59
|
-
raise ValueError('string is not hex-encoded')
|
|
60
|
-
ans[i] = x
|
|
61
|
-
return ans
|
|
62
|
-
|
|
63
|
-
utf8_decoder_table = v'''[
|
|
64
|
-
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 00..1f
|
|
65
|
-
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 20..3f
|
|
66
|
-
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 40..5f
|
|
67
|
-
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 60..7f
|
|
68
|
-
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, // 80..9f
|
|
69
|
-
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, // a0..bf
|
|
70
|
-
8,8,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, // c0..df
|
|
71
|
-
0xa,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x4,0x3,0x3, // e0..ef
|
|
72
|
-
0xb,0x6,0x6,0x6,0x5,0x8,0x8,0x8,0x8,0x8,0x8,0x8,0x8,0x8,0x8,0x8, // f0..ff
|
|
73
|
-
0x0,0x1,0x2,0x3,0x5,0x8,0x7,0x1,0x1,0x1,0x4,0x6,0x1,0x1,0x1,0x1, // s0..s0
|
|
74
|
-
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,0,1,0,1,1,1,1,1,1, // s1..s2
|
|
75
|
-
1,2,1,1,1,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1, // s3..s4
|
|
76
|
-
1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,3,1,3,1,1,1,1,1,1, // s5..s6
|
|
77
|
-
1,3,1,1,1,1,1,3,1,3,1,1,1,1,1,1,1,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // s7..s8
|
|
78
|
-
]'''
|
|
79
|
-
|
|
80
|
-
def _from_code_point(x):
|
|
81
|
-
if x <= 0xFFFF:
|
|
82
|
-
return String.fromCharCode(x)
|
|
83
|
-
x -= 0x10000
|
|
84
|
-
return String.fromCharCode((x >> 10) + 0xD800, (x % 0x400) + 0xDC00)
|
|
85
|
-
|
|
86
|
-
def utf8_decode(bytes, errors, replacement):
|
|
87
|
-
# Convert an array of UTF-8 encoded bytes into a string
|
|
88
|
-
state = 0
|
|
89
|
-
ans = v'[]'
|
|
90
|
-
|
|
91
|
-
for v'var i = 0, l = bytes.length; i < l; i++': # noqa
|
|
92
|
-
byte = bytes[i]
|
|
93
|
-
typ = utf8_decoder_table[byte]
|
|
94
|
-
codep = (byte & 0x3f) | (codep << 6) if state is not 0 else (0xff >> typ) & (byte)
|
|
95
|
-
state = utf8_decoder_table[256 + state*16 + typ]
|
|
96
|
-
if state is 0:
|
|
97
|
-
ans.push(_from_code_point(codep))
|
|
98
|
-
elif state is 1:
|
|
99
|
-
if not errors or errors is 'strict':
|
|
100
|
-
raise UnicodeDecodeError(str.format('The byte 0x{:02x} at position {} is not valid UTF-8', byte, i))
|
|
101
|
-
elif errors is 'replace':
|
|
102
|
-
ans.push(replacement or '?')
|
|
103
|
-
return ans.join('')
|
|
104
|
-
|
|
105
|
-
def utf8_encode_js(string):
|
|
106
|
-
# Encode a string as an array of UTF-8 bytes
|
|
107
|
-
escstr = encodeURIComponent(string)
|
|
108
|
-
ans = v'[]'
|
|
109
|
-
for v'var i = 0; i < escstr.length; i++':
|
|
110
|
-
ch = escstr[i]
|
|
111
|
-
if ch is '%':
|
|
112
|
-
ans.push(parseInt(escstr[i+1:i+3], 16))
|
|
113
|
-
i += 2
|
|
114
|
-
else:
|
|
115
|
-
ans.push(ch.charCodeAt(0))
|
|
116
|
-
return Uint8Array(ans)
|
|
117
|
-
|
|
118
|
-
if jstype(TextEncoder) is 'function':
|
|
119
|
-
_u8enc = TextEncoder('utf-8')
|
|
120
|
-
utf8_encode = _u8enc.encode.bind(_u8enc)
|
|
121
|
-
_u8enc = undefined
|
|
122
|
-
else:
|
|
123
|
-
utf8_encode = utf8_encode_js
|
|
124
|
-
|
|
125
|
-
def utf8_encode_native(string):
|
|
126
|
-
return _u8enc.encode(string)
|
|
1
|
+
# vim:fileencoding=utf-8
|
|
2
|
+
# License: BSD Copyright: 2016, Kovid Goyal <kovid at kovidgoyal.net>
|
|
3
|
+
|
|
4
|
+
def base64encode(bytes, altchars, pad_char):
|
|
5
|
+
# Convert an array of bytes into a base-64 encoded string
|
|
6
|
+
l = bytes.length
|
|
7
|
+
remainder = l % 3
|
|
8
|
+
main_length = l - remainder
|
|
9
|
+
encodings = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789' + (altchars or '+/')
|
|
10
|
+
pad_char = '=' if pad_char is undefined else pad_char
|
|
11
|
+
ans = v'[]'
|
|
12
|
+
for v'var i = 0; i < main_length; i += 3':
|
|
13
|
+
chunk = (bytes[i] << 16) | (bytes[i + 1] << 8) | bytes[i + 2]
|
|
14
|
+
ans.push(encodings[(chunk & 16515072) >> 18], encodings[(chunk & 258048) >> 12], encodings[(chunk & 4032) >> 6], encodings[chunk & 63])
|
|
15
|
+
if remainder is 1:
|
|
16
|
+
chunk = bytes[main_length]
|
|
17
|
+
ans.push(encodings[(chunk & 252) >> 2], encodings[(chunk & 3) << 4], pad_char, pad_char)
|
|
18
|
+
elif remainder is 2:
|
|
19
|
+
chunk = (bytes[main_length] << 8) | bytes[main_length + 1]
|
|
20
|
+
ans.push(encodings[(chunk & 64512) >> 10], encodings[(chunk & 1008) >> 4], encodings[(chunk & 15) << 2], pad_char)
|
|
21
|
+
return ans.join('')
|
|
22
|
+
|
|
23
|
+
def base64decode(string):
|
|
24
|
+
# convert the output of base64encode back into an array of bytes
|
|
25
|
+
# (Uint8Array) only works with the standard altchars and pad_char
|
|
26
|
+
if jstype(window) is not 'undefined':
|
|
27
|
+
chars = window.atob(string)
|
|
28
|
+
else:
|
|
29
|
+
chars = new Buffer(string, 'base64').toString('binary') # noqa: undef
|
|
30
|
+
ans = Uint8Array(chars.length)
|
|
31
|
+
for i in range(ans.length):
|
|
32
|
+
ans[i] = chars.charCodeAt(i)
|
|
33
|
+
return ans
|
|
34
|
+
|
|
35
|
+
def urlsafe_b64encode(bytes, pad_char):
|
|
36
|
+
return base64encode(bytes, '-_', pad_char)
|
|
37
|
+
|
|
38
|
+
def urlsafe_b64decode(string):
|
|
39
|
+
string = String.prototype.replace.call(string, /[_-]/g, def(m): return '+' if m is '-' else '/';)
|
|
40
|
+
return base64decode(string)
|
|
41
|
+
|
|
42
|
+
def hexlify(bytes):
|
|
43
|
+
ans = v'[]'
|
|
44
|
+
for v'var i = 0; i < bytes.length; i++':
|
|
45
|
+
x = bytes[i].toString(16)
|
|
46
|
+
if x.length is 1:
|
|
47
|
+
x = '0' + x
|
|
48
|
+
ans.push(x)
|
|
49
|
+
return ans.join('')
|
|
50
|
+
|
|
51
|
+
def unhexlify(string):
|
|
52
|
+
num = string.length // 2
|
|
53
|
+
if num * 2 is not string.length:
|
|
54
|
+
raise ValueError('string length is not a multiple of two')
|
|
55
|
+
ans = Uint8Array(num)
|
|
56
|
+
for v'var i = 0; i < num; i++':
|
|
57
|
+
x = parseInt(string[i*2:i*2+2], 16)
|
|
58
|
+
if isNaN(x):
|
|
59
|
+
raise ValueError('string is not hex-encoded')
|
|
60
|
+
ans[i] = x
|
|
61
|
+
return ans
|
|
62
|
+
|
|
63
|
+
utf8_decoder_table = v'''[
|
|
64
|
+
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 00..1f
|
|
65
|
+
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 20..3f
|
|
66
|
+
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 40..5f
|
|
67
|
+
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 60..7f
|
|
68
|
+
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, // 80..9f
|
|
69
|
+
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, // a0..bf
|
|
70
|
+
8,8,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, // c0..df
|
|
71
|
+
0xa,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x4,0x3,0x3, // e0..ef
|
|
72
|
+
0xb,0x6,0x6,0x6,0x5,0x8,0x8,0x8,0x8,0x8,0x8,0x8,0x8,0x8,0x8,0x8, // f0..ff
|
|
73
|
+
0x0,0x1,0x2,0x3,0x5,0x8,0x7,0x1,0x1,0x1,0x4,0x6,0x1,0x1,0x1,0x1, // s0..s0
|
|
74
|
+
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,0,1,0,1,1,1,1,1,1, // s1..s2
|
|
75
|
+
1,2,1,1,1,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1, // s3..s4
|
|
76
|
+
1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,3,1,3,1,1,1,1,1,1, // s5..s6
|
|
77
|
+
1,3,1,1,1,1,1,3,1,3,1,1,1,1,1,1,1,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // s7..s8
|
|
78
|
+
]'''
|
|
79
|
+
|
|
80
|
+
def _from_code_point(x):
|
|
81
|
+
if x <= 0xFFFF:
|
|
82
|
+
return String.fromCharCode(x)
|
|
83
|
+
x -= 0x10000
|
|
84
|
+
return String.fromCharCode((x >> 10) + 0xD800, (x % 0x400) + 0xDC00)
|
|
85
|
+
|
|
86
|
+
def utf8_decode(bytes, errors, replacement):
|
|
87
|
+
# Convert an array of UTF-8 encoded bytes into a string
|
|
88
|
+
state = 0
|
|
89
|
+
ans = v'[]'
|
|
90
|
+
|
|
91
|
+
for v'var i = 0, l = bytes.length; i < l; i++': # noqa
|
|
92
|
+
byte = bytes[i]
|
|
93
|
+
typ = utf8_decoder_table[byte]
|
|
94
|
+
codep = (byte & 0x3f) | (codep << 6) if state is not 0 else (0xff >> typ) & (byte)
|
|
95
|
+
state = utf8_decoder_table[256 + state*16 + typ]
|
|
96
|
+
if state is 0:
|
|
97
|
+
ans.push(_from_code_point(codep))
|
|
98
|
+
elif state is 1:
|
|
99
|
+
if not errors or errors is 'strict':
|
|
100
|
+
raise UnicodeDecodeError(str.format('The byte 0x{:02x} at position {} is not valid UTF-8', byte, i))
|
|
101
|
+
elif errors is 'replace':
|
|
102
|
+
ans.push(replacement or '?')
|
|
103
|
+
return ans.join('')
|
|
104
|
+
|
|
105
|
+
def utf8_encode_js(string):
|
|
106
|
+
# Encode a string as an array of UTF-8 bytes
|
|
107
|
+
escstr = encodeURIComponent(string)
|
|
108
|
+
ans = v'[]'
|
|
109
|
+
for v'var i = 0; i < escstr.length; i++':
|
|
110
|
+
ch = escstr[i]
|
|
111
|
+
if ch is '%':
|
|
112
|
+
ans.push(parseInt(escstr[i+1:i+3], 16))
|
|
113
|
+
i += 2
|
|
114
|
+
else:
|
|
115
|
+
ans.push(ch.charCodeAt(0))
|
|
116
|
+
return Uint8Array(ans)
|
|
117
|
+
|
|
118
|
+
if jstype(TextEncoder) is 'function':
|
|
119
|
+
_u8enc = TextEncoder('utf-8')
|
|
120
|
+
utf8_encode = _u8enc.encode.bind(_u8enc)
|
|
121
|
+
_u8enc = undefined
|
|
122
|
+
else:
|
|
123
|
+
utf8_encode = utf8_encode_js
|
|
124
|
+
|
|
125
|
+
def utf8_encode_native(string):
|
|
126
|
+
return _u8enc.encode(string)
|
package/src/lib/enum.pyj
ADDED
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
# vim:fileencoding=utf-8
|
|
2
|
+
# License: BSD
|
|
3
|
+
# RapydScript implementation of Python's enum standard library.
|
|
4
|
+
#
|
|
5
|
+
# Supported: Enum base class with .name, .value attributes, iteration over
|
|
6
|
+
# members, and Color.RED access — matching Python's Enum syntax.
|
|
7
|
+
#
|
|
8
|
+
# Usage:
|
|
9
|
+
# from enum import Enum
|
|
10
|
+
#
|
|
11
|
+
# class Color(Enum):
|
|
12
|
+
# RED = 1
|
|
13
|
+
# GREEN = 2
|
|
14
|
+
# BLUE = 3
|
|
15
|
+
#
|
|
16
|
+
# Color.RED.name # 'RED'
|
|
17
|
+
# Color.RED.value # 1
|
|
18
|
+
# list(Color) # [<Color.RED: 1>, <Color.GREEN: 2>, <Color.BLUE: 3>]
|
|
19
|
+
# for m in Color: print(m)
|
|
20
|
+
#
|
|
21
|
+
# Implementation notes:
|
|
22
|
+
# - The RapydScript compiler now emits class variables (prototype assignments)
|
|
23
|
+
# BEFORE calling __init_subclass__, so the hook can inspect them.
|
|
24
|
+
# - Enum members are plain objects created with Object.create(cls.prototype);
|
|
25
|
+
# they are true instances of the subclass and of Enum.
|
|
26
|
+
# - Member singletons: Color.RED is always the same object.
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class Enum:
|
|
30
|
+
"""Base class for creating enumerated constants."""
|
|
31
|
+
|
|
32
|
+
def __init__(self, value=None):
|
|
33
|
+
# Enum members are created lazily by __init_subclass__, not by calling
|
|
34
|
+
# the constructor directly. This __init__ is intentionally a no-op so
|
|
35
|
+
# that the constructor can be called without side-effects.
|
|
36
|
+
pass
|
|
37
|
+
|
|
38
|
+
@property
|
|
39
|
+
def name(self):
|
|
40
|
+
return this._name_
|
|
41
|
+
|
|
42
|
+
@property
|
|
43
|
+
def value(self):
|
|
44
|
+
return this._value_
|
|
45
|
+
|
|
46
|
+
def __repr__(self):
|
|
47
|
+
return '<' + this.__class__.__name__ + '.' + this._name_ + ': ' + repr(this._value_) + '>'
|
|
48
|
+
|
|
49
|
+
def __str__(self):
|
|
50
|
+
return this.__class__.__name__ + '.' + this._name_
|
|
51
|
+
|
|
52
|
+
def __eq__(self, other):
|
|
53
|
+
# Enum members compare by identity (same as Python).
|
|
54
|
+
return this is other
|
|
55
|
+
|
|
56
|
+
def __hash__(self):
|
|
57
|
+
return this._value_
|
|
58
|
+
|
|
59
|
+
@classmethod
|
|
60
|
+
def __init_subclass__(cls, **kwargs):
|
|
61
|
+
"""
|
|
62
|
+
Called automatically when a class inherits from Enum.
|
|
63
|
+
|
|
64
|
+
Walks the own enumerable string-keyed properties of cls.prototype
|
|
65
|
+
(which at this point already hold the raw class-variable values because
|
|
66
|
+
the compiler emits class variables before this hook) and replaces each
|
|
67
|
+
non-function, non-dunder value with a proper enum member object that
|
|
68
|
+
carries .name and .value attributes.
|
|
69
|
+
|
|
70
|
+
Also installs Symbol.iterator on the prototype so that
|
|
71
|
+
``for m in Color:`` and ``list(Color)`` work.
|
|
72
|
+
"""
|
|
73
|
+
proto = cls.prototype
|
|
74
|
+
members = {}
|
|
75
|
+
members_by_value = {}
|
|
76
|
+
members_list = []
|
|
77
|
+
|
|
78
|
+
keys = v"Object.keys(proto)"
|
|
79
|
+
for k in keys:
|
|
80
|
+
# Skip dunder names (__init__, __repr__, …) and RapydScript internals
|
|
81
|
+
if k.startsWith('_') or k.startsWith('ρσ'):
|
|
82
|
+
continue
|
|
83
|
+
val = proto[k]
|
|
84
|
+
# Skip methods (functions) and already-processed members
|
|
85
|
+
if jstype(val) is 'function':
|
|
86
|
+
continue
|
|
87
|
+
if v"val instanceof cls":
|
|
88
|
+
continue
|
|
89
|
+
|
|
90
|
+
# Create an enum member as an object that inherits from cls.prototype,
|
|
91
|
+
# bypassing the constructor (same idea as Python's EnumMeta.__new__).
|
|
92
|
+
v"""
|
|
93
|
+
var ρσ_member = Object.create(proto);
|
|
94
|
+
ρσ_member._name_ = k;
|
|
95
|
+
ρσ_member._value_ = val;
|
|
96
|
+
"""
|
|
97
|
+
|
|
98
|
+
# Replace the raw value on the prototype with the member singleton.
|
|
99
|
+
proto[k] = ρσ_member # noqa: F821
|
|
100
|
+
|
|
101
|
+
members[k] = ρσ_member
|
|
102
|
+
if v"members_by_value[val] === undefined":
|
|
103
|
+
members_by_value[val] = ρσ_member
|
|
104
|
+
members_list.push(ρσ_member)
|
|
105
|
+
|
|
106
|
+
# Store the member registry on the class constructor itself.
|
|
107
|
+
cls._members_ = members
|
|
108
|
+
cls._members_by_value_ = members_by_value
|
|
109
|
+
cls._member_names_ = members_list.map(def(m): return m._name_;)
|
|
110
|
+
|
|
111
|
+
# Install Symbol.iterator on the class constructor itself (not the
|
|
112
|
+
# prototype) so that ``list(Color)`` and ``for m in Color:`` work.
|
|
113
|
+
# ρσ_list_constructor checks iterable[Symbol.iterator] on the object
|
|
114
|
+
# being iterated; for an enum class that object is the constructor.
|
|
115
|
+
v"""cls[Symbol.iterator] = function() {
|
|
116
|
+
var ρσ_i = 0;
|
|
117
|
+
return {
|
|
118
|
+
next: function() {
|
|
119
|
+
if (ρσ_i < members_list.length) {
|
|
120
|
+
return { value: members_list[ρσ_i++], done: false };
|
|
121
|
+
}
|
|
122
|
+
return { value: undefined, done: true };
|
|
123
|
+
}
|
|
124
|
+
};
|
|
125
|
+
};"""
|