rapydscript-ns 0.8.4 → 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.
Files changed (141) 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 +26 -0
  5. package/HACKING.md +103 -103
  6. package/LICENSE +24 -24
  7. package/README.md +716 -169
  8. package/TODO.md +7 -2
  9. package/add-toc-to-readme +2 -2
  10. package/bin/export +75 -75
  11. package/bin/rapydscript +70 -70
  12. package/bin/web-repl-export +102 -102
  13. package/build +2 -2
  14. package/language-service/index.js +36 -27
  15. package/package.json +1 -1
  16. package/publish.py +37 -37
  17. package/release/baselib-plain-pretty.js +2358 -168
  18. package/release/baselib-plain-ugly.js +73 -3
  19. package/release/compiler.js +6283 -3093
  20. package/release/signatures.json +31 -30
  21. package/session.vim +4 -4
  22. package/setup.cfg +2 -2
  23. package/src/ast.pyj +1 -0
  24. package/src/baselib-builtins.pyj +340 -2
  25. package/src/baselib-bytes.pyj +664 -0
  26. package/src/baselib-errors.pyj +1 -1
  27. package/src/baselib-internal.pyj +267 -60
  28. package/src/baselib-itertools.pyj +110 -97
  29. package/src/baselib-str.pyj +22 -4
  30. package/src/compiler.pyj +36 -36
  31. package/src/errors.pyj +30 -30
  32. package/src/lib/abc.pyj +317 -0
  33. package/src/lib/aes.pyj +646 -646
  34. package/src/lib/contextlib.pyj +379 -0
  35. package/src/lib/copy.pyj +120 -120
  36. package/src/lib/dataclasses.pyj +532 -0
  37. package/src/lib/datetime.pyj +712 -0
  38. package/src/lib/elementmaker.pyj +83 -83
  39. package/src/lib/encodings.pyj +126 -126
  40. package/src/lib/enum.pyj +125 -0
  41. package/src/lib/gettext.pyj +569 -569
  42. package/src/lib/io.pyj +500 -0
  43. package/src/lib/itertools.pyj +580 -580
  44. package/src/lib/json.pyj +227 -0
  45. package/src/lib/math.pyj +193 -193
  46. package/src/lib/operator.pyj +11 -11
  47. package/src/lib/pythonize.pyj +20 -20
  48. package/src/lib/random.pyj +118 -118
  49. package/src/lib/re.pyj +504 -470
  50. package/src/lib/react.pyj +74 -74
  51. package/src/lib/traceback.pyj +63 -63
  52. package/src/lib/typing.pyj +577 -0
  53. package/src/lib/uuid.pyj +77 -77
  54. package/src/monaco-language-service/builtins.js +14 -4
  55. package/src/monaco-language-service/diagnostics.js +19 -20
  56. package/src/monaco-language-service/dts.js +550 -550
  57. package/src/output/classes.pyj +62 -26
  58. package/src/output/comments.pyj +45 -45
  59. package/src/output/exceptions.pyj +201 -201
  60. package/src/output/functions.pyj +78 -5
  61. package/src/output/jsx.pyj +164 -164
  62. package/src/output/loops.pyj +5 -2
  63. package/src/output/operators.pyj +100 -34
  64. package/src/output/treeshake.pyj +182 -182
  65. package/src/output/utils.pyj +72 -72
  66. package/src/parse.pyj +80 -16
  67. package/src/string_interpolation.pyj +72 -72
  68. package/src/tokenizer.pyj +10 -5
  69. package/src/unicode_aliases.pyj +576 -576
  70. package/src/utils.pyj +192 -192
  71. package/test/_import_one.pyj +37 -37
  72. package/test/_import_two/__init__.pyj +11 -11
  73. package/test/_import_two/level2/deep.pyj +4 -4
  74. package/test/_import_two/other.pyj +6 -6
  75. package/test/_import_two/sub.pyj +13 -13
  76. package/test/abc.pyj +291 -0
  77. package/test/aes_vectors.pyj +421 -421
  78. package/test/annotations.pyj +80 -80
  79. package/test/arithmetic_nostrict.pyj +88 -0
  80. package/test/arithmetic_types.pyj +169 -0
  81. package/test/baselib.pyj +91 -0
  82. package/test/bytes.pyj +467 -0
  83. package/test/classes.pyj +1 -0
  84. package/test/comparison_ops.pyj +173 -0
  85. package/test/contextlib.pyj +362 -0
  86. package/test/dataclasses.pyj +253 -0
  87. package/test/datetime.pyj +500 -0
  88. package/test/debugger_stmt.pyj +41 -0
  89. package/test/decorators.pyj +77 -77
  90. package/test/docstrings.pyj +39 -39
  91. package/test/elementmaker_test.pyj +45 -45
  92. package/test/enum.pyj +134 -0
  93. package/test/eval_exec.pyj +56 -0
  94. package/test/format.pyj +148 -0
  95. package/test/functions.pyj +151 -151
  96. package/test/generators.pyj +41 -41
  97. package/test/generic.pyj +370 -370
  98. package/test/imports.pyj +72 -72
  99. package/test/internationalization.pyj +73 -73
  100. package/test/io.pyj +316 -0
  101. package/test/json.pyj +196 -0
  102. package/test/lint.pyj +164 -164
  103. package/test/loops.pyj +85 -85
  104. package/test/numpy.pyj +734 -734
  105. package/test/object.pyj +64 -0
  106. package/test/omit_function_metadata.pyj +20 -20
  107. package/test/python_compat.pyj +17 -15
  108. package/test/python_features.pyj +70 -15
  109. package/test/regexp.pyj +83 -55
  110. package/test/repl.pyj +121 -121
  111. package/test/scoped_flags.pyj +76 -76
  112. package/test/tuples.pyj +96 -0
  113. package/test/typing.pyj +469 -0
  114. package/test/unit/index.js +116 -7
  115. package/test/unit/language-service-dts.js +543 -543
  116. package/test/unit/language-service-hover.js +455 -455
  117. package/test/unit/language-service.js +84 -0
  118. package/test/unit/web-repl.js +1337 -1
  119. package/test/vars_locals_globals.pyj +94 -0
  120. package/tools/cli.js +558 -547
  121. package/tools/compile.js +224 -219
  122. package/tools/completer.js +131 -131
  123. package/tools/embedded_compiler.js +262 -251
  124. package/tools/gettext.js +185 -185
  125. package/tools/ini.js +65 -65
  126. package/tools/lint.js +16 -19
  127. package/tools/msgfmt.js +187 -187
  128. package/tools/repl.js +223 -223
  129. package/tools/test.js +118 -118
  130. package/tools/utils.js +128 -128
  131. package/tools/web_repl.js +95 -95
  132. package/try +41 -41
  133. package/web-repl/env.js +196 -196
  134. package/web-repl/index.html +163 -163
  135. package/web-repl/main.js +252 -252
  136. package/web-repl/prism.css +139 -139
  137. package/web-repl/prism.js +113 -113
  138. package/web-repl/rapydscript.js +224 -224
  139. package/web-repl/sha1.js +25 -25
  140. package/PYTHON_DIFFERENCES_REPORT.md +0 -291
  141. package/PYTHON_FEATURE_COVERAGE.md +0 -200
