rapydscript-ns 0.9.2 → 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.
Files changed (151) hide show
  1. package/.agignore +1 -1
  2. package/.github/workflows/ci.yml +38 -38
  3. package/=template.pyj +5 -5
  4. package/CHANGELOG.md +19 -0
  5. package/HACKING.md +103 -103
  6. package/LICENSE +24 -24
  7. package/PYTHON_GAPS.md +420 -0
  8. package/README.md +153 -29
  9. package/TODO.md +16 -118
  10. package/add-toc-to-readme +2 -2
  11. package/bin/export +75 -75
  12. package/bin/rapydscript +70 -70
  13. package/bin/web-repl-export +102 -102
  14. package/build +2 -2
  15. package/language-service/index.js +237 -8
  16. package/memory/project_string_impl.md +43 -0
  17. package/package.json +1 -1
  18. package/publish.py +37 -37
  19. package/release/baselib-plain-pretty.js +248 -38
  20. package/release/baselib-plain-ugly.js +8 -8
  21. package/release/compiler.js +778 -277
  22. package/release/signatures.json +30 -30
  23. package/session.vim +4 -4
  24. package/setup.cfg +2 -2
  25. package/src/ast.pyj +4 -1
  26. package/src/baselib-builtins.pyj +56 -2
  27. package/src/baselib-containers.pyj +2 -0
  28. package/src/baselib-errors.pyj +7 -3
  29. package/src/baselib-internal.pyj +51 -6
  30. package/src/baselib-str.pyj +5 -3
  31. package/src/compiler.pyj +36 -36
  32. package/src/errors.pyj +30 -30
  33. package/src/lib/aes.pyj +646 -646
  34. package/src/lib/asyncio.pyj +534 -0
  35. package/src/lib/base64.pyj +399 -0
  36. package/src/lib/bisect.pyj +73 -0
  37. package/src/lib/collections.pyj +1 -1
  38. package/src/lib/copy.pyj +120 -120
  39. package/src/lib/csv.pyj +494 -0
  40. package/src/lib/elementmaker.pyj +83 -83
  41. package/src/lib/encodings.pyj +126 -126
  42. package/src/lib/gettext.pyj +569 -569
  43. package/src/lib/heapq.pyj +98 -0
  44. package/src/lib/html.pyj +382 -0
  45. package/src/lib/http/__init__.pyj +98 -0
  46. package/src/lib/http/client.pyj +304 -0
  47. package/src/lib/http/cookies.pyj +236 -0
  48. package/src/lib/itertools.pyj +580 -580
  49. package/src/lib/logging.pyj +672 -0
  50. package/src/lib/math.pyj +193 -193
  51. package/src/lib/operator.pyj +11 -11
  52. package/src/lib/pythonize.pyj +20 -20
  53. package/src/lib/random.pyj +118 -118
  54. package/src/lib/react.pyj +74 -74
  55. package/src/lib/string.pyj +357 -0
  56. package/src/lib/textwrap.pyj +329 -0
  57. package/src/lib/traceback.pyj +63 -63
  58. package/src/lib/urllib/__init__.pyj +14 -0
  59. package/src/lib/urllib/error.pyj +66 -0
  60. package/src/lib/urllib/parse.pyj +475 -0
  61. package/src/lib/urllib/request.pyj +86 -0
  62. package/src/lib/uuid.pyj +77 -77
  63. package/src/monaco-language-service/analyzer.js +5 -2
  64. package/src/monaco-language-service/completions.js +26 -0
  65. package/src/monaco-language-service/diagnostics.js +202 -3
  66. package/src/monaco-language-service/dts.js +550 -550
  67. package/src/monaco-language-service/scope.js +1 -0
  68. package/src/output/comments.pyj +45 -45
  69. package/src/output/exceptions.pyj +201 -201
  70. package/src/output/functions.pyj +152 -6
  71. package/src/output/jsx.pyj +164 -164
  72. package/src/output/loops.pyj +17 -2
  73. package/src/output/modules.pyj +1 -1
  74. package/src/output/operators.pyj +15 -0
  75. package/src/output/stream.pyj +0 -1
  76. package/src/output/treeshake.pyj +182 -182
  77. package/src/output/utils.pyj +72 -72
  78. package/src/parse.pyj +80 -17
  79. package/src/string_interpolation.pyj +72 -72
  80. package/src/tokenizer.pyj +1 -1
  81. package/src/unicode_aliases.pyj +576 -576
  82. package/src/utils.pyj +192 -192
  83. package/test/_import_one.pyj +37 -37
  84. package/test/_import_two/__init__.pyj +11 -11
  85. package/test/_import_two/level2/deep.pyj +4 -4
  86. package/test/_import_two/other.pyj +6 -6
  87. package/test/_import_two/sub.pyj +13 -13
  88. package/test/aes_vectors.pyj +421 -421
  89. package/test/annotations.pyj +80 -80
  90. package/test/async_generators.pyj +144 -0
  91. package/test/asyncio.pyj +307 -0
  92. package/test/base64.pyj +202 -0
  93. package/test/bisect.pyj +178 -0
  94. package/test/csv.pyj +405 -0
  95. package/test/decorators.pyj +77 -77
  96. package/test/docstrings.pyj +39 -39
  97. package/test/elementmaker_test.pyj +45 -45
  98. package/test/float_special.pyj +64 -0
  99. package/test/functions.pyj +151 -151
  100. package/test/generators.pyj +41 -41
  101. package/test/generic.pyj +370 -370
  102. package/test/heapq.pyj +174 -0
  103. package/test/html.pyj +212 -0
  104. package/test/http.pyj +259 -0
  105. package/test/imports.pyj +79 -72
  106. package/test/internationalization.pyj +73 -73
  107. package/test/lint.pyj +164 -164
  108. package/test/logging.pyj +356 -0
  109. package/test/long.pyj +130 -0
  110. package/test/loops.pyj +85 -85
  111. package/test/numpy.pyj +734 -734
  112. package/test/parenthesized_with.pyj +141 -0
  113. package/test/python_compat.pyj +3 -5
  114. package/test/python_modulo.pyj +76 -0
  115. package/test/python_modulo_off.pyj +21 -0
  116. package/test/repl.pyj +121 -121
  117. package/test/scoped_flags.pyj +76 -76
  118. package/test/str.pyj +14 -0
  119. package/test/string.pyj +245 -0
  120. package/test/textwrap.pyj +172 -0
  121. package/test/type_display.pyj +48 -0
  122. package/test/type_enforcement.pyj +164 -0
  123. package/test/unit/index.js +14 -6
  124. package/test/unit/language-service-completions.js +119 -0
  125. package/test/unit/language-service-dts.js +543 -543
  126. package/test/unit/language-service-hover.js +455 -455
  127. package/test/unit/language-service-scope.js +32 -0
  128. package/test/unit/language-service.js +127 -3
  129. package/test/unit/run-language-service.js +17 -3
  130. package/test/unit/web-repl.js +2094 -29
  131. package/test/urllib.pyj +193 -0
  132. package/tools/compile.js +1 -1
  133. package/tools/compiler.d.ts +367 -367
  134. package/tools/completer.js +131 -131
  135. package/tools/embedded_compiler.js +7 -7
  136. package/tools/gettext.js +185 -185
  137. package/tools/ini.js +65 -65
  138. package/tools/msgfmt.js +187 -187
  139. package/tools/repl.js +223 -223
  140. package/tools/test.js +118 -118
  141. package/tools/utils.js +128 -128
  142. package/tools/web_repl.js +95 -95
  143. package/try +41 -41
  144. package/web-repl/env.js +196 -196
  145. package/web-repl/index.html +163 -163
  146. package/web-repl/main.js +1 -1
  147. package/web-repl/prism.css +139 -139
  148. package/web-repl/prism.js +113 -113
  149. package/web-repl/rapydscript.js +224 -224
  150. package/web-repl/sha1.js +25 -25
  151. package/test/omit_function_metadata.pyj +0 -20
package/test/imports.pyj CHANGED
@@ -1,72 +1,79 @@
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
+ # Python-style multi-line parenthesized import with trailing comma
7
+ from _import_one import (
8
+ toplevel_var,
9
+ toplevel_func as tf,
10
+ TopLevel,
11
+ )
12
+
13
+ def AClass(x):
14
+ return this
15
+
16
+ eq = assrt.equal
17
+ # Test import of top-level variables and callables
18
+ eq(toplevel_var, 'foo')
19
+ eq(tf('x'), 'xtoplevel')
20
+ eq(toplevel_var2, 'foo2')
21
+ eq(toplevel_func2('x'), 'xtoplevel2')
22
+ eq(false_var, undefined)
23
+ eq(test_other, 'other')
24
+
25
+ # Test import of top-level vars in a conditional
26
+ eq('true', true_var)
27
+
28
+ # Test plain imports
29
+ import _import_one
30
+ eq(_import_one.toplevel_var, toplevel_var)
31
+ eq(_import_one.toplevel_func('x'), tf('x'))
32
+
33
+ # Test recognition of imported classes
34
+ tl = TopLevel('1')
35
+ eq(tl.a, '1')
36
+ tl2 = TL2('x')
37
+ eq(tl2.a, 'x')
38
+
39
+ # Test access to submodules via plain imports
40
+ import _import_two.sub, _import_two.sub as ts
41
+ eq('sub', _import_two.sub.sub_var)
42
+ eq('sub', ts.sub_var)
43
+ eq('sub', _import_two.sub.sub_func())
44
+
45
+ # Test deep import
46
+ from _import_two.level2.deep import deep_var
47
+ eq('deep', deep_var)
48
+
49
+ # Test that class accessed via plain import is
50
+ # recognized
51
+ s = _import_two.sub.Sub(1)
52
+ eq(s.a, 1)
53
+ s2 = ts.Sub(1)
54
+ eq(s2.a, 1)
55
+
56
+
57
+ # Test that a class imported into an inner scope is not recognized as a class
58
+ # outside that scope
59
+ def inner():
60
+ from _import_one import AClass
61
+ a = AClass(1)
62
+ eq(a.a, 1)
63
+
64
+ inner()
65
+ b = AClass(1)
66
+ eq(b, this)
67
+
68
+ # Test global symbol declared in other module
69
+ eq(GLOBAL_SYMBOL, 'i am global')
70
+
71
+ # Import errors happen during parsing, so we cannot test them directly as they would
72
+ # prevent this file from being parsed.
73
+
74
+ assrt.throws(def():
75
+ RapydScript.parse('from _import_one import not_exported', {'basedir':test_path}).body[0]
76
+ , /not exported/)
77
+ assrt.throws(def():
78
+ RapydScript.parse('import xxxx', {'basedir':test_path}).body[0]
79
+ , /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')