rapydscript-ns 0.9.1 → 0.9.2
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 +3 -1
- package/HACKING.md +103 -103
- package/LICENSE +24 -24
- package/README.md +1 -1
- package/TODO.md +117 -0
- 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 +7 -7
- package/language-service/language-service.d.ts +1 -1
- package/package.json +6 -2
- package/publish.py +37 -37
- package/release/compiler.js +245 -230
- package/release/signatures.json +22 -22
- package/session.vim +4 -4
- package/setup.cfg +2 -2
- package/src/compiler.pyj +36 -36
- package/src/errors.pyj +30 -30
- package/src/lib/aes.pyj +646 -646
- package/src/lib/copy.pyj +120 -120
- package/src/lib/elementmaker.pyj +83 -83
- package/src/lib/encodings.pyj +126 -126
- 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/react.pyj +74 -74
- package/src/lib/traceback.pyj +63 -63
- package/src/lib/uuid.pyj +77 -77
- package/src/monaco-language-service/diagnostics.js +2 -2
- package/src/monaco-language-service/dts.js +550 -550
- package/src/monaco-language-service/index.js +2 -2
- package/src/output/comments.pyj +45 -45
- package/src/output/exceptions.pyj +201 -201
- package/src/output/jsx.pyj +164 -164
- package/src/output/loops.pyj +9 -0
- package/src/output/treeshake.pyj +182 -182
- package/src/output/utils.pyj +72 -72
- package/src/string_interpolation.pyj +72 -72
- 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/aes_vectors.pyj +421 -421
- package/test/annotations.pyj +80 -80
- package/test/decorators.pyj +77 -77
- package/test/docstrings.pyj +39 -39
- package/test/elementmaker_test.pyj +45 -45
- 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/omit_function_metadata.pyj +20 -20
- package/test/repl.pyj +121 -121
- package/test/scoped_flags.pyj +76 -76
- package/test/unit/index.js +66 -0
- package/test/unit/language-service-dts.js +543 -543
- package/test/unit/language-service-hover.js +455 -455
- package/test/unit/language-service.js +1 -1
- package/tools/compiler.d.ts +367 -0
- package/tools/completer.js +131 -131
- package/tools/gettext.js +185 -185
- package/tools/ini.js +65 -65
- 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/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/test/imports.pyj
CHANGED
|
@@ -1,72 +1,72 @@
|
|
|
1
|
-
# globals:test_path, GLOBAL_SYMBOL, assrt
|
|
2
|
-
from _import_one import toplevel_var, toplevel_func as tf, TopLevel, true_var, false_var, test_other
|
|
3
|
-
from _import_two import (toplevel_var2,
|
|
4
|
-
toplevel_func2, TopLevel2 as TL2)
|
|
5
|
-
|
|
6
|
-
def AClass(x):
|
|
7
|
-
return this
|
|
8
|
-
|
|
9
|
-
eq = assrt.equal
|
|
10
|
-
# Test import of top-level variables and callables
|
|
11
|
-
eq(toplevel_var, 'foo')
|
|
12
|
-
eq(tf('x'), 'xtoplevel')
|
|
13
|
-
eq(toplevel_var2, 'foo2')
|
|
14
|
-
eq(toplevel_func2('x'), 'xtoplevel2')
|
|
15
|
-
eq(false_var, undefined)
|
|
16
|
-
eq(test_other, 'other')
|
|
17
|
-
|
|
18
|
-
# Test import of top-level vars in a conditional
|
|
19
|
-
eq('true', true_var)
|
|
20
|
-
|
|
21
|
-
# Test plain imports
|
|
22
|
-
import _import_one
|
|
23
|
-
eq(_import_one.toplevel_var, toplevel_var)
|
|
24
|
-
eq(_import_one.toplevel_func('x'), tf('x'))
|
|
25
|
-
|
|
26
|
-
# Test recognition of imported classes
|
|
27
|
-
tl = TopLevel('1')
|
|
28
|
-
eq(tl.a, '1')
|
|
29
|
-
tl2 = TL2('x')
|
|
30
|
-
eq(tl2.a, 'x')
|
|
31
|
-
|
|
32
|
-
# Test access to submodules via plain imports
|
|
33
|
-
import _import_two.sub, _import_two.sub as ts
|
|
34
|
-
eq('sub', _import_two.sub.sub_var)
|
|
35
|
-
eq('sub', ts.sub_var)
|
|
36
|
-
eq('sub', _import_two.sub.sub_func())
|
|
37
|
-
|
|
38
|
-
# Test deep import
|
|
39
|
-
from _import_two.level2.deep import deep_var
|
|
40
|
-
eq('deep', deep_var)
|
|
41
|
-
|
|
42
|
-
# Test that class accessed via plain import is
|
|
43
|
-
# recognized
|
|
44
|
-
s = _import_two.sub.Sub(1)
|
|
45
|
-
eq(s.a, 1)
|
|
46
|
-
s2 = ts.Sub(1)
|
|
47
|
-
eq(s2.a, 1)
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
# Test that a class imported into an inner scope is not recognized as a class
|
|
51
|
-
# outside that scope
|
|
52
|
-
def inner():
|
|
53
|
-
from _import_one import AClass
|
|
54
|
-
a = AClass(1)
|
|
55
|
-
eq(a.a, 1)
|
|
56
|
-
|
|
57
|
-
inner()
|
|
58
|
-
b = AClass(1)
|
|
59
|
-
eq(b, this)
|
|
60
|
-
|
|
61
|
-
# Test global symbol declared in other module
|
|
62
|
-
eq(GLOBAL_SYMBOL, 'i am global')
|
|
63
|
-
|
|
64
|
-
# Import errors happen during parsing, so we cannot test them directly as they would
|
|
65
|
-
# prevent this file from being parsed.
|
|
66
|
-
|
|
67
|
-
assrt.throws(def():
|
|
68
|
-
RapydScript.parse('from _import_one import not_exported', {'basedir':test_path}).body[0]
|
|
69
|
-
, /not exported/)
|
|
70
|
-
assrt.throws(def():
|
|
71
|
-
RapydScript.parse('import xxxx', {'basedir':test_path}).body[0]
|
|
72
|
-
, /doesn't exist/)
|
|
1
|
+
# globals:test_path, GLOBAL_SYMBOL, assrt
|
|
2
|
+
from _import_one import toplevel_var, toplevel_func as tf, TopLevel, true_var, false_var, test_other
|
|
3
|
+
from _import_two import (toplevel_var2,
|
|
4
|
+
toplevel_func2, TopLevel2 as TL2)
|
|
5
|
+
|
|
6
|
+
def AClass(x):
|
|
7
|
+
return this
|
|
8
|
+
|
|
9
|
+
eq = assrt.equal
|
|
10
|
+
# Test import of top-level variables and callables
|
|
11
|
+
eq(toplevel_var, 'foo')
|
|
12
|
+
eq(tf('x'), 'xtoplevel')
|
|
13
|
+
eq(toplevel_var2, 'foo2')
|
|
14
|
+
eq(toplevel_func2('x'), 'xtoplevel2')
|
|
15
|
+
eq(false_var, undefined)
|
|
16
|
+
eq(test_other, 'other')
|
|
17
|
+
|
|
18
|
+
# Test import of top-level vars in a conditional
|
|
19
|
+
eq('true', true_var)
|
|
20
|
+
|
|
21
|
+
# Test plain imports
|
|
22
|
+
import _import_one
|
|
23
|
+
eq(_import_one.toplevel_var, toplevel_var)
|
|
24
|
+
eq(_import_one.toplevel_func('x'), tf('x'))
|
|
25
|
+
|
|
26
|
+
# Test recognition of imported classes
|
|
27
|
+
tl = TopLevel('1')
|
|
28
|
+
eq(tl.a, '1')
|
|
29
|
+
tl2 = TL2('x')
|
|
30
|
+
eq(tl2.a, 'x')
|
|
31
|
+
|
|
32
|
+
# Test access to submodules via plain imports
|
|
33
|
+
import _import_two.sub, _import_two.sub as ts
|
|
34
|
+
eq('sub', _import_two.sub.sub_var)
|
|
35
|
+
eq('sub', ts.sub_var)
|
|
36
|
+
eq('sub', _import_two.sub.sub_func())
|
|
37
|
+
|
|
38
|
+
# Test deep import
|
|
39
|
+
from _import_two.level2.deep import deep_var
|
|
40
|
+
eq('deep', deep_var)
|
|
41
|
+
|
|
42
|
+
# Test that class accessed via plain import is
|
|
43
|
+
# recognized
|
|
44
|
+
s = _import_two.sub.Sub(1)
|
|
45
|
+
eq(s.a, 1)
|
|
46
|
+
s2 = ts.Sub(1)
|
|
47
|
+
eq(s2.a, 1)
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
# Test that a class imported into an inner scope is not recognized as a class
|
|
51
|
+
# outside that scope
|
|
52
|
+
def inner():
|
|
53
|
+
from _import_one import AClass
|
|
54
|
+
a = AClass(1)
|
|
55
|
+
eq(a.a, 1)
|
|
56
|
+
|
|
57
|
+
inner()
|
|
58
|
+
b = AClass(1)
|
|
59
|
+
eq(b, this)
|
|
60
|
+
|
|
61
|
+
# Test global symbol declared in other module
|
|
62
|
+
eq(GLOBAL_SYMBOL, 'i am global')
|
|
63
|
+
|
|
64
|
+
# Import errors happen during parsing, so we cannot test them directly as they would
|
|
65
|
+
# prevent this file from being parsed.
|
|
66
|
+
|
|
67
|
+
assrt.throws(def():
|
|
68
|
+
RapydScript.parse('from _import_one import not_exported', {'basedir':test_path}).body[0]
|
|
69
|
+
, /not exported/)
|
|
70
|
+
assrt.throws(def():
|
|
71
|
+
RapydScript.parse('import xxxx', {'basedir':test_path}).body[0]
|
|
72
|
+
, /doesn't exist/)
|
|
@@ -1,73 +1,73 @@
|
|
|
1
|
-
# vim:fileencoding=utf-8
|
|
2
|
-
# License: BSD Copyright: 2015, Kovid Goyal <kovid at kovidgoyal.net>
|
|
3
|
-
|
|
4
|
-
from gettext import gettext as _, ngettext, install
|
|
5
|
-
|
|
6
|
-
g = require('../tools/gettext.js')
|
|
7
|
-
|
|
8
|
-
def gettext(code):
|
|
9
|
-
ans = {}
|
|
10
|
-
g.gettext(ans, code, '<test>')
|
|
11
|
-
return ans
|
|
12
|
-
|
|
13
|
-
def test_string(code, *args):
|
|
14
|
-
catalog = gettext(code)
|
|
15
|
-
assrt.equal(len(catalog), len(args))
|
|
16
|
-
for msgid, q in zip(Object.keys(catalog), args):
|
|
17
|
-
assrt.equal(g.entry_to_string(msgid, catalog[msgid]), q)
|
|
18
|
-
|
|
19
|
-
test_string('a = _("one")', '#: <test>:1\nmsgid "one"\nmsgstr ""')
|
|
20
|
-
test_string('a = _("one")\nb = gettext("one")', '#: <test>:1\n#: <test>:2\nmsgid "one"\nmsgstr ""')
|
|
21
|
-
test_string('''a = _("""one
|
|
22
|
-
two""")''', '#: <test>:1\nmsgid "one\\ntwo"\nmsgstr ""')
|
|
23
|
-
test_string('a = _("{}one")', '#: <test>:1\n#, python-brace-format\nmsgid "{}one"\nmsgstr ""')
|
|
24
|
-
test_string('a = _("{one}")', '#: <test>:1\n#, python-brace-format\nmsgid "{one}"\nmsgstr ""')
|
|
25
|
-
test_string('ngettext("one", "two", 1)', '#: <test>:1\nmsgid "one"\nmsgid_plural "two"\nmsgstr[0] ""\nmsgstr[1] ""')
|
|
26
|
-
test_string('''_('o"ne')''', '#: <test>:1\nmsgid "o\\"ne"\nmsgstr ""')
|
|
27
|
-
|
|
28
|
-
m = require('../tools/msgfmt.js')
|
|
29
|
-
catalog = m.parse(r'''
|
|
30
|
-
msgid ""
|
|
31
|
-
msgstr ""
|
|
32
|
-
"Language: en\n"
|
|
33
|
-
"Plural-Forms: nplurals=2; \n"
|
|
34
|
-
|
|
35
|
-
#, fuzzy
|
|
36
|
-
msgid "one\n"
|
|
37
|
-
"continued"
|
|
38
|
-
msgstr "ON"
|
|
39
|
-
"E"
|
|
40
|
-
|
|
41
|
-
msgid "two"
|
|
42
|
-
msgid_plural "three"
|
|
43
|
-
msgstr[0] "a"
|
|
44
|
-
"bc"
|
|
45
|
-
msgstr[1] "def"
|
|
46
|
-
|
|
47
|
-
msgid "test \"quote\" escape"
|
|
48
|
-
msgstr "good"
|
|
49
|
-
''')
|
|
50
|
-
|
|
51
|
-
assrt.equal(2, catalog['nplurals'])
|
|
52
|
-
assrt.equal('en', catalog['language'])
|
|
53
|
-
assrt.equal(catalog['entries'].length, 3)
|
|
54
|
-
item = catalog['entries'][0]
|
|
55
|
-
assrt.equal(item['msgid'], 'one\ncontinued')
|
|
56
|
-
assrt.deepEqual(item['msgstr'], v"['ONE']")
|
|
57
|
-
assrt.ok(item['fuzzy'], 'item not fuzzy')
|
|
58
|
-
item = catalog['entries'][1]
|
|
59
|
-
assrt.equal(item['msgid'], 'two')
|
|
60
|
-
assrt.deepEqual(item['msgstr'], v"['abc', 'def']")
|
|
61
|
-
assrt.ok(not item['fuzzy'], 'item not fuzzy')
|
|
62
|
-
item = catalog['entries'][2]
|
|
63
|
-
assrt.equal(item['msgid'], 'test "quote" escape')
|
|
64
|
-
assrt.deepEqual(item['msgstr'], v"['good']")
|
|
65
|
-
|
|
66
|
-
install({'entries': {
|
|
67
|
-
'one':['ONE'],
|
|
68
|
-
'two':['1', '2'],
|
|
69
|
-
}})
|
|
70
|
-
|
|
71
|
-
assrt.equal(_('one'), 'ONE')
|
|
72
|
-
assrt.equal(ngettext('two', 'xxx', 1), '1')
|
|
73
|
-
assrt.equal(ngettext('two', 'xxx', 100), '2')
|
|
1
|
+
# vim:fileencoding=utf-8
|
|
2
|
+
# License: BSD Copyright: 2015, Kovid Goyal <kovid at kovidgoyal.net>
|
|
3
|
+
|
|
4
|
+
from gettext import gettext as _, ngettext, install
|
|
5
|
+
|
|
6
|
+
g = require('../tools/gettext.js')
|
|
7
|
+
|
|
8
|
+
def gettext(code):
|
|
9
|
+
ans = {}
|
|
10
|
+
g.gettext(ans, code, '<test>')
|
|
11
|
+
return ans
|
|
12
|
+
|
|
13
|
+
def test_string(code, *args):
|
|
14
|
+
catalog = gettext(code)
|
|
15
|
+
assrt.equal(len(catalog), len(args))
|
|
16
|
+
for msgid, q in zip(Object.keys(catalog), args):
|
|
17
|
+
assrt.equal(g.entry_to_string(msgid, catalog[msgid]), q)
|
|
18
|
+
|
|
19
|
+
test_string('a = _("one")', '#: <test>:1\nmsgid "one"\nmsgstr ""')
|
|
20
|
+
test_string('a = _("one")\nb = gettext("one")', '#: <test>:1\n#: <test>:2\nmsgid "one"\nmsgstr ""')
|
|
21
|
+
test_string('''a = _("""one
|
|
22
|
+
two""")''', '#: <test>:1\nmsgid "one\\ntwo"\nmsgstr ""')
|
|
23
|
+
test_string('a = _("{}one")', '#: <test>:1\n#, python-brace-format\nmsgid "{}one"\nmsgstr ""')
|
|
24
|
+
test_string('a = _("{one}")', '#: <test>:1\n#, python-brace-format\nmsgid "{one}"\nmsgstr ""')
|
|
25
|
+
test_string('ngettext("one", "two", 1)', '#: <test>:1\nmsgid "one"\nmsgid_plural "two"\nmsgstr[0] ""\nmsgstr[1] ""')
|
|
26
|
+
test_string('''_('o"ne')''', '#: <test>:1\nmsgid "o\\"ne"\nmsgstr ""')
|
|
27
|
+
|
|
28
|
+
m = require('../tools/msgfmt.js')
|
|
29
|
+
catalog = m.parse(r'''
|
|
30
|
+
msgid ""
|
|
31
|
+
msgstr ""
|
|
32
|
+
"Language: en\n"
|
|
33
|
+
"Plural-Forms: nplurals=2; \n"
|
|
34
|
+
|
|
35
|
+
#, fuzzy
|
|
36
|
+
msgid "one\n"
|
|
37
|
+
"continued"
|
|
38
|
+
msgstr "ON"
|
|
39
|
+
"E"
|
|
40
|
+
|
|
41
|
+
msgid "two"
|
|
42
|
+
msgid_plural "three"
|
|
43
|
+
msgstr[0] "a"
|
|
44
|
+
"bc"
|
|
45
|
+
msgstr[1] "def"
|
|
46
|
+
|
|
47
|
+
msgid "test \"quote\" escape"
|
|
48
|
+
msgstr "good"
|
|
49
|
+
''')
|
|
50
|
+
|
|
51
|
+
assrt.equal(2, catalog['nplurals'])
|
|
52
|
+
assrt.equal('en', catalog['language'])
|
|
53
|
+
assrt.equal(catalog['entries'].length, 3)
|
|
54
|
+
item = catalog['entries'][0]
|
|
55
|
+
assrt.equal(item['msgid'], 'one\ncontinued')
|
|
56
|
+
assrt.deepEqual(item['msgstr'], v"['ONE']")
|
|
57
|
+
assrt.ok(item['fuzzy'], 'item not fuzzy')
|
|
58
|
+
item = catalog['entries'][1]
|
|
59
|
+
assrt.equal(item['msgid'], 'two')
|
|
60
|
+
assrt.deepEqual(item['msgstr'], v"['abc', 'def']")
|
|
61
|
+
assrt.ok(not item['fuzzy'], 'item not fuzzy')
|
|
62
|
+
item = catalog['entries'][2]
|
|
63
|
+
assrt.equal(item['msgid'], 'test "quote" escape')
|
|
64
|
+
assrt.deepEqual(item['msgstr'], v"['good']")
|
|
65
|
+
|
|
66
|
+
install({'entries': {
|
|
67
|
+
'one':['ONE'],
|
|
68
|
+
'two':['1', '2'],
|
|
69
|
+
}})
|
|
70
|
+
|
|
71
|
+
assrt.equal(_('one'), 'ONE')
|
|
72
|
+
assrt.equal(ngettext('two', 'xxx', 1), '1')
|
|
73
|
+
assrt.equal(ngettext('two', 'xxx', 100), '2')
|
package/test/lint.pyj
CHANGED
|
@@ -1,164 +1,164 @@
|
|
|
1
|
-
# vim:fileencoding=utf-8
|
|
2
|
-
# License: BSD
|
|
3
|
-
# Copyright: 2015, Kovid Goyal <kovid at kovidgoyal.net>
|
|
4
|
-
|
|
5
|
-
linter = require('../tools/lint.js')
|
|
6
|
-
|
|
7
|
-
def lint(code):
|
|
8
|
-
return linter.lint_code(code, {'filename':'<test>', 'report':def():
|
|
9
|
-
pass
|
|
10
|
-
})
|
|
11
|
-
|
|
12
|
-
def err_test(code, ident, line, name, other_line):
|
|
13
|
-
msgs = lint(code)
|
|
14
|
-
assrt.ok(len(msgs) > 0, 'failed to find error in: ' + code)
|
|
15
|
-
assrt.equal(len(msgs), 1, 'found ' + (len(msgs) - 1) + ' extra errors in: ' + code)
|
|
16
|
-
assrt.equal(msgs[0].ident, ident, 'incorrect ident: ' + msgs[0].ident + ' for: ' + code)
|
|
17
|
-
if line != undefined:
|
|
18
|
-
assrt.equal(msgs[0].start_line, line, 'incorrect line: ' + msgs[0].start_line + ' for: ' + code)
|
|
19
|
-
if name != undefined:
|
|
20
|
-
assrt.equal(msgs[0].name, name, 'incorrect name: ' + msgs[0].name + ' for: ' + code)
|
|
21
|
-
if other_line != undefined:
|
|
22
|
-
assrt.equal(msgs[0].other_line, other_line, 'incorrect other_line: ' + msgs[0].other_line + ' for: ' + code)
|
|
23
|
-
|
|
24
|
-
def ok_test(code):
|
|
25
|
-
msgs = lint(code)
|
|
26
|
-
assrt.equal(msgs.length, 0, 'Got unexpected msg: ' + (msgs[0] or {}).message + ' for code: ' + code)
|
|
27
|
-
|
|
28
|
-
# Imports
|
|
29
|
-
err_test('import foo', 'unused-import', 1, 'foo')
|
|
30
|
-
err_test('import foo.boo', 'unused-import', 1, 'foo')
|
|
31
|
-
err_test('import foo as boo', 'unused-import', 1, 'boo')
|
|
32
|
-
err_test('from x import foo', 'unused-import', 1, 'foo')
|
|
33
|
-
err_test('from x import foo as boo', 'unused-import', 1, 'boo')
|
|
34
|
-
ok_test('import foo\nfoo')
|
|
35
|
-
|
|
36
|
-
# Function arguments
|
|
37
|
-
ok_test('def f(a):\n return a')
|
|
38
|
-
ok_test('def f(a=1):\n return a')
|
|
39
|
-
ok_test('def f(*a):\n return a')
|
|
40
|
-
ok_test('def f(**a):\n return a')
|
|
41
|
-
ok_test('def f(a):\n return 1')
|
|
42
|
-
|
|
43
|
-
# Extended slices
|
|
44
|
-
ok_test('a = []; a[::2], a[1:-1]')
|
|
45
|
-
|
|
46
|
-
# Top level unused ignored
|
|
47
|
-
ok_test('a=1\ndef f():\n pass')
|
|
48
|
-
|
|
49
|
-
# Destructuring assignment
|
|
50
|
-
ok_test('def f():\n a, b = 1, 2; a, b')
|
|
51
|
-
ok_test('def f():\n a = 1; b, c = a, 2; return b, c')
|
|
52
|
-
ok_test('for x, (y, z) in [ [1, [2, 3]] ]:\n x + y + z')
|
|
53
|
-
err_test('def f():\n a, b = 1, 1; return a', 'unused-local', 2, 'b')
|
|
54
|
-
|
|
55
|
-
# Compound assignment
|
|
56
|
-
err_test('a += 1', 'undef', 1, 'a')
|
|
57
|
-
ok_test('def f():\n a = 1; a += 1')
|
|
58
|
-
|
|
59
|
-
# Unused bindings
|
|
60
|
-
err_test('def f():\n a=1', 'unused-local', 2, 'a')
|
|
61
|
-
err_test('def f():\n def a():\n pass', 'unused-local', 2, 'a')
|
|
62
|
-
|
|
63
|
-
# Undefined references
|
|
64
|
-
err_test('f()', 'undef', 1, 'f')
|
|
65
|
-
err_test('a', 'undef', 1, 'a')
|
|
66
|
-
err_test('def f():\n a=1; return a\na', 'undef', 3, 'a')
|
|
67
|
-
|
|
68
|
-
# Comprehensions
|
|
69
|
-
ok_test('[x for x in [1,2]]')
|
|
70
|
-
ok_test('[1 for x in [1,2] if x]')
|
|
71
|
-
ok_test('[1 for x in [1,2]]')
|
|
72
|
-
ok_test('def f():\n l=[1,2];[x for x in l]')
|
|
73
|
-
ok_test('def f():\n l=[1,2];{x:True for x in l}')
|
|
74
|
-
err_test('def f():\n [x for x in [1,2]]; return x', 'undef', 2, 'x')
|
|
75
|
-
|
|
76
|
-
# Loops
|
|
77
|
-
ok_test('def f():\n for x in "":\n pass\n return x')
|
|
78
|
-
ok_test('def f():\n for x in "":\n x += 1\n')
|
|
79
|
-
ok_test('def f():\n for x, y in "":\n pass\n return x, y')
|
|
80
|
-
ok_test('for v"var i = 0; i < 1; i++":\n print(i)')
|
|
81
|
-
err_test('def f():\n a = 1\n for a in "":\n a', 'loop-shadowed', 3, 'a', 2)
|
|
82
|
-
|
|
83
|
-
# Semi-colons
|
|
84
|
-
err_test('a=1;;a', 'extra-semicolon', 1, ';')
|
|
85
|
-
err_test('a=1;', 'eol-semicolon', 1, ';')
|
|
86
|
-
|
|
87
|
-
# Builtins
|
|
88
|
-
for k in 'String Symbol this self window Map arguments print len range dir undefined'.split(' '):
|
|
89
|
-
ok_test(k)
|
|
90
|
-
|
|
91
|
-
# noqa
|
|
92
|
-
ok_test('f() # noqa')
|
|
93
|
-
ok_test('f() # noqa:undef')
|
|
94
|
-
err_test('f() # noqa:xxx', 'undef')
|
|
95
|
-
|
|
96
|
-
# Named func in branch
|
|
97
|
-
err_test('if 1:\n def f():\n pass', 'func-in-branch', 2, 'f')
|
|
98
|
-
err_test('if 1:\n pass\nelse:\n def f():\n pass', 'func-in-branch', 4, 'f')
|
|
99
|
-
err_test('try:\n def f():\n pass\nexcept:\n pass', 'func-in-branch', 2, 'f')
|
|
100
|
-
ok_test('if 1:\n a = def():\n pass')
|
|
101
|
-
|
|
102
|
-
# Syntax errors
|
|
103
|
-
err_test('def f(:\n pass', 'syntax-err', 1)
|
|
104
|
-
|
|
105
|
-
# Functions
|
|
106
|
-
ok_test('def f():\n pass\nf()')
|
|
107
|
-
|
|
108
|
-
# Non-locals
|
|
109
|
-
err_test('def a():\n x = 1\n def b():\n nonlocal x\n b()', 'unused-local', 2, 'x')
|
|
110
|
-
ok_test('def a():\n x = 1\n def b():\n nonlocal x\n x\n b()')
|
|
111
|
-
ok_test('def a():\n x = 1\n def b():\n nonlocal x\n x\n x = 2\n b()')
|
|
112
|
-
ok_test('def a():\n x = 1\n def ():\n nonlocal x\n x = 1\n x')
|
|
113
|
-
ok_test('nonlocal a\na()')
|
|
114
|
-
|
|
115
|
-
# Define after use
|
|
116
|
-
err_test('def g():\n f()\n f()\n def f():\n pass', 'def-after-use', 3, 'f')
|
|
117
|
-
|
|
118
|
-
# Decorators
|
|
119
|
-
ok_test('from x import y\n@y\ndef f():\n pass')
|
|
120
|
-
|
|
121
|
-
# try/except
|
|
122
|
-
ok_test('try:\n 1\nexcept Error as e:\n e')
|
|
123
|
-
|
|
124
|
-
# Classes
|
|
125
|
-
ok_test('''
|
|
126
|
-
class A:
|
|
127
|
-
|
|
128
|
-
h = j = 1
|
|
129
|
-
x = h + j
|
|
130
|
-
if True:
|
|
131
|
-
k = 1
|
|
132
|
-
else:
|
|
133
|
-
k = 2
|
|
134
|
-
|
|
135
|
-
def __init__(self, a):
|
|
136
|
-
self.a = a
|
|
137
|
-
|
|
138
|
-
def unused(self):
|
|
139
|
-
pass
|
|
140
|
-
other = unused
|
|
141
|
-
|
|
142
|
-
class B(A):
|
|
143
|
-
|
|
144
|
-
def __init__(self):
|
|
145
|
-
A.__init__(self, 'b')
|
|
146
|
-
''')
|
|
147
|
-
err_test('class A:\n def a(self):\n a()', 'undef', 3, 'a')
|
|
148
|
-
err_test('class A:\n def a(self):\n pass\n def a(self):\n pass', 'dup-method', 4, 'a')
|
|
149
|
-
|
|
150
|
-
# Object literals
|
|
151
|
-
err_test('{"a":1, "a":2}', 'dup-key', 1, 'a')
|
|
152
|
-
|
|
153
|
-
# keyword arg values
|
|
154
|
-
ok_test('def f():\n a=1\n f(b=a)')
|
|
155
|
-
ok_test('def f():\n a={}\n f(**a)')
|
|
156
|
-
|
|
157
|
-
# with statement
|
|
158
|
-
ok_test('''
|
|
159
|
-
def f():
|
|
160
|
-
a = 1
|
|
161
|
-
with a as b:
|
|
162
|
-
b()
|
|
163
|
-
''')
|
|
164
|
-
err_test('with a:\n pass', 'undef', '1', 'a')
|
|
1
|
+
# vim:fileencoding=utf-8
|
|
2
|
+
# License: BSD
|
|
3
|
+
# Copyright: 2015, Kovid Goyal <kovid at kovidgoyal.net>
|
|
4
|
+
|
|
5
|
+
linter = require('../tools/lint.js')
|
|
6
|
+
|
|
7
|
+
def lint(code):
|
|
8
|
+
return linter.lint_code(code, {'filename':'<test>', 'report':def():
|
|
9
|
+
pass
|
|
10
|
+
})
|
|
11
|
+
|
|
12
|
+
def err_test(code, ident, line, name, other_line):
|
|
13
|
+
msgs = lint(code)
|
|
14
|
+
assrt.ok(len(msgs) > 0, 'failed to find error in: ' + code)
|
|
15
|
+
assrt.equal(len(msgs), 1, 'found ' + (len(msgs) - 1) + ' extra errors in: ' + code)
|
|
16
|
+
assrt.equal(msgs[0].ident, ident, 'incorrect ident: ' + msgs[0].ident + ' for: ' + code)
|
|
17
|
+
if line != undefined:
|
|
18
|
+
assrt.equal(msgs[0].start_line, line, 'incorrect line: ' + msgs[0].start_line + ' for: ' + code)
|
|
19
|
+
if name != undefined:
|
|
20
|
+
assrt.equal(msgs[0].name, name, 'incorrect name: ' + msgs[0].name + ' for: ' + code)
|
|
21
|
+
if other_line != undefined:
|
|
22
|
+
assrt.equal(msgs[0].other_line, other_line, 'incorrect other_line: ' + msgs[0].other_line + ' for: ' + code)
|
|
23
|
+
|
|
24
|
+
def ok_test(code):
|
|
25
|
+
msgs = lint(code)
|
|
26
|
+
assrt.equal(msgs.length, 0, 'Got unexpected msg: ' + (msgs[0] or {}).message + ' for code: ' + code)
|
|
27
|
+
|
|
28
|
+
# Imports
|
|
29
|
+
err_test('import foo', 'unused-import', 1, 'foo')
|
|
30
|
+
err_test('import foo.boo', 'unused-import', 1, 'foo')
|
|
31
|
+
err_test('import foo as boo', 'unused-import', 1, 'boo')
|
|
32
|
+
err_test('from x import foo', 'unused-import', 1, 'foo')
|
|
33
|
+
err_test('from x import foo as boo', 'unused-import', 1, 'boo')
|
|
34
|
+
ok_test('import foo\nfoo')
|
|
35
|
+
|
|
36
|
+
# Function arguments
|
|
37
|
+
ok_test('def f(a):\n return a')
|
|
38
|
+
ok_test('def f(a=1):\n return a')
|
|
39
|
+
ok_test('def f(*a):\n return a')
|
|
40
|
+
ok_test('def f(**a):\n return a')
|
|
41
|
+
ok_test('def f(a):\n return 1')
|
|
42
|
+
|
|
43
|
+
# Extended slices
|
|
44
|
+
ok_test('a = []; a[::2], a[1:-1]')
|
|
45
|
+
|
|
46
|
+
# Top level unused ignored
|
|
47
|
+
ok_test('a=1\ndef f():\n pass')
|
|
48
|
+
|
|
49
|
+
# Destructuring assignment
|
|
50
|
+
ok_test('def f():\n a, b = 1, 2; a, b')
|
|
51
|
+
ok_test('def f():\n a = 1; b, c = a, 2; return b, c')
|
|
52
|
+
ok_test('for x, (y, z) in [ [1, [2, 3]] ]:\n x + y + z')
|
|
53
|
+
err_test('def f():\n a, b = 1, 1; return a', 'unused-local', 2, 'b')
|
|
54
|
+
|
|
55
|
+
# Compound assignment
|
|
56
|
+
err_test('a += 1', 'undef', 1, 'a')
|
|
57
|
+
ok_test('def f():\n a = 1; a += 1')
|
|
58
|
+
|
|
59
|
+
# Unused bindings
|
|
60
|
+
err_test('def f():\n a=1', 'unused-local', 2, 'a')
|
|
61
|
+
err_test('def f():\n def a():\n pass', 'unused-local', 2, 'a')
|
|
62
|
+
|
|
63
|
+
# Undefined references
|
|
64
|
+
err_test('f()', 'undef', 1, 'f')
|
|
65
|
+
err_test('a', 'undef', 1, 'a')
|
|
66
|
+
err_test('def f():\n a=1; return a\na', 'undef', 3, 'a')
|
|
67
|
+
|
|
68
|
+
# Comprehensions
|
|
69
|
+
ok_test('[x for x in [1,2]]')
|
|
70
|
+
ok_test('[1 for x in [1,2] if x]')
|
|
71
|
+
ok_test('[1 for x in [1,2]]')
|
|
72
|
+
ok_test('def f():\n l=[1,2];[x for x in l]')
|
|
73
|
+
ok_test('def f():\n l=[1,2];{x:True for x in l}')
|
|
74
|
+
err_test('def f():\n [x for x in [1,2]]; return x', 'undef', 2, 'x')
|
|
75
|
+
|
|
76
|
+
# Loops
|
|
77
|
+
ok_test('def f():\n for x in "":\n pass\n return x')
|
|
78
|
+
ok_test('def f():\n for x in "":\n x += 1\n')
|
|
79
|
+
ok_test('def f():\n for x, y in "":\n pass\n return x, y')
|
|
80
|
+
ok_test('for v"var i = 0; i < 1; i++":\n print(i)')
|
|
81
|
+
err_test('def f():\n a = 1\n for a in "":\n a', 'loop-shadowed', 3, 'a', 2)
|
|
82
|
+
|
|
83
|
+
# Semi-colons
|
|
84
|
+
err_test('a=1;;a', 'extra-semicolon', 1, ';')
|
|
85
|
+
err_test('a=1;', 'eol-semicolon', 1, ';')
|
|
86
|
+
|
|
87
|
+
# Builtins
|
|
88
|
+
for k in 'String Symbol this self window Map arguments print len range dir undefined'.split(' '):
|
|
89
|
+
ok_test(k)
|
|
90
|
+
|
|
91
|
+
# noqa
|
|
92
|
+
ok_test('f() # noqa')
|
|
93
|
+
ok_test('f() # noqa:undef')
|
|
94
|
+
err_test('f() # noqa:xxx', 'undef')
|
|
95
|
+
|
|
96
|
+
# Named func in branch
|
|
97
|
+
err_test('if 1:\n def f():\n pass', 'func-in-branch', 2, 'f')
|
|
98
|
+
err_test('if 1:\n pass\nelse:\n def f():\n pass', 'func-in-branch', 4, 'f')
|
|
99
|
+
err_test('try:\n def f():\n pass\nexcept:\n pass', 'func-in-branch', 2, 'f')
|
|
100
|
+
ok_test('if 1:\n a = def():\n pass')
|
|
101
|
+
|
|
102
|
+
# Syntax errors
|
|
103
|
+
err_test('def f(:\n pass', 'syntax-err', 1)
|
|
104
|
+
|
|
105
|
+
# Functions
|
|
106
|
+
ok_test('def f():\n pass\nf()')
|
|
107
|
+
|
|
108
|
+
# Non-locals
|
|
109
|
+
err_test('def a():\n x = 1\n def b():\n nonlocal x\n b()', 'unused-local', 2, 'x')
|
|
110
|
+
ok_test('def a():\n x = 1\n def b():\n nonlocal x\n x\n b()')
|
|
111
|
+
ok_test('def a():\n x = 1\n def b():\n nonlocal x\n x\n x = 2\n b()')
|
|
112
|
+
ok_test('def a():\n x = 1\n def ():\n nonlocal x\n x = 1\n x')
|
|
113
|
+
ok_test('nonlocal a\na()')
|
|
114
|
+
|
|
115
|
+
# Define after use
|
|
116
|
+
err_test('def g():\n f()\n f()\n def f():\n pass', 'def-after-use', 3, 'f')
|
|
117
|
+
|
|
118
|
+
# Decorators
|
|
119
|
+
ok_test('from x import y\n@y\ndef f():\n pass')
|
|
120
|
+
|
|
121
|
+
# try/except
|
|
122
|
+
ok_test('try:\n 1\nexcept Error as e:\n e')
|
|
123
|
+
|
|
124
|
+
# Classes
|
|
125
|
+
ok_test('''
|
|
126
|
+
class A:
|
|
127
|
+
|
|
128
|
+
h = j = 1
|
|
129
|
+
x = h + j
|
|
130
|
+
if True:
|
|
131
|
+
k = 1
|
|
132
|
+
else:
|
|
133
|
+
k = 2
|
|
134
|
+
|
|
135
|
+
def __init__(self, a):
|
|
136
|
+
self.a = a
|
|
137
|
+
|
|
138
|
+
def unused(self):
|
|
139
|
+
pass
|
|
140
|
+
other = unused
|
|
141
|
+
|
|
142
|
+
class B(A):
|
|
143
|
+
|
|
144
|
+
def __init__(self):
|
|
145
|
+
A.__init__(self, 'b')
|
|
146
|
+
''')
|
|
147
|
+
err_test('class A:\n def a(self):\n a()', 'undef', 3, 'a')
|
|
148
|
+
err_test('class A:\n def a(self):\n pass\n def a(self):\n pass', 'dup-method', 4, 'a')
|
|
149
|
+
|
|
150
|
+
# Object literals
|
|
151
|
+
err_test('{"a":1, "a":2}', 'dup-key', 1, 'a')
|
|
152
|
+
|
|
153
|
+
# keyword arg values
|
|
154
|
+
ok_test('def f():\n a=1\n f(b=a)')
|
|
155
|
+
ok_test('def f():\n a={}\n f(**a)')
|
|
156
|
+
|
|
157
|
+
# with statement
|
|
158
|
+
ok_test('''
|
|
159
|
+
def f():
|
|
160
|
+
a = 1
|
|
161
|
+
with a as b:
|
|
162
|
+
b()
|
|
163
|
+
''')
|
|
164
|
+
err_test('with a:\n pass', 'undef', '1', 'a')
|