package/test/json.pyj ADDED
@@ -0,0 +1,196 @@
1
+ # globals: assrt
2
+ # vim:fileencoding=utf-8
3
+ #
4
+ # json.pyj
5
+ # Tests for the json standard library module.
6
+
7
+ from json import dumps, loads, dump, load, JSONDecodeError
8
+
9
+ ae = assrt.equal
10
+ ade = assrt.deepEqual
11
+ ok = assrt.ok
12
+ throws = assrt.throws
13
+
14
+ # ── 1. dumps — basic types ────────────────────────────────────────────────────
15
+
16
+ ae(dumps(None), 'null')
17
+ ae(dumps(True), 'true')
18
+ ae(dumps(False), 'false')
19
+ ae(dumps(42), '42')
20
+ ae(dumps(3.14), '3.14')
21
+ ae(dumps('hello'), '"hello"')
22
+ ae(dumps('with "quotes"'), '"with \\"quotes\\""')
23
+
24
+ # ── 2. dumps — collections ────────────────────────────────────────────────────
25
+
26
+ ae(dumps([]), '[]')
27
+ ae(dumps([1, 2, 3]), '[1,2,3]')
28
+ ae(dumps({}), '{}')
29
+
30
+ # Object with single key (no ordering ambiguity)
31
+ _d1 = dumps({'a': 1})
32
+ ae(_d1, '{"a":1}')
33
+
34
+ # ── 3. dumps — indent ─────────────────────────────────────────────────────────
35
+
36
+ _pretty = dumps([1, 2], indent=2)
37
+ ok(_pretty.indexOf('\n') >= 0, 'indented output should contain newlines')
38
+ ok(_pretty.indexOf(' ') >= 0, 'indented output should contain spaces')
39
+
40
+ # ── 4. dumps — sort_keys ──────────────────────────────────────────────────────
41
+
42
+ _sk = dumps({'b': 2, 'a': 1}, sort_keys=True)
43
+ ae(_sk, '{"a":1,"b":2}')
44
+
45
+ # Nested sort_keys
46
+ _sk2 = dumps({'z': {'y': 3, 'x': 4}, 'a': 1}, sort_keys=True)
47
+ ae(_sk2, '{"a":1,"z":{"x":4,"y":3}}')
48
+
49
+ # ── 5. dumps — separators ─────────────────────────────────────────────────────
50
+
51
+ # Compact form used in Python: separators=(',', ':')
52
+ _compact = dumps({'a': 1, 'b': 2}, sort_keys=True, separators=(',', ':'))
53
+ ae(_compact, '{"a":1,"b":2}')
54
+
55
+ # ── 6. dumps — default callback ───────────────────────────────────────────────
56
+
57
+ class _Point:
58
+ def __init__(self, x, y):
59
+ self.x = x
60
+ self.y = y
61
+
62
+ def _point_default(obj):
63
+ if isinstance(obj, _Point):
64
+ return {'x': obj.x, 'y': obj.y}
65
+ raise TypeError('not serializable')
66
+
67
+ _pt_json = dumps(_Point(3, 4), dflt=_point_default)
68
+ _pt_obj = loads(_pt_json)
69
+ ae(_pt_obj.x, 3)
70
+ ae(_pt_obj.y, 4)
71
+
72
+ # ── 7. dumps — allow_nan ──────────────────────────────────────────────────────
73
+
74
+ _nan_raised = False
75
+ try:
76
+ dumps(v'NaN')
77
+ except ValueError:
78
+ _nan_raised = True
79
+ ok(_nan_raised, 'dumps(NaN) should raise ValueError by default')
80
+
81
+ _inf_raised = False
82
+ try:
83
+ dumps(v'Infinity')
84
+ except ValueError:
85
+ _inf_raised = True
86
+ ok(_inf_raised, 'dumps(Infinity) should raise ValueError by default')
87
+
88
+ # allow_nan=True should not raise
89
+ _nan_str = dumps(v'NaN', allow_nan=True)
90
+ ok(_nan_str.length > 0, 'allow_nan=True should return a string')
91
+
92
+ # ── 8. loads — basic types ────────────────────────────────────────────────────
93
+
94
+ ae(loads('null'), None)
95
+ ae(loads('true'), True)
96
+ ae(loads('false'), False)
97
+ ae(loads('42'), 42)
98
+ ae(loads('3.14'), 3.14)
99
+ ae(loads('"hello"'), 'hello')
100
+
101
+ # ── 9. loads — collections ────────────────────────────────────────────────────
102
+
103
+ _arr = loads('[1, 2, 3]')
104
+ ade(_arr, [1, 2, 3])
105
+
106
+ _obj = loads('{"a": 1, "b": 2}')
107
+ ae(_obj.a, 1)
108
+ ae(_obj.b, 2)
109
+
110
+ # ── 10. loads — nested structures ─────────────────────────────────────────────
111
+
112
+ _nested = loads('{"users": [{"name": "Alice", "age": 30}, {"name": "Bob", "age": 25}]}')
113
+ ae(_nested.users.length, 2)
114
+ ae(_nested.users[0].name, 'Alice')
115
+ ae(_nested.users[1].age, 25)
116
+
117
+ # ── 11. loads — object_hook ───────────────────────────────────────────────────
118
+
119
+ class _NameAge:
120
+ def __init__(self, d):
121
+ self.name = d.name if d.name else ''
122
+ self.age = d.age if d.age else 0
123
+
124
+ def _obj_hook(d):
125
+ if d.name is not None:
126
+ return _NameAge(d)
127
+ return d
128
+
129
+ _h = loads('{"name": "Alice", "age": 30}', object_hook=_obj_hook)
130
+ ok(isinstance(_h, _NameAge), 'object_hook should produce a _NameAge instance')
131
+ ae(_h.name, 'Alice')
132
+ ae(_h.age, 30)
133
+
134
+ # ── 12. loads — object_pairs_hook ─────────────────────────────────────────────
135
+
136
+ _pairs_result = []
137
+ def _pairs_hook(pairs):
138
+ _pairs_result.push(pairs.length)
139
+ return pairs
140
+
141
+ loads('{"x": 1, "y": 2}', object_pairs_hook=_pairs_hook)
142
+ ae(_pairs_result[0], 2, 'object_pairs_hook should receive 2 pairs')
143
+
144
+ # ── 13. loads — parse_float / parse_int ───────────────────────────────────────
145
+
146
+ _floats = []
147
+ def _capture_float(s):
148
+ _floats.push(s)
149
+ return float(s)
150
+
151
+ loads('3.14', parse_float=_capture_float)
152
+ ae(_floats.length, 1)
153
+ ae(_floats[0], '3.14')
154
+
155
+ _ints = []
156
+ def _capture_int(s):
157
+ _ints.push(s)
158
+ return int(s)
159
+
160
+ loads('42', parse_int=_capture_int)
161
+ ae(_ints.length, 1)
162
+ ae(_ints[0], '42')
163
+
164
+ # ── 14. loads — JSONDecodeError ───────────────────────────────────────────────
165
+
166
+ _err_raised = False
167
+ try:
168
+ loads('{invalid json}')
169
+ except JSONDecodeError as e:
170
+ _err_raised = True
171
+ ok(isinstance(e, JSONDecodeError), 'should be JSONDecodeError')
172
+ ok(isinstance(e, ValueError), 'JSONDecodeError should be a ValueError')
173
+ ok(_err_raised, 'invalid JSON should raise JSONDecodeError')
174
+
175
+ # ── 15. round-trip ────────────────────────────────────────────────────────────
176
+
177
+ _original = {'name': 'test', 'values': [1, 2, 3], 'nested': {'ok': True}}
178
+ _rt = loads(dumps(_original))
179
+ ae(_rt.name, _original.name)
180
+ ade(_rt.values, _original.values)
181
+ ae(_rt.nested.ok, _original.nested.ok)
182
+
183
+ # ── 16. dump / load via file-like object ──────────────────────────────────────
184
+
185
+ class _StringIO:
186
+ def __init__(self):
187
+ self._buf = ''
188
+ def write(self, s):
189
+ self._buf += s
190
+ def read(self):
191
+ return self._buf
192
+
193
+ _sio = _StringIO()
194
+ dump({'key': 'value'}, _sio)
195
+ _loaded = load(_sio)
196
+ ae(_loaded.key, 'value')
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')