rapydscript-ng 0.8.2 → 0.8.4

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 (60) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/bin/build.ts +29 -0
  3. package/local-agent.md +4 -0
  4. package/package.json +1 -1
  5. package/release/baselib-plain-pretty.js +85 -61
  6. package/release/baselib-plain-ugly.js +3 -3
  7. package/release/compiler.js +9661 -9540
  8. package/release/signatures.json +26 -26
  9. package/src/ast.pyj +169 -64
  10. package/src/baselib-builtins.pyj +35 -14
  11. package/src/baselib-containers.pyj +70 -40
  12. package/src/baselib-internal.pyj +20 -8
  13. package/src/baselib-itertools.pyj +6 -2
  14. package/src/baselib-str.pyj +74 -28
  15. package/src/errors.pyj +4 -1
  16. package/src/lib/aes.pyj +664 -35
  17. package/src/lib/elementmaker.pyj +105 -13
  18. package/src/lib/encodings.pyj +31 -7
  19. package/src/lib/gettext.pyj +6 -3
  20. package/src/lib/math.pyj +38 -22
  21. package/src/lib/pythonize.pyj +5 -3
  22. package/src/lib/random.pyj +13 -5
  23. package/src/lib/re.pyj +81 -18
  24. package/src/lib/traceback.pyj +42 -10
  25. package/src/lib/uuid.pyj +2 -1
  26. package/src/output/classes.pyj +70 -26
  27. package/src/output/codegen.pyj +92 -20
  28. package/src/output/comments.pyj +11 -4
  29. package/src/output/exceptions.pyj +17 -4
  30. package/src/output/functions.pyj +145 -26
  31. package/src/output/literals.pyj +7 -2
  32. package/src/output/loops.pyj +79 -23
  33. package/src/output/modules.pyj +41 -12
  34. package/src/output/operators.pyj +154 -31
  35. package/src/output/statements.pyj +38 -10
  36. package/src/output/stream.pyj +43 -12
  37. package/src/output/utils.pyj +10 -3
  38. package/src/parse.pyj +740 -259
  39. package/src/string_interpolation.pyj +4 -1
  40. package/src/tokenizer.pyj +314 -57
  41. package/src/unicode_aliases.pyj +4 -2
  42. package/src/utils.pyj +19 -5
  43. package/test/functions.pyj +8 -0
  44. package/test/generic.pyj +9 -0
  45. package/test/lsp.pyj +16 -0
  46. package/test/str.pyj +10 -0
  47. package/tools/cli.mjs +4 -3
  48. package/tools/compile.mjs +9 -3
  49. package/tools/compiler.mjs +0 -6
  50. package/tools/fmt.mjs +41 -2
  51. package/tools/lint-worker.mjs +107 -0
  52. package/tools/lint.mjs +134 -8
  53. package/tools/lsp.mjs +11 -1
  54. package/tree-sitter/grammar.js +27 -6
  55. package/tree-sitter/queries/highlights.scm +10 -0
  56. package/tree-sitter/src/grammar.json +130 -5
  57. package/tree-sitter/src/node-types.json +73 -0
  58. package/tree-sitter/src/parser.c +119589 -114993
  59. package/tree-sitter/src/scanner.c +275 -17
  60. package/tree-sitter/test/corpus/strings.txt +41 -5
package/src/parse.pyj CHANGED
@@ -1,33 +1,110 @@
1
1
  # vim:fileencoding=utf-8
2
2
  # License: BSD Copyright: 2016, Kovid Goyal <kovid at kovidgoyal.net>
3
- # globals: readfile, writefile, stat_file, sha1sum, ast_from_json, ast_to_json, make_lazy_ast_module, decode_cache, encode_cache
3
+ # globals: readfile, writefile, stat_file, sha1sum, ast_from_json,
4
+ # globals: ast_to_json, make_lazy_ast_module, decode_cache, encode_cache
4
5
  from __python__ import hash_literals
5
6
 
6
7
  from ast import (
7
- AST_ArgsDef, AST_Array, AST_Assign, AST_Binary, AST_BlockStatement, AST_Break,
8
- AST_Call, AST_CallArg, AST_CallArgs, AST_Catch, AST_Class, AST_ClassCall, AST_Conditional,
9
- AST_Constant, AST_Continue, AST_DWLoop, AST_Debugger, AST_Decorator,
10
- AST_Definitions, AST_DictComprehension, AST_Directive, AST_Do, AST_Dot,
11
- AST_Else, AST_EmptyStatement, AST_Except, AST_ExpressiveObject, AST_False, AST_Finally,
12
- AST_ForIn, AST_ForJS, AST_Function, AST_GeneratorComprehension, AST_Hole,
13
- AST_If, AST_Import, AST_ImportedVar, AST_Imports, AST_ListComprehension,
14
- AST_Method, AST_New, AST_Null, AST_Number, AST_Object, AST_ObjectKeyVal,
15
- AST_PropAccess, AST_RegExp, AST_Return, AST_Scope, AST_Set,
16
- AST_SetComprehension, AST_SetItem, AST_Seq, AST_SimpleStatement, AST_Splice,
17
- AST_String, AST_Sub, AST_ItemAccess, AST_SymbolAlias,
18
- AST_SymbolCatch, AST_SymbolDefun, AST_SymbolFunarg,
19
- AST_SymbolLambda, AST_SymbolNonlocal, AST_SymbolRef, AST_SymbolVar, AST_This,
20
- AST_Throw, AST_Toplevel, AST_True, AST_Try, AST_UnaryPrefix,
21
- AST_Undefined, AST_Var, AST_VarDef, AST_Verbatim, AST_While, AST_With, AST_WithClause,
22
- AST_Yield, AST_Await, AST_Assert, AST_Existential, is_node_type, TreeWalker
8
+ AST_ArgsDef,
9
+ AST_Array,
10
+ AST_Assign,
11
+ AST_Binary,
12
+ AST_BlockStatement,
13
+ AST_Break,
14
+ AST_Call,
15
+ AST_CallArg,
16
+ AST_CallArgs,
17
+ AST_Catch,
18
+ AST_Class,
19
+ AST_ClassCall,
20
+ AST_Conditional,
21
+ AST_Constant,
22
+ AST_Continue,
23
+ AST_DWLoop,
24
+ AST_Debugger,
25
+ AST_Decorator,
26
+ AST_Definitions,
27
+ AST_DictComprehension,
28
+ AST_Directive,
29
+ AST_Do,
30
+ AST_Dot,
31
+ AST_Else,
32
+ AST_EmptyStatement,
33
+ AST_Except,
34
+ AST_ExpressiveObject,
35
+ AST_False,
36
+ AST_Finally,
37
+ AST_ForIn,
38
+ AST_ForJS,
39
+ AST_Function,
40
+ AST_GeneratorComprehension,
41
+ AST_Hole,
42
+ AST_If,
43
+ AST_Import,
44
+ AST_ImportedVar,
45
+ AST_Imports,
46
+ AST_ListComprehension,
47
+ AST_Method,
48
+ AST_New,
49
+ AST_Null,
50
+ AST_Number,
51
+ AST_Object,
52
+ AST_ObjectKeyVal,
53
+ AST_PropAccess,
54
+ AST_RegExp,
55
+ AST_Return,
56
+ AST_Scope,
57
+ AST_Set,
58
+ AST_SetComprehension,
59
+ AST_SetItem,
60
+ AST_Seq,
61
+ AST_SimpleStatement,
62
+ AST_Splice,
63
+ AST_String,
64
+ AST_Sub,
65
+ AST_ItemAccess,
66
+ AST_SymbolAlias,
67
+ AST_SymbolCatch,
68
+ AST_SymbolDefun,
69
+ AST_SymbolFunarg,
70
+ AST_SymbolLambda,
71
+ AST_SymbolNonlocal,
72
+ AST_SymbolRef,
73
+ AST_SymbolVar,
74
+ AST_This,
75
+ AST_Throw,
76
+ AST_Toplevel,
77
+ AST_True,
78
+ AST_Try,
79
+ AST_UnaryPrefix,
80
+ AST_Undefined,
81
+ AST_Var,
82
+ AST_VarDef,
83
+ AST_Verbatim,
84
+ AST_While,
85
+ AST_With,
86
+ AST_WithClause,
87
+ AST_Yield,
88
+ AST_Await,
89
+ AST_Assert,
90
+ AST_Existential,
91
+ is_node_type,
92
+ TreeWalker
23
93
  )
24
94
  from errors import SyntaxError, ImportError
25
95
  from tokenizer import tokenizer, is_token, RESERVED_WORDS
26
- from utils import make_predicate, array_to_hash, defaults, has_prop, cache_file_name
96
+ from utils import (
97
+ make_predicate, array_to_hash, defaults, has_prop, cache_file_name
98
+ )
27
99
 
28
100
 
29
101
  COMPILER_VERSION = '__COMPILER_VERSION__'
30
- PYTHON_FLAGS = {'dict_literals': True, 'overload_getitem': True, 'bound_methods': True, 'hash_literals': True}
102
+ PYTHON_FLAGS = {
103
+ 'dict_literals': True,
104
+ 'overload_getitem': True,
105
+ 'bound_methods': True,
106
+ 'hash_literals': True,
107
+ }
31
108
  CACHE_VERSION = 1
32
109
 
33
110
 
@@ -50,28 +127,19 @@ NATIVE_CLASSES = {
50
127
  'SyntaxError': {},
51
128
  'TypeError': {},
52
129
  'URIError': {},
53
- 'Object': {
54
- 'static': static_predicate(
55
- 'getOwnPropertyNames getOwnPropertyDescriptor getOwnPropertyDescriptors'
56
- ' getOwnPropertySymbols keys entries values create defineProperty'
57
- ' defineProperties getPrototypeOf setPrototypeOf assign'
58
- ' seal isSealed is preventExtensions isExtensible'
59
- ' freeze isFrozen'
60
- )
61
- },
62
- 'String': {
63
- 'static': static_predicate('fromCharCode')
64
- },
65
- 'Array': {
66
- 'static': static_predicate('isArray from of')
67
- },
130
+ 'Object': {'static': static_predicate(
131
+ 'getOwnPropertyNames getOwnPropertyDescriptor'
132
+ ' getOwnPropertyDescriptors'
133
+ ' getOwnPropertySymbols keys entries values create defineProperty'
134
+ ' defineProperties getPrototypeOf setPrototypeOf assign'
135
+ ' seal isSealed is preventExtensions isExtensible'
136
+ ' freeze isFrozen'
137
+ )},
138
+ 'String': {'static': static_predicate('fromCharCode')},
139
+ 'Array': {'static': static_predicate('isArray from of')},
68
140
  'Function': {},
69
- 'Date': {
70
- 'static': static_predicate('UTC now parse')
71
- },
72
- 'ArrayBuffer': {
73
- 'static': static_predicate('isView transfer')
74
- },
141
+ 'Date': {'static': static_predicate('UTC now parse')},
142
+ 'ArrayBuffer': {'static': static_predicate('isView transfer')},
75
143
  'DataView': {},
76
144
  'Float32Array': {},
77
145
  'Float64Array': {},
@@ -87,9 +155,7 @@ NATIVE_CLASSES = {
87
155
  'Proxy': {},
88
156
  'Set': {},
89
157
  'WeakSet': {},
90
- 'Promise': {
91
- 'static': static_predicate('all race reject resolve')
92
- },
158
+ 'Promise': {'static': static_predicate('all race reject resolve')},
93
159
  'WebSocket': {},
94
160
  'XMLHttpRequest': {},
95
161
  'TextEncoder': {},
@@ -141,7 +207,9 @@ PRECEDENCE = (def (a, ret):
141
207
 
142
208
  STATEMENTS_WITH_LABELS = array_to_hash(['for', 'do', 'while', 'switch'])
143
209
 
144
- ATOMIC_START_TOKEN = array_to_hash(['atom', 'num', 'string', 'regexp', 'name', 'js'])
210
+ ATOMIC_START_TOKEN = array_to_hash([
211
+ 'atom', 'num', 'string', 'regexp', 'name', 'js'
212
+ ])
145
213
 
146
214
  compile_time_decorators = ['staticmethod', 'external', 'property']
147
215
 
@@ -164,7 +232,10 @@ def has_setter_decorator(decorators, name):
164
232
  remove = v'[]'
165
233
  for v'var i = 0; i < decorators.length; i++':
166
234
  s = decorators[i]
167
- if is_node_type(s, AST_Dot) and is_node_type(s.expression, AST_SymbolRef) and s.expression.name is name and s.property is 'setter':
235
+ if is_node_type(s, AST_Dot) and is_node_type(
236
+ s.expression,
237
+ AST_SymbolRef
238
+ ) and s.expression.name is name and s.property is 'setter':
168
239
  remove.push(i)
169
240
  if remove.length:
170
241
  remove.reverse()
@@ -175,7 +246,11 @@ def has_setter_decorator(decorators, name):
175
246
 
176
247
 
177
248
  # -----[ Parser ]-----
178
- def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_ids, imported_modules, importing_modules, options):
249
+ def create_parser_ctx(
250
+ S, import_dirs, module_id, baselib_items,
251
+ imported_module_ids, imported_modules,
252
+ importing_modules, options
253
+ ):
179
254
  def next():
180
255
  S.prev = S.token
181
256
  if S.peeked.length:
@@ -197,10 +272,17 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
197
272
  return S.prev
198
273
 
199
274
  def croak(msg, line, col, pos, is_eof):
200
- # note: undefined means nothing was passed in, None/null means a null value was passed in
275
+ # note: undefined means nothing was passed in,
276
+ # None/null means a null value was passed in
201
277
  ctx = S.input.context()
202
- raise new SyntaxError(msg, ctx.filename, (line if line is not undefined else ctx.tokline),
203
- (col if col is not undefined else ctx.tokcol), (pos if pos is not undefined else ctx.tokpos), is_eof)
278
+ raise new SyntaxError(
279
+ msg,
280
+ ctx.filename,
281
+ (line if line is not undefined else ctx.tokline),
282
+ (col if col is not undefined else ctx.tokcol),
283
+ (pos if pos is not undefined else ctx.tokpos),
284
+ is_eof
285
+ )
204
286
 
205
287
  def token_error(token, msg):
206
288
  is_eof = token.type is 'eof'
@@ -209,9 +291,13 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
209
291
  def unexpected(token):
210
292
  if token is undefined:
211
293
  token = S.token
212
- token_error(token, 'Unexpected token: ' + token.type + ' «' + token.value + '»')
294
+ token_error(
295
+ token,
296
+ 'Unexpected token: ' + token.type + ' «' + token.value + '»'
297
+ )
213
298
 
214
- # --- Error recovery (only active when options.recover_errors is True) --------
299
+ # --- Error recovery (only active when
300
+ # options.recover_errors is True) --------
215
301
  # These helpers let the LSP obtain a usable AST from a file that contains
216
302
  # syntax errors. They are never invoked on the normal compile path, so they
217
303
  # cannot introduce a performance or behavior regression there.
@@ -229,7 +315,8 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
229
315
  # Resynchronize after a syntax error: always consume at least one token
230
316
  # (guaranteeing forward progress) then stop at the start of the next
231
317
  # logical line, a block dedent, or eof. next() may itself raise a
232
- # tokenizer level SyntaxError (e.g. an unterminated string on the skipped
318
+ # tokenizer level SyntaxError (e.g. an unterminated string on the
319
+ # skipped
233
320
  # line); such errors are recorded and skipping continues. The tokenizer
234
321
  # advances its position for every such error (and never raises for an
235
322
  # unexpected character in recover mode), so this loop always terminates.
@@ -249,8 +336,12 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
249
336
  def expect_token(type, val):
250
337
  if is_(type, val):
251
338
  return next()
252
- token_error(S.token, 'Unexpected token ' + S.token.type + ' «' + S.token.value + '»' +
253
- ', expected ' + type + ' «' + val + '»')
339
+ token_error(
340
+ S.token,
341
+ 'Unexpected token ' + S.token.type +
342
+ ' «' + S.token.value + '»' +
343
+ ', expected ' + type + ' «' + val + '»'
344
+ )
254
345
 
255
346
  def expect(punc):
256
347
  return expect_token('punc', punc)
@@ -277,11 +368,17 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
277
368
  # Get the named functions and classes
278
369
  if Array.isArray(body):
279
370
  for obj in body:
280
- if is_node_type(obj, AST_Function) or is_node_type(obj, AST_Class):
371
+ if is_node_type(
372
+ obj,
373
+ AST_Function
374
+ ) or is_node_type(obj, AST_Class):
281
375
  if obj.name:
282
376
  ans.push(obj.name.name)
283
377
  else:
284
- token_error(obj.start, 'Top-level functions must have names')
378
+ token_error(
379
+ obj.start,
380
+ 'Top-level functions must have names'
381
+ )
285
382
  else:
286
383
  # skip inner scopes
287
384
  if is_node_type(obj, AST_Scope):
@@ -291,8 +388,13 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
291
388
  if opt:
292
389
  ans = ans.concat(scan_for_top_level_callables(opt))
293
390
 
294
- if is_node_type(opt, AST_Assign) and not (is_node_type(opt.right, AST_Scope)):
295
- ans = ans.concat(scan_for_top_level_callables(opt.right))
391
+ if is_node_type(
392
+ opt,
393
+ AST_Assign
394
+ ) and not (is_node_type(opt.right, AST_Scope)):
395
+ ans = ans.concat(
396
+ scan_for_top_level_callables(opt.right)
397
+ )
296
398
 
297
399
  elif body.body:
298
400
  # recursive descent into wrapper statements that contain body blocks
@@ -311,7 +413,8 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
311
413
 
312
414
  def scan_for_local_vars(body):
313
415
  """
314
- Pick out all variables being assigned to from within this scope, we'll mark them as local
416
+ Pick out all variables being assigned to from within this scope,
417
+ we'll mark them as local
315
418
 
316
419
  body body to be scanned
317
420
  """
@@ -373,7 +476,10 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
373
476
  if opt:
374
477
  extend(scan_for_local_vars(opt))
375
478
 
376
- if is_node_type(opt, AST_Assign) and not (is_node_type(opt.right, AST_Scope)):
479
+ if is_node_type(
480
+ opt,
481
+ AST_Assign
482
+ ) and not (is_node_type(opt.right, AST_Scope)):
377
483
  extend(scan_for_local_vars(opt.right))
378
484
 
379
485
  # pick up iterators from loops
@@ -399,7 +505,10 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
399
505
  is_compound_assign = False
400
506
  for lhs in body.traverse_chain()[0]:
401
507
  add_assign_lhs(lhs)
402
- if is_node_type(lhs, AST_Seq) or is_node_type(lhs, AST_Array):
508
+ if is_node_type(
509
+ lhs,
510
+ AST_Seq
511
+ ) or is_node_type(lhs, AST_Array):
403
512
  is_compound_assign = True
404
513
  break
405
514
  if is_compound_assign:
@@ -454,19 +563,28 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
454
563
 
455
564
  @embed_tokens
456
565
  async def statement():
457
- # From Kovid: The next three lines were a hack to try to support statements
566
+ # From Kovid: The next three lines were a hack to try to support
567
+ # statements
458
568
  # starting with a regexp literal. However, it did not work, for example:
459
569
  # echo 'f=1\n/asd/.test()' | rs -> parse error
460
- # So we just accept that this cannot be supported in RS, and avoid hacks that mess
570
+ # So we just accept that this cannot be supported in RS, and avoid
571
+ # hacks that mess
461
572
  # with the internal state of S. In any case,
462
573
  # statements starting with a literal are very rare.
463
574
  if S.token.type is 'operator' and S.token.value.substr(0, 1) is '/':
464
- token_error(S.token, 'RapydScript does not support statements starting with regexp literals')
575
+ token_error(
576
+ S.token,
577
+ 'RapydScript does not support statements starting with'
578
+ ' regexp literals'
579
+ )
465
580
 
466
581
  S.statement_starting_token = S.token
467
582
  tmp_ = S.token.type
468
583
  p = prev()
469
- if p and not S.token.nlb and ATOMIC_START_TOKEN[p.type] and not is_('punc', ':'):
584
+ if p and not S.token.nlb and ATOMIC_START_TOKEN[p.type] and not is_(
585
+ 'punc',
586
+ ':'
587
+ ):
470
588
  unexpected()
471
589
  if tmp_ is 'string':
472
590
  return await simple_statement()
@@ -476,7 +594,8 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
476
594
  return new AST_Directive({
477
595
  'value': tmp_
478
596
  })
479
- elif tmp_ is 'num' or tmp_ is 'regexp' or tmp_ is 'operator' or tmp_ is 'atom' or tmp_ is 'js':
597
+ elif (tmp_ is 'num' or tmp_ is 'regexp' or tmp_ is 'operator'
598
+ or tmp_ is 'atom' or tmp_ is 'js'):
480
599
  return await simple_statement()
481
600
  elif tmp_ is 'punc':
482
601
  tmp_ = S.token.value
@@ -491,11 +610,16 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
491
610
  return await simple_statement()
492
611
  elif tmp_ is ';':
493
612
  next()
494
- return new AST_EmptyStatement({'stype': ';', 'start': prev(), 'end': prev()})
613
+ return new AST_EmptyStatement({
614
+ 'stype': ';', 'start': prev(), 'end': prev()
615
+ })
495
616
  else:
496
617
  unexpected()
497
618
  elif tmp_ is 'name':
498
- if (is_token(peek(), 'punc', ':')) token_error(peek(), 'invalid syntax, colon not allowed here')
619
+ if (is_token(peek(), 'punc', ':')) token_error(
620
+ peek(),
621
+ 'invalid syntax, colon not allowed here'
622
+ )
499
623
  return await simple_statement()
500
624
  elif tmp_ is 'keyword':
501
625
  tmp_ = S.token.value
@@ -514,7 +638,9 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
514
638
  expect_token('keyword', 'while')
515
639
  tmp = await expression(True)
516
640
  if is_node_type(tmp, AST_Assign):
517
- croak('Assignments in do loop conditions are not allowed')
641
+ croak(
642
+ 'Assignments in do loop conditions are not allowed'
643
+ )
518
644
  semicolon()
519
645
  return tmp
520
646
  )()
@@ -525,7 +651,9 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
525
651
  elif tmp_ is 'while':
526
652
  while_cond = await expression(True)
527
653
  if is_node_type(while_cond, AST_Assign):
528
- croak('Assignments in while loop conditions are not allowed')
654
+ croak(
655
+ 'Assignments in while loop conditions are not allowed'
656
+ )
529
657
  if not is_('punc', ':'):
530
658
  croak('Expected a colon after the while statement')
531
659
  while_body = await in_loop(statement)
@@ -581,12 +709,17 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
581
709
  if is_('punc', ','):
582
710
  next()
583
711
  msg = await expression(False)
584
- return new AST_Assert({'start': start, 'condition': cond, 'message': msg, 'end': prev()})
712
+ return new AST_Assert({
713
+ 'start': start, 'condition': cond,
714
+ 'message': msg, 'end': prev()
715
+ })
585
716
  elif tmp_ is 'if':
586
717
  return await if_()
587
718
  elif tmp_ is 'pass':
588
719
  semicolon()
589
- return new AST_EmptyStatement({'stype': 'pass', 'start': prev(), 'end': prev()})
720
+ return new AST_EmptyStatement({
721
+ 'stype': 'pass', 'start': prev(), 'end': prev()
722
+ })
590
723
  elif tmp_ is 'return':
591
724
  if S.in_function is 0:
592
725
  croak("'return' outside of function")
@@ -644,7 +777,9 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
644
777
  if is_('keyword', 'as'):
645
778
  next()
646
779
  alias = as_symbol(AST_SymbolAlias)
647
- clauses.push(new AST_WithClause({'expression': expr, 'alias': alias}))
780
+ clauses.push(new AST_WithClause({
781
+ 'expression': expr, 'alias': alias
782
+ }))
648
783
  if is_('punc', ','):
649
784
  next()
650
785
  continue
@@ -695,8 +830,12 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
695
830
  init = await expression(True, True)
696
831
  # standardize AST_Seq into array now for consistency
697
832
  if is_node_type(init, AST_Seq):
698
- if is_node_type(init.car, AST_SymbolRef) and is_node_type(init.cdr, AST_SymbolRef):
699
- # Optimization to prevent runtime call to ρσ_flatten when init is simply (a, b)
833
+ if is_node_type(
834
+ init.car,
835
+ AST_SymbolRef
836
+ ) and is_node_type(init.cdr, AST_SymbolRef):
837
+ # Optimization to prevent runtime call to ρσ_flatten
838
+ # when init is simply (a, b)
700
839
  tmp = init.to_array()
701
840
  else:
702
841
  tmp = [init]
@@ -708,7 +847,9 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
708
847
 
709
848
  if is_('operator', 'in'):
710
849
  if is_node_type(init, AST_Var) and init.definitions.length > 1:
711
- croak('Only one variable declaration allowed in for..in loop')
850
+ croak(
851
+ 'Only one variable declaration allowed in for..in loop'
852
+ )
712
853
  next()
713
854
  return await for_in(init, list_comp)
714
855
 
@@ -763,13 +904,15 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
763
904
 
764
905
  elif is_node_type(expr, AST_Dot):
765
906
  referenced_path = []
766
- # this one is for detecting classes inside modules and eventually nested classes
907
+ # this one is for detecting classes inside modules and
908
+ # eventually nested classes
767
909
  while is_node_type(expr, AST_Dot):
768
910
  referenced_path.unshift(expr.property)
769
911
  expr = expr.expression
770
912
  if is_node_type(expr, AST_SymbolRef):
771
913
  referenced_path.unshift(expr.name)
772
- # now 'referenced_path' should contain the full path of potential class
914
+ # now 'referenced_path' should contain the full path
915
+ # of potential class
773
916
  if len(referenced_path) > 1:
774
917
  class_name = referenced_path.join('.')
775
918
  for s in range(S.classes.length - 1, -1, -1):
@@ -779,17 +922,29 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
779
922
 
780
923
  def import_error(message):
781
924
  ctx = S.input.context()
782
- raise new ImportError(message, ctx.filename, ctx.tokline, ctx.tokcol, ctx.tokpos)
925
+ raise new ImportError(
926
+ message,
927
+ ctx.filename,
928
+ ctx.tokline,
929
+ ctx.tokcol,
930
+ ctx.tokpos
931
+ )
783
932
 
784
933
  async def do_import(key):
785
934
  if has_prop(imported_modules, key):
786
935
  return
787
- # Circular import check must come BEFORE loading_promises so we detect cycles
936
+ # Circular import check must come BEFORE loading_promises so we
937
+ # detect cycles
788
938
  # even when the same module is being loaded by a parallel chain.
789
939
  if has_prop(importing_modules, key) and importing_modules[key]:
790
- import_error('Detected a recursive import of: ' + key + ' while importing: ' + module_id)
791
- # If a parallel chain is already loading this module, wait for it instead of
792
- # starting a duplicate load. loading_promises is shared across the entire
940
+ import_error(
941
+ 'Detected a recursive import of: ' + key +
942
+ ' while importing: ' + module_id
943
+ )
944
+ # If a parallel chain is already loading this module, wait for it
945
+ # instead of
946
+ # starting a duplicate load. loading_promises is shared across
947
+ # the entire
793
948
  # compilation via options.loading_promises.
794
949
  loading_promises = options.loading_promises
795
950
  if has_prop(loading_promises, key):
@@ -798,8 +953,10 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
798
953
 
799
954
  # Register this load BEFORE the first await so that any parallel caller
800
955
  # that reaches this point sees the in-progress entry and waits.
801
- # Use a single-element list to capture the resolve function from the Promise
802
- # executor without needing nonlocal (mutating a container, not rebinding).
956
+ # Use a single-element list to capture the resolve function from
957
+ # the Promise
958
+ # executor without needing nonlocal (mutating a container,
959
+ # not rebinding).
803
960
  _rfn = v'[null]'
804
961
 
805
962
  def _capture_resolve(resolve):
@@ -813,20 +970,37 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
813
970
  await do_import(package_module_id)
814
971
 
815
972
  if options.for_linting:
816
- imported_modules[key] = {'is_cached': True, 'classes': {}, 'module_id': key, 'exports': [],
817
- 'nonlocalvars': [], 'baselib': {}, 'outputs': {}, 'discard_asserts': options.discard_asserts}
973
+ imported_modules[key] = {
974
+ 'is_cached': True,
975
+ 'classes': {},
976
+ 'module_id': key,
977
+ 'exports': [],
978
+ 'nonlocalvars': [],
979
+ 'baselib': {},
980
+ 'outputs': {},
981
+ 'discard_asserts': options.discard_asserts,
982
+ }
818
983
  return
819
984
 
820
- # stat_file returns {mtimeMs, content?}. For real filesystems mtimeMs is a
821
- # number and content is absent; for virtual filesystems content holds the
985
+ # stat_file returns {mtimeMs, content?}. For real filesystems
986
+ # mtimeMs is a
987
+ # number and content is absent; for virtual filesystems
988
+ # content holds the
822
989
  # already-read source to avoid a double read.
823
990
  async def safe_stat(base_path): # noqa
824
- for i, path in enumerate([base_path + '.pyj', base_path + '/__init__.pyj']):
991
+ for i, path in enumerate([
992
+ base_path + '.pyj', base_path + '/__init__.pyj'
993
+ ]):
825
994
  try:
826
995
  st = await stat_file(path)
827
- return [st.mtimeMs, path, st.content if has_prop(st, 'content') else None]
996
+ return [
997
+ st.mtimeMs,
998
+ path,
999
+ st.content if has_prop(st, 'content') else None,
1000
+ ]
828
1001
  except as e:
829
- if e.code is 'ENOENT' or e.code is 'EPERM' or e.code is 'EACCESS':
1002
+ if (e.code is 'ENOENT' or e.code is 'EPERM'
1003
+ or e.code is 'EACCESS'):
830
1004
  if i is 1:
831
1005
  return None, None, None
832
1006
  if i is 1:
@@ -837,15 +1011,24 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
837
1011
 
838
1012
  for location in import_dirs:
839
1013
  if location:
840
- file_mtime, filename, prefetched_src = await safe_stat(location + '/' + modpath)
1014
+ file_mtime, filename, prefetched_src = await safe_stat(
1015
+ location + '/' + modpath
1016
+ )
841
1017
  if filename is not None:
842
1018
  break
843
1019
  if filename is None:
844
- import_error("Failed Import: '" + key + "' module doesn't exist in any of the import directories: " + import_dirs.join(':'))
845
-
846
- # Read the cache file. I/O starts here; any CPU work done before the
1020
+ import_error(
1021
+ "Failed Import: '" + key +
1022
+ "' module doesn't exist in any of the import"
1023
+ ' directories: ' + import_dirs.join(':')
1024
+ )
1025
+
1026
+ # Read the cache file. I/O starts here; any CPU work done
1027
+ # before the
847
1028
  # await can overlap with the disk read.
848
- cache_read = readfile(cache_file_name(filename, options.module_cache_dir))
1029
+ cache_read = readfile(
1030
+ cache_file_name(filename, options.module_cache_dir)
1031
+ )
849
1032
 
850
1033
  cached = None
851
1034
  ast_json_str = None
@@ -858,21 +1041,31 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
858
1041
  cached = None
859
1042
 
860
1043
  srchash = src_code = None
861
- cache_ok = cached and cached.v is CACHE_VERSION and cached.compiler_version is COMPILER_VERSION
862
- if cache_ok and file_mtime is not None and cached.mtime is not None and cached.mtime is file_mtime:
863
- # Fast path: mtime matches — source file is unchanged, skip reading and hashing it
1044
+ cache_ok = (
1045
+ cached and cached.v is CACHE_VERSION
1046
+ and cached.compiler_version is COMPILER_VERSION
1047
+ )
1048
+ if (cache_ok and file_mtime is not None
1049
+ and cached.mtime is not None
1050
+ and cached.mtime is file_mtime):
1051
+ # Fast path: mtime matches — source file is unchanged,
1052
+ # skip reading and hashing it
864
1053
  srchash = cached.signature
865
1054
  else:
866
- # Need source content to validate with sha1sum (or to re-parse on miss)
1055
+ # Need source content to validate with sha1sum (or to
1056
+ # re-parse on miss)
867
1057
  src_code = prefetched_src or await readfile(filename, 'utf-8')
868
1058
  srchash = sha1sum(src_code)
869
1059
  if not cache_ok or cached.signature is not srchash:
870
1060
  cached = None
871
1061
 
872
1062
  if cached is not None:
873
- # Load all deps in parallel — cached module deps have been pre-validated as
874
- # non-circular so Promise.all is safe. The loading_promises dict ensures
875
- # that if two parallel chains try to load the same dep, only one actually
1063
+ # Load all deps in parallel — cached module deps have been
1064
+ # pre-validated as
1065
+ # non-circular so Promise.all is safe. The loading_promises
1066
+ # dict ensures
1067
+ # that if two parallel chains try to load the same dep,
1068
+ # only one actually
876
1069
  # does the work; the other waits.
877
1070
  pending = v'[]'
878
1071
  for ikey in cached.imported_module_ids:
@@ -880,11 +1073,17 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
880
1073
  pending.push(do_import(ikey))
881
1074
  if pending.length > 0:
882
1075
  await Promise.all(pending)
883
- # Reconstruct classes dict from the simplified cache (no full AST nodes).
1076
+ # Reconstruct classes dict from the simplified cache
1077
+ # (no full AST nodes).
884
1078
  classes = {}
885
1079
  for cname in Object.keys(cached.classes or {}):
886
1080
  ci = cached.classes[cname]
887
- classes[cname] = {'name': {'name': cname}, 'static': ci.static or {}, 'bound': ci.bound or [], 'classvars': ci.classvars or {}}
1081
+ classes[cname] = {
1082
+ 'name': {'name': cname},
1083
+ 'static': ci.static or {},
1084
+ 'bound': ci.bound or [],
1085
+ 'classvars': ci.classvars or {},
1086
+ }
888
1087
  meta = {
889
1088
  'module_id': key,
890
1089
  'filename': filename,
@@ -901,21 +1100,25 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
901
1100
  module = make_lazy_ast_module(ast_json_str, meta)
902
1101
  imported_modules[key] = module
903
1102
  else:
904
- await parse(src_code, {
905
- 'filename': filename,
906
- 'toplevel': None,
907
- 'basedir': options.basedir,
908
- 'libdir': options.libdir,
909
- 'import_dirs': options.import_dirs,
910
- 'module_id': key,
911
- 'imported_modules': imported_modules,
912
- 'importing_modules': importing_modules,
913
- 'discard_asserts': options.discard_asserts,
914
- 'module_cache_dir': options.module_cache_dir,
915
- '_src_hash': srchash,
916
- '_file_mtime': file_mtime,
917
- 'loading_promises': loading_promises,
918
- }) # This function will add the module to imported_modules itself
1103
+ await parse(
1104
+ src_code,
1105
+ {
1106
+ 'filename': filename,
1107
+ 'toplevel': None,
1108
+ 'basedir': options.basedir,
1109
+ 'libdir': options.libdir,
1110
+ 'import_dirs': options.import_dirs,
1111
+ 'module_id': key,
1112
+ 'imported_modules': imported_modules,
1113
+ 'importing_modules': importing_modules,
1114
+ 'discard_asserts': options.discard_asserts,
1115
+ 'module_cache_dir': options.module_cache_dir,
1116
+ '_src_hash': srchash,
1117
+ '_file_mtime': file_mtime,
1118
+ 'loading_promises': loading_promises,
1119
+ }
1120
+ )
1121
+ # This function will add the module to imported_modules itself
919
1122
  finally:
920
1123
  del loading_promises[key]
921
1124
  if _rfn[0]:
@@ -951,7 +1154,9 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
951
1154
  else:
952
1155
  continue
953
1156
  break
954
- return new AST_EmptyStatement({'stype': 'scoped_flags', 'start': prev(), 'end': prev()})
1157
+ return new AST_EmptyStatement({
1158
+ 'stype': 'scoped_flags', 'start': prev(), 'end': prev()
1159
+ })
955
1160
 
956
1161
  async def import_(from_import):
957
1162
  ans = new AST_Imports({'imports': []})
@@ -1001,8 +1206,14 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
1001
1206
  exports[symdef.name] = True
1002
1207
  while True:
1003
1208
  aname = as_symbol(AST_ImportedVar)
1004
- if not options.for_linting and not has_prop(exports, aname.name):
1005
- import_error('The symbol "' + aname.name + '" is not exported from the module: ' + key)
1209
+ if not options.for_linting and not has_prop(
1210
+ exports,
1211
+ aname.name
1212
+ ):
1213
+ import_error(
1214
+ 'The symbol "' + aname.name +
1215
+ '" is not exported from the module: ' + key
1216
+ )
1006
1217
  if is_('keyword', 'as'):
1007
1218
  next()
1008
1219
  aname.alias = as_symbol(AST_SymbolAlias)
@@ -1022,12 +1233,20 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
1022
1233
  obj = classes[argvar.name]
1023
1234
  if obj:
1024
1235
  key = argvar.alias.name if argvar.alias else argvar.name
1025
- S.classes[-1][key] = {'static': obj.static, 'bound': obj.bound, 'classvars': obj.classvars}
1236
+ S.classes[-1][key] = {
1237
+ 'static': obj.static,
1238
+ 'bound': obj.bound,
1239
+ 'classvars': obj.classvars,
1240
+ }
1026
1241
  else:
1027
1242
  for cname in Object.keys(classes):
1028
1243
  obj = classes[cname]
1029
1244
  key = imp.alias.name if imp.alias else imp.key
1030
- S.classes[-1][key + '.' + obj.name.name] = {'static': obj.static, 'bound': obj.bound, 'classvars': obj.classvars}
1245
+ S.classes[-1][key + '.' + obj.name.name] = {
1246
+ 'static': obj.static,
1247
+ 'bound': obj.bound,
1248
+ 'classvars': obj.classvars,
1249
+ }
1031
1250
 
1032
1251
  return ans
1033
1252
 
@@ -1077,7 +1296,8 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
1077
1296
  return d
1078
1297
  )()
1079
1298
  cls_body = await (async def (loop, labels):
1080
- # navigate to correct location in the module tree and append the class
1299
+ # navigate to correct location in the module tree and
1300
+ # append the class
1081
1301
  S.in_class.push(name.name)
1082
1302
  S.classes[S.classes.length - 1][name.name] = class_details
1083
1303
  S.classes.push({})
@@ -1117,7 +1337,9 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
1117
1337
  if stmt.is_getter or stmt.is_setter:
1118
1338
  descriptor = definition.dynamic_properties[stmt.name.name]
1119
1339
  if not descriptor:
1120
- descriptor = definition.dynamic_properties[stmt.name.name] = {}
1340
+ descriptor = definition.dynamic_properties[
1341
+ stmt.name.name
1342
+ ] = {}
1121
1343
  descriptor['getter' if stmt.is_getter else 'setter'] = stmt
1122
1344
  elif stmt.name.name is '__init__':
1123
1345
  definition.init = stmt
@@ -1134,14 +1356,25 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
1134
1356
  return
1135
1357
  if is_node_type(node, AST_Function):
1136
1358
  return
1137
- if is_node_type(node, AST_Assign) and is_node_type(node.left, AST_SymbolRef):
1359
+ if is_node_type(node, AST_Assign) and is_node_type(
1360
+ node.left,
1361
+ AST_SymbolRef
1362
+ ):
1138
1363
  varname = node.left.name
1139
1364
  if FORBIDDEN_CLASS_VARS.indexOf(varname) is not -1:
1140
- token_error(node.left.start, varname + ' is not allowed as a class variable name')
1365
+ token_error(
1366
+ node.left.start,
1367
+ varname + ' is not allowed as a class variable name'
1368
+ )
1141
1369
  class_var_names[varname] = True
1142
1370
  definition.classvars[varname] = True
1143
- elif is_node_type(node, AST_SymbolRef) and has_prop(class_var_names, node.name):
1144
- node.thedef = new AST_SymbolDefun({'name': name.name + '.prototype.' + node.name})
1371
+ elif is_node_type(node, AST_SymbolRef) and has_prop(
1372
+ class_var_names,
1373
+ node.name
1374
+ ):
1375
+ node.thedef = new AST_SymbolDefun({
1376
+ 'name': name.name + '.prototype.' + node.name
1377
+ })
1145
1378
  if descend:
1146
1379
  descend.call(node)
1147
1380
  this._visit = visit_node
@@ -1154,7 +1387,9 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
1154
1387
  return definition
1155
1388
 
1156
1389
  async def function_(in_class, is_expression, is_async=False):
1157
- name = as_symbol(AST_SymbolDefun if in_class else AST_SymbolLambda) if is_('name') else None
1390
+ name = as_symbol(
1391
+ AST_SymbolDefun if in_class else AST_SymbolLambda
1392
+ ) if is_('name') else None
1158
1393
  if in_class and not name:
1159
1394
  croak('Cannot use anonymous function as class methods')
1160
1395
  is_anonymous = not name
@@ -1166,10 +1401,16 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
1166
1401
  property_setter = has_setter_decorator(S.decorators, name.name)
1167
1402
  if staticloc:
1168
1403
  if property_getter or property_setter:
1169
- croak('A method cannot be both static and a property getter/setter')
1170
- S.classes[S.classes.length - 2][in_class].static[name.name] = True
1404
+ croak(
1405
+ 'A method cannot be both static and a'
1406
+ ' property getter/setter'
1407
+ )
1408
+ S.classes[S.classes.length - 2][in_class].static[
1409
+ name.name
1410
+ ] = True
1171
1411
  staticmethod = True
1172
- elif name.name is not '__init__' and S.scoped_flags.get('bound_methods'):
1412
+ elif (name.name is not '__init__'
1413
+ and S.scoped_flags.get('bound_methods')):
1173
1414
  S.classes[S.classes.length - 2][in_class].bound.push(name.name)
1174
1415
 
1175
1416
  expect('(')
@@ -1196,7 +1437,11 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
1196
1437
  if has_prop(seen_names, current_arg_name):
1197
1438
  token_error(prev(), "Can't repeat parameter names")
1198
1439
  if current_arg_name is 'arguments':
1199
- token_error(prev(), "Can't use the name arguments as a parameter name, it is reserved by JavaScript")
1440
+ token_error(
1441
+ prev(),
1442
+ "Can't use the name arguments as a parameter"
1443
+ ' name, it is reserved by JavaScript'
1444
+ )
1200
1445
  seen_names[current_arg_name] = True
1201
1446
  # save these in order to move back if we have an annotation
1202
1447
  name_token = S.token
@@ -1226,8 +1471,9 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
1226
1471
  return sym
1227
1472
  else:
1228
1473
  if not is_('name'):
1229
- # there is no name, which is an error we should report on the
1230
- # same line as the definition, so move to that is we're not already there.
1474
+ # there is no name, which is an error we should
1475
+ # report on the same line as the definition, so
1476
+ # move to that is we're not already there.
1231
1477
  if S.input.context().tokline is not def_line:
1232
1478
  croak('Name expected', def_line)
1233
1479
  else:
@@ -1252,29 +1498,52 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
1252
1498
  # **kwargs
1253
1499
  next()
1254
1500
  if kwargs_sym:
1255
- token_error(name_token, "Can't define multiple **kwargs in function definition")
1501
+ token_error(
1502
+ name_token,
1503
+ "Can't define multiple **kwargs"
1504
+ ' in function definition'
1505
+ )
1256
1506
  kwargs_sym = await get_arg()
1257
1507
  elif is_('operator', '*'):
1258
1508
  # *args
1259
1509
  next()
1260
1510
  if starargs_sym:
1261
- token_error(name_token, "Can't define multiple *args in function definition")
1511
+ token_error(
1512
+ name_token,
1513
+ "Can't define multiple *args in function definition"
1514
+ )
1262
1515
  if kwargs_sym:
1263
- token_error(name_token, "Can't define *args after **kwargs in function definition")
1516
+ token_error(
1517
+ name_token,
1518
+ "Can't define *args after **kwargs"
1519
+ ' in function definition'
1520
+ )
1264
1521
  starargs_sym = await get_arg()
1265
1522
  else:
1266
1523
  if starargs_sym or kwargs_sym:
1267
- token_error(name_token, "Can't define a formal parameter after *args or **kwargs")
1524
+ token_error(
1525
+ name_token,
1526
+ "Can't define a formal parameter after"
1527
+ ' *args or **kwargs'
1528
+ )
1268
1529
  a.push(await get_arg())
1269
1530
  if is_('operator', '='):
1270
1531
  if kwargs_sym:
1271
- token_error(name_token, "Can't define an optional formal parameter after **kwargs")
1532
+ token_error(
1533
+ name_token,
1534
+ "Can't define an optional formal parameter"
1535
+ ' after **kwargs'
1536
+ )
1272
1537
  next()
1273
1538
  defaults[current_arg_name] = await expression(False)
1274
1539
  has_defaults = True
1275
1540
  else:
1276
1541
  if has_defaults:
1277
- token_error(name_token, "Can't define required formal parameters after optional formal parameters")
1542
+ token_error(
1543
+ name_token,
1544
+ "Can't define required formal parameters"
1545
+ ' after optional formal parameters'
1546
+ )
1278
1547
  next()
1279
1548
  # check if we have a return type annotation
1280
1549
  if is_('punc', '->'):
@@ -1288,7 +1557,9 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
1288
1557
  'kwargs': kwargs_sym,
1289
1558
  'defaults': defaults,
1290
1559
  'has_defaults': has_defaults,
1291
- 'is_simple_func': not starargs_sym and not kwargs_sym and not has_defaults,
1560
+ 'is_simple_func': (
1561
+ not starargs_sym and not kwargs_sym and not has_defaults
1562
+ ),
1292
1563
  })
1293
1564
  )()
1294
1565
 
@@ -1339,14 +1610,23 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
1339
1610
  definition.is_getter = property_getter
1340
1611
  definition.is_setter = property_setter
1341
1612
  if definition.argnames.args.length < 1 and not definition.static:
1342
- croak('Methods of a class must have at least one argument, traditionally named self')
1613
+ croak(
1614
+ 'Methods of a class must have at least one argument,'
1615
+ ' traditionally named self'
1616
+ )
1343
1617
  if definition.name and definition.name.name is '__init__':
1344
1618
  if definition.is_generator:
1345
- croak('The __init__ method of a class cannot be a generator (yield not allowed)')
1619
+ croak(
1620
+ 'The __init__ method of a class cannot be a'
1621
+ ' generator (yield not allowed)'
1622
+ )
1346
1623
  if definition.is_async:
1347
1624
  croak('The __init__ method of a class cannot be async')
1348
1625
  if property_getter or property_setter:
1349
- croak('The __init__ method of a class cannot be a property getter/setter')
1626
+ croak(
1627
+ 'The __init__ method of a class cannot be a'
1628
+ ' property getter/setter'
1629
+ )
1350
1630
  if definition.is_async and definition.is_generator:
1351
1631
  croak('A function cannot be both async and a generator')
1352
1632
  if definition.is_generator:
@@ -1357,13 +1637,19 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
1357
1637
  for i in range(assignments.length):
1358
1638
  for j in range(definition.argnames.args.length + 1):
1359
1639
  if j is definition.argnames.args.length:
1360
- definition.localvars.push(new_symbol(AST_SymbolVar, assignments[i]))
1361
- elif j < definition.argnames.args.length and assignments[i] is definition.argnames.args[j].name:
1640
+ definition.localvars.push(
1641
+ new_symbol(AST_SymbolVar, assignments[i])
1642
+ )
1643
+ elif (j < definition.argnames.args.length
1644
+ and assignments[i] is definition.argnames.args[j].name):
1362
1645
  break
1363
1646
 
1364
1647
  nonlocals = scan_for_nonlocal_defs(definition.body)
1365
1648
  nonlocals = {name for name in nonlocals}
1366
- definition.localvars = definition.localvars.filter(def (v): return not nonlocals.has(v.name);)
1649
+ definition.localvars = definition.localvars.filter(
1650
+ def (v):
1651
+ return not nonlocals.has(v.name)
1652
+ )
1367
1653
  return definition
1368
1654
 
1369
1655
  async def if_():
@@ -1419,7 +1705,8 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
1419
1705
  a.push(stmt)
1420
1706
  else:
1421
1707
  current_whitespace = S.token.leading_whitespace
1422
- if current_whitespace.length is 0 or prev_whitespace is current_whitespace:
1708
+ if (current_whitespace.length is 0
1709
+ or prev_whitespace is current_whitespace):
1423
1710
  croak('Expected an indented block')
1424
1711
  while not is_('punc', '}'):
1425
1712
  if is_('eof'):
@@ -1499,7 +1786,9 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
1499
1786
 
1500
1787
  return new AST_Try({
1501
1788
  'body': body,
1502
- 'bcatch': (new AST_Catch({'body': bcatch}) if bcatch.length else None),
1789
+ 'bcatch': (
1790
+ new AST_Catch({'body': bcatch}) if bcatch.length else None
1791
+ ),
1503
1792
  'bfinally': bfinally,
1504
1793
  'belse': belse
1505
1794
  })
@@ -1612,7 +1901,10 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
1612
1901
  'end': tok,
1613
1902
  'value': tok.value,
1614
1903
  })
1615
- token_error(tok, 'Expecting an atomic token (number/string/bool/regexp/js/None)')
1904
+ token_error(
1905
+ tok,
1906
+ 'Expecting an atomic token (number/string/bool/regexp/js/None)'
1907
+ )
1616
1908
 
1617
1909
  def as_atom_node():
1618
1910
  ret = token_as_atom_node()
@@ -1627,15 +1919,20 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
1627
1919
  if is_('punc'):
1628
1920
  tmp_ = start.value
1629
1921
  if tmp_ is '(':
1922
+ prev_parens = S.in_parenthesized_expr
1630
1923
  S.in_parenthesized_expr = True
1631
1924
  next()
1632
1925
  if is_('punc', ')'):
1633
1926
  next()
1927
+ S.in_parenthesized_expr = prev_parens
1634
1928
  return new AST_Array({'elements': []})
1635
1929
  ex = await expression(True)
1636
1930
  if is_('keyword', 'for'):
1637
- ret = await read_comprehension(new AST_GeneratorComprehension({'statement': ex}), ')')
1638
- S.in_parenthesized_expr = False
1931
+ ret = await read_comprehension(
1932
+ new AST_GeneratorComprehension({'statement': ex}),
1933
+ ')'
1934
+ )
1935
+ S.in_parenthesized_expr = prev_parens
1639
1936
  return ret
1640
1937
  ex.start = start
1641
1938
  ex.end = S.token
@@ -1645,7 +1942,7 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
1645
1942
  expect(')')
1646
1943
  if is_node_type(ex, AST_UnaryPrefix):
1647
1944
  ex.parenthesized = True
1648
- S.in_parenthesized_expr = False
1945
+ S.in_parenthesized_expr = prev_parens
1649
1946
  return await subscripts(ex, allow_calls)
1650
1947
  elif tmp_ is '[':
1651
1948
  return await subscripts(await array_(), allow_calls)
@@ -1700,7 +1997,10 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
1700
1997
  saw_starargs = False
1701
1998
  while not is_('punc', closing):
1702
1999
  if saw_starargs:
1703
- token_error(prev(), '*args must be the last argument in a function call')
2000
+ token_error(
2001
+ prev(),
2002
+ '*args must be the last argument in a function call'
2003
+ )
1704
2004
 
1705
2005
  if first:
1706
2006
  first = False
@@ -1730,7 +2030,10 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
1730
2030
  kwargs.push([arg.left, arg.right])
1731
2031
  else:
1732
2032
  pargs.push(arg)
1733
- return new AST_CallArgs({'args': pargs, 'kwargs': kwargs, 'kwarg_items': v'[]', 'starargs': saw_starargs})
2033
+ return new AST_CallArgs({
2034
+ 'args': pargs, 'kwargs': kwargs,
2035
+ 'kwarg_items': v'[]', 'starargs': saw_starargs
2036
+ })
1734
2037
  return a
1735
2038
 
1736
2039
  async def func_call_list(empty):
@@ -1740,13 +2043,19 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
1740
2043
  kwarg_items = v'[]'
1741
2044
  starargs = False
1742
2045
  if empty:
1743
- return new AST_CallArgs({'args': a, 'kwargs': kwargs, 'kwarg_items': kwarg_items, 'starargs': starargs})
2046
+ return new AST_CallArgs({
2047
+ 'args': a, 'kwargs': kwargs,
2048
+ 'kwarg_items': kwarg_items, 'starargs': starargs
2049
+ })
1744
2050
  single_comprehension = False
1745
2051
  while not is_('punc', ')') and not is_('eof'):
1746
2052
  if not first:
1747
- expect(',')
1748
- if is_('punc', ')'):
1749
- break
2053
+ if S.token.nlb and not is_('punc', ','):
2054
+ pass
2055
+ else:
2056
+ expect(',')
2057
+ if is_('punc', ')'):
2058
+ break
1750
2059
  if is_('operator', '*'):
1751
2060
  next()
1752
2061
  arg = await expression(False)
@@ -1763,16 +2072,27 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
1763
2072
  else:
1764
2073
  if is_('keyword', 'for'):
1765
2074
  if not first:
1766
- croak('Generator expression must be parenthesized if not sole argument')
1767
- comp = await read_comprehension(new AST_GeneratorComprehension({'statement': arg}), ')')
1768
- a.push(new AST_CallArg({'value': comp, 'is_array': False}))
2075
+ croak(
2076
+ 'Generator expression must be'
2077
+ ' parenthesized if not sole argument'
2078
+ )
2079
+ comp = await read_comprehension(
2080
+ new AST_GeneratorComprehension({'statement': arg}),
2081
+ ')'
2082
+ )
2083
+ a.push(new AST_CallArg({
2084
+ 'value': comp, 'is_array': False
2085
+ }))
1769
2086
  single_comprehension = True
1770
2087
  break
1771
2088
  a.push(new AST_CallArg({'value': arg, 'is_array': False}))
1772
2089
  first = False
1773
2090
  if not single_comprehension:
1774
2091
  next()
1775
- return new AST_CallArgs({'args': a, 'kwargs': kwargs, 'kwarg_items': kwarg_items, 'starargs': starargs})
2092
+ return new AST_CallArgs({
2093
+ 'args': a, 'kwargs': kwargs,
2094
+ 'kwarg_items': kwarg_items, 'starargs': starargs
2095
+ })
1776
2096
 
1777
2097
  @embed_tokens
1778
2098
  async def array_():
@@ -1782,7 +2102,10 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
1782
2102
  expr.push(await expression(False))
1783
2103
  if is_('keyword', 'for'):
1784
2104
  # list comprehension
1785
- return await read_comprehension(new AST_ListComprehension({'statement': expr[0]}), ']')
2105
+ return await read_comprehension(
2106
+ new AST_ListComprehension({'statement': expr[0]}),
2107
+ ']'
2108
+ )
1786
2109
 
1787
2110
  if not is_('punc', ']'):
1788
2111
  expect(',')
@@ -1818,7 +2141,10 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
1818
2141
  ctx.expecting_object_literal_key = orig
1819
2142
  if is_('keyword', 'for'):
1820
2143
  # is_pydict is irrelevant here
1821
- return await read_comprehension(new AST_SetComprehension({'statement': left}), '}')
2144
+ return await read_comprehension(
2145
+ new AST_SetComprehension({'statement': left}),
2146
+ '}'
2147
+ )
1822
2148
  if a.length is 0 and (is_('punc', ',') or is_('punc', '}')):
1823
2149
  end = prev()
1824
2150
  return await set_(start, end, left)
@@ -1836,11 +2162,9 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
1836
2162
  return await dict_comprehension(a, is_pydict, is_jshash)
1837
2163
 
1838
2164
  next()
1839
- return new (AST_ExpressiveObject if has_non_const_keys else AST_Object)({
1840
- 'properties': a,
1841
- 'is_pydict': is_pydict,
1842
- 'is_jshash': is_jshash,
1843
- })
2165
+ return new (
2166
+ AST_ExpressiveObject if has_non_const_keys else AST_Object
2167
+ )({'properties': a, 'is_pydict': is_pydict, 'is_jshash': is_jshash,})
1844
2168
 
1845
2169
  async def set_(start, end, expr):
1846
2170
  ostart = start
@@ -1852,7 +2176,9 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
1852
2176
  # allow trailing comma
1853
2177
  break
1854
2178
  set_val = await expression(False)
1855
- a.push(new AST_SetItem({'start': start, 'value': set_val, 'end': prev()}))
2179
+ a.push(new AST_SetItem({
2180
+ 'start': start, 'value': set_val, 'end': prev()
2181
+ }))
1856
2182
  next()
1857
2183
  return new AST_Set({'items': a, 'start': ostart, 'end': prev()})
1858
2184
 
@@ -1860,7 +2186,8 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
1860
2186
  if is_node_type(obj, AST_GeneratorComprehension):
1861
2187
  baselib_items['yield'] = True
1862
2188
  S.in_comprehension = True
1863
- S.in_parenthesized_expr = False # in case we are already in a parenthesized expression
2189
+ # in case we are already in a parenthesized expression
2190
+ S.in_parenthesized_expr = False
1864
2191
  expect_token('keyword', 'for')
1865
2192
  forloop = await for_(True)
1866
2193
  obj.init = forloop.init
@@ -1881,11 +2208,17 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
1881
2208
  else:
1882
2209
  left = await expression(False)
1883
2210
  if not is_('punc', ':'):
1884
- return await read_comprehension(new AST_SetComprehension({'statement': left}), '}')
2211
+ return await read_comprehension(
2212
+ new AST_SetComprehension({'statement': left}),
2213
+ '}'
2214
+ )
1885
2215
  expect(':')
1886
2216
  right = await expression(False)
1887
2217
  return await read_comprehension(
1888
- new AST_DictComprehension({'statement': left, 'value_statement': right, 'is_pydict': is_pydict, 'is_jshash': is_jshash}),
2218
+ new AST_DictComprehension({
2219
+ 'statement': left, 'value_statement': right,
2220
+ 'is_pydict': is_pydict, 'is_jshash': is_jshash
2221
+ }),
1889
2222
  '}'
1890
2223
  )
1891
2224
 
@@ -1893,7 +2226,8 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
1893
2226
  tmp = S.token
1894
2227
  next()
1895
2228
  tmp_ = tmp.type
1896
- if tmp_ is 'name' or tmp_ is 'operator' or tmp_ is 'keyword' or tmp_ is 'atom':
2229
+ if (tmp_ is 'name' or tmp_ is 'operator'
2230
+ or tmp_ is 'keyword' or tmp_ is 'atom'):
1897
2231
  return tmp.value
1898
2232
  else:
1899
2233
  unexpected()
@@ -1928,7 +2262,10 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
1928
2262
  return sym
1929
2263
 
1930
2264
  def is_static_method(cls, method):
1931
- if has_prop(COMMON_STATIC, method) or (cls.static and has_prop(cls.static, method)):
2265
+ if has_prop(
2266
+ COMMON_STATIC,
2267
+ method
2268
+ ) or (cls.static and has_prop(cls.static, method)):
1932
2269
  return True
1933
2270
  else:
1934
2271
  return False
@@ -1992,44 +2329,79 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
1992
2329
  _ca.push(new AST_CallArg({'value': expr, 'is_array': False}))
1993
2330
  for _sb in slice_bounds:
1994
2331
  _ca.push(new AST_CallArg({'value': _sb, 'is_array': False}))
1995
- return await subscripts(new AST_Call({
1996
- 'start': start,
1997
- 'expression': new AST_SymbolRef({
1998
- 'name': 'ρσ_delslice' if S.in_delete else 'ρσ_eslice'
2332
+ return await subscripts(
2333
+ new AST_Call({
2334
+ 'start': start,
2335
+ 'expression': new AST_SymbolRef({
2336
+ 'name': (
2337
+ 'ρσ_delslice'
2338
+ if S.in_delete else 'ρσ_eslice'
2339
+ )
2340
+ }),
2341
+ 'args': new AST_CallArgs({
2342
+ 'args': _ca, 'kwargs': v'[]',
2343
+ 'kwarg_items': v'[]', 'starargs': False
2344
+ }),
2345
+ 'end': prev()
1999
2346
  }),
2000
- 'args': new AST_CallArgs({'args': _ca, 'kwargs': v'[]', 'kwarg_items': v'[]', 'starargs': False}),
2001
- 'end': prev()
2002
- }), allow_calls)
2347
+ allow_calls
2348
+ )
2003
2349
  else:
2004
2350
  # regular slice (arr[start:end])
2005
- slice_bounds = [new AST_Number({'value': 0}) if i is None else i for i in slice_bounds]
2351
+ slice_bounds = [
2352
+ new AST_Number({'value': 0}) if i is None else i
2353
+ for i in slice_bounds
2354
+ ]
2006
2355
  if S.in_delete:
2007
2356
  _ca2 = v'[]'
2008
- _ca2.push(new AST_CallArg({'value': expr, 'is_array': False}))
2009
- _ca2.push(new AST_CallArg({'value': new AST_Number({'value': 1}), 'is_array': False}))
2357
+ _ca2.push(new AST_CallArg({
2358
+ 'value': expr, 'is_array': False
2359
+ }))
2360
+ _ca2.push(new AST_CallArg({
2361
+ 'value': new AST_Number({'value': 1}),
2362
+ 'is_array': False
2363
+ }))
2010
2364
  for _sb in slice_bounds:
2011
- _ca2.push(new AST_CallArg({'value': _sb, 'is_array': False}))
2012
- return await subscripts(new AST_Call({
2013
- 'start': start,
2014
- 'expression': new AST_SymbolRef({'name': 'ρσ_delslice'}),
2015
- 'args': new AST_CallArgs({'args': _ca2, 'kwargs': v'[]', 'kwarg_items': v'[]', 'starargs': False}),
2016
- 'end': prev()
2017
- }), allow_calls)
2365
+ _ca2.push(new AST_CallArg({
2366
+ 'value': _sb, 'is_array': False
2367
+ }))
2368
+ return await subscripts(
2369
+ new AST_Call({
2370
+ 'start': start,
2371
+ 'expression': new AST_SymbolRef({
2372
+ 'name': 'ρσ_delslice'
2373
+ }),
2374
+ 'args': new AST_CallArgs({
2375
+ 'args': _ca2, 'kwargs': v'[]',
2376
+ 'kwarg_items': v'[]', 'starargs': False
2377
+ }),
2378
+ 'end': prev()
2379
+ }),
2380
+ allow_calls
2381
+ )
2018
2382
 
2019
2383
  _ca3 = v'[]'
2020
2384
  for _sb in slice_bounds:
2021
- _ca3.push(new AST_CallArg({'value': _sb, 'is_array': False}))
2022
- return await subscripts(new AST_Call({
2023
- 'start': start,
2024
- 'expression': new AST_Dot({
2385
+ _ca3.push(new AST_CallArg({
2386
+ 'value': _sb, 'is_array': False
2387
+ }))
2388
+ return await subscripts(
2389
+ new AST_Call({
2025
2390
  'start': start,
2026
- 'expression': expr,
2027
- 'property': 'slice',
2391
+ 'expression': new AST_Dot({
2392
+ 'start': start,
2393
+ 'expression': expr,
2394
+ 'property': 'slice',
2395
+ 'end': prev()
2396
+ }),
2397
+ 'args': new AST_CallArgs({
2398
+ 'args': _ca3, 'kwargs': v'[]',
2399
+ 'kwarg_items': v'[]', 'starargs': False
2400
+ }),
2028
2401
  'end': prev()
2029
2402
  }),
2030
- 'args': new AST_CallArgs({'args': _ca3, 'kwargs': v'[]', 'kwarg_items': v'[]', 'starargs': False}),
2031
- 'end': prev()
2032
- }), allow_calls)
2403
+ allow_calls
2404
+ )
2033
2405
  else:
2034
2406
  # regular index (arr[index])
2035
2407
  if is_py_sub:
@@ -2061,6 +2433,7 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
2061
2433
 
2062
2434
  async def call_(expr):
2063
2435
  start = expr.start
2436
+ prev_parens = S.in_parenthesized_expr
2064
2437
  S.in_parenthesized_expr = True
2065
2438
  next()
2066
2439
  if not expr.parens and get_class_in_scope(expr):
@@ -2072,7 +2445,7 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
2072
2445
  'args': call_args,
2073
2446
  'end': prev()
2074
2447
  }), True)
2075
- S.in_parenthesized_expr = False
2448
+ S.in_parenthesized_expr = prev_parens
2076
2449
  return ret
2077
2450
  else:
2078
2451
  if is_node_type(expr, AST_Dot):
@@ -2091,7 +2464,7 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
2091
2464
  'args': classcall_args,
2092
2465
  'end': prev()
2093
2466
  }), True)
2094
- S.in_parenthesized_expr = False
2467
+ S.in_parenthesized_expr = prev_parens
2095
2468
  return ret
2096
2469
  elif is_node_type(expr, AST_SymbolRef):
2097
2470
  tmp_ = expr.name
@@ -2103,12 +2476,15 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
2103
2476
  'expression': jstype_args.args[0].value,
2104
2477
  'end': prev()
2105
2478
  })
2106
- S.in_parenthesized_expr = False
2479
+ S.in_parenthesized_expr = prev_parens
2107
2480
  return ret
2108
2481
  elif tmp_ is 'isinstance':
2109
2482
  args = await func_call_list()
2110
2483
  if args.args.length is not 2:
2111
- croak('isinstance() must be called with exactly two arguments')
2484
+ croak(
2485
+ 'isinstance() must be called with exactly'
2486
+ ' two arguments'
2487
+ )
2112
2488
  ret = new AST_Binary({
2113
2489
  'start': start,
2114
2490
  'left': args.args[0].value,
@@ -2116,7 +2492,7 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
2116
2492
  'right': args.args[1].value,
2117
2493
  'end': prev()
2118
2494
  })
2119
- S.in_parenthesized_expr = False
2495
+ S.in_parenthesized_expr = prev_parens
2120
2496
  return ret
2121
2497
 
2122
2498
  # fall-through to basic function call
@@ -2127,7 +2503,7 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
2127
2503
  'args': basic_args,
2128
2504
  'end': prev()
2129
2505
  }), True)
2130
- S.in_parenthesized_expr = False
2506
+ S.in_parenthesized_expr = prev_parens
2131
2507
  return ret
2132
2508
 
2133
2509
  async def get_attr(expr, allow_calls):
@@ -2147,11 +2523,14 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
2147
2523
  }), allow_calls)
2148
2524
 
2149
2525
  async def existential(expr, allow_calls):
2150
- ans = new AST_Existential({'start': expr.start, 'end': S.token, 'expression': expr})
2526
+ ans = new AST_Existential({
2527
+ 'start': expr.start, 'end': S.token, 'expression': expr
2528
+ })
2151
2529
  next()
2152
2530
  ttype = S.token.type
2153
2531
  val = S.token.value
2154
- if S.token.nlb or ttype is 'keyword' or ttype is 'operator' or ttype is 'eof':
2532
+ if (S.token.nlb or ttype is 'keyword'
2533
+ or ttype is 'operator' or ttype is 'eof'):
2155
2534
  ans.after = None
2156
2535
  return ans
2157
2536
  if ttype is 'punc':
@@ -2197,14 +2576,21 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
2197
2576
  expr = await expression()
2198
2577
  S.parsing_decorator = False
2199
2578
  S.decorators.push(expr)
2200
- return new AST_EmptyStatement({'stype': '@', 'start': prev(), 'end': prev()})
2579
+ return new AST_EmptyStatement({
2580
+ 'stype': '@', 'start': prev(), 'end': prev()
2581
+ })
2201
2582
  if is_('operator') and UNARY_PREFIX[start.value]:
2202
2583
  next()
2203
2584
  is_parenthesized = is_('punc', '(')
2204
2585
  S.in_delete = start.value is 'delete'
2205
2586
  expr = await maybe_unary(allow_calls)
2206
2587
  S.in_delete = False
2207
- ex = make_unary(AST_UnaryPrefix, start.value, expr, is_parenthesized)
2588
+ ex = make_unary(
2589
+ AST_UnaryPrefix,
2590
+ start.value,
2591
+ expr,
2592
+ is_parenthesized
2593
+ )
2208
2594
  ex.start = start
2209
2595
  ex.end = prev()
2210
2596
  return ex
@@ -2248,7 +2634,12 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
2248
2634
  async def maybe_conditional(no_in):
2249
2635
  start = S.token
2250
2636
  expr = await expr_ops(no_in)
2251
- if (is_('keyword', 'if') and (S.in_parenthesized_expr or (S.statement_starting_token is not S.token and not S.in_comprehension and not S.token.nlb))):
2637
+ if (is_('keyword', 'if') and (
2638
+ S.in_parenthesized_expr or (
2639
+ S.statement_starting_token is not S.token
2640
+ and not S.in_comprehension
2641
+ and not S.token.nlb
2642
+ ))):
2252
2643
  next()
2253
2644
  ne = await expression(False)
2254
2645
  expect_token('keyword', 'else')
@@ -2264,10 +2655,18 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
2264
2655
  return expr
2265
2656
 
2266
2657
  def create_assign(data):
2267
- if data.right and is_node_type(data.right, AST_Seq) and (
2268
- is_node_type(data.right.car, AST_Assign) or
2269
- is_node_type(data.right.cdr, AST_Assign)) and data.operator is not '=':
2270
- token_error(data.start, 'Invalid assignment operator for chained assignment: ' + data.operator)
2658
+ if data.right and is_node_type(
2659
+ data.right,
2660
+ AST_Seq
2661
+ ) and (
2662
+ is_node_type(data.right.car, AST_Assign)
2663
+ or is_node_type(data.right.cdr, AST_Assign)
2664
+ ) and data.operator is not '=':
2665
+ token_error(
2666
+ data.start,
2667
+ 'Invalid assignment operator for chained'
2668
+ ' assignment: ' + data.operator
2669
+ )
2271
2670
  ans = AST_Assign(data)
2272
2671
  if S.in_class.length and S.in_class[-1]:
2273
2672
  class_name = S.in_class[-1]
@@ -2287,7 +2686,10 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
2287
2686
  val = S.token.value
2288
2687
  if is_('operator') and ASSIGNMENT[val]:
2289
2688
  if only_plain_assignment and val is not '=':
2290
- croak('Invalid assignment operator for chained assignment: ' + val)
2689
+ croak(
2690
+ 'Invalid assignment operator for chained assignment: '
2691
+ + val
2692
+ )
2291
2693
  next()
2292
2694
  assign_right = await maybe_assign(no_in, True)
2293
2695
  return create_assign({
@@ -2317,20 +2719,26 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
2317
2719
  })
2318
2720
  if commas:
2319
2721
  left = v'[ expr ]'
2320
- while is_('punc', ',') and (not peek().nlb or S.in_parenthesized_expr):
2321
- next()
2722
+ while is_(
2723
+ 'punc', ','
2724
+ ) and (not peek().nlb or S.in_parenthesized_expr) or (
2725
+ S.in_parenthesized_expr and S.token.nlb
2726
+ and not is_('punc', ')')
2727
+ ):
2728
+ if is_('punc', ','):
2729
+ next()
2322
2730
  if is_node_type(expr, AST_Assign):
2323
2731
  left[-1] = left[-1].left
2324
2732
  seq_cdr = await expression(True, no_in)
2325
2733
  return create_assign({
2326
2734
  'start': start,
2327
- 'left': (left[0] if left.length is 1 else new AST_Array({
2328
- 'elements': left
2329
- })),
2735
+ 'left': (
2736
+ left[0] if left.length is 1
2737
+ else new AST_Array({'elements': left})
2738
+ ),
2330
2739
  'operator': expr.operator,
2331
2740
  'right': new AST_Seq({
2332
- 'car': expr.right,
2333
- 'cdr': seq_cdr
2741
+ 'car': expr.right, 'cdr': seq_cdr
2334
2742
  }),
2335
2743
  'end': peek()
2336
2744
  })
@@ -2378,10 +2786,15 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
2378
2786
  raise
2379
2787
  else:
2380
2788
  element = await statement()
2381
- if first_token and is_node_type(element, AST_Directive) and element.value.indexOf('#!') is 0:
2789
+ if first_token and is_node_type(
2790
+ element,
2791
+ AST_Directive
2792
+ ) and element.value.indexOf('#!') is 0:
2382
2793
  shebang = element.value
2383
2794
  else:
2384
- ds = not toplevel and is_docstring(element) # do not process strings as docstrings if we are concatenating toplevels
2795
+ # do not process strings as docstrings if we are
2796
+ # concatenating toplevels
2797
+ ds = not toplevel and is_docstring(element)
2385
2798
  if ds:
2386
2799
  docstrings.push(ds)
2387
2800
  else:
@@ -2404,17 +2817,21 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
2404
2817
 
2405
2818
  if options.recover_errors:
2406
2819
  # Combine parser-level recovered errors with any collected by the
2407
- # tokenizer (e.g. skipped unexpected characters) for the LSP to report.
2820
+ # tokenizer (e.g. skipped unexpected characters) for the
2821
+ # LSP to report.
2408
2822
  recovered = S.recovered_errors
2409
2823
  try:
2410
2824
  tok_ctx = S.input.context()
2411
- if tok_ctx and tok_ctx.recovered_errors and tok_ctx.recovered_errors.length:
2825
+ if (tok_ctx and tok_ctx.recovered_errors
2826
+ and tok_ctx.recovered_errors.length):
2412
2827
  recovered = recovered.concat(tok_ctx.recovered_errors)
2413
2828
  except:
2414
2829
  pass
2415
2830
  toplevel.recovered_errors = recovered
2416
2831
 
2417
- toplevel.nonlocalvars = scan_for_nonlocal_defs(toplevel.body).concat(S.globals)
2832
+ toplevel.nonlocalvars = scan_for_nonlocal_defs(
2833
+ toplevel.body
2834
+ ).concat(S.globals)
2418
2835
  toplevel.localvars = []
2419
2836
  toplevel.exports = []
2420
2837
  seen_exports = {}
@@ -2445,16 +2862,23 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
2445
2862
  importing_modules[module_id] = False
2446
2863
  toplevel.comments_after = S.token.comments_before or v'[]'
2447
2864
 
2448
- if options._src_hash and options.filename and module_id is not '__main__':
2865
+ if (options._src_hash and options.filename
2866
+ and module_id is not '__main__'):
2449
2867
  try:
2450
- # Simplified class info (no full AST nodes) for lazy-shell reconstruction.
2868
+ # Simplified class info (no full AST nodes) for
2869
+ # lazy-shell reconstruction.
2451
2870
  classes_cache = {}
2452
2871
  for cname in Object.keys(toplevel.classes or {}):
2453
2872
  cls = toplevel.classes[cname]
2454
- classes_cache[cname] = {'static': cls.static or {}, 'bound': cls.bound or [], 'classvars': cls.classvars or {}}
2873
+ classes_cache[cname] = {
2874
+ 'static': cls.static or {},
2875
+ 'bound': cls.bound or [],
2876
+ 'classvars': cls.classvars or {},
2877
+ }
2455
2878
  # Single pass: compute has_side_effects + tree-shaking index.
2456
2879
  # The index lets the tree-shaker resolve the fixpoint iteration
2457
- # (steps 4-5) without accessing mod.body — no AST deserialization
2880
+ # (steps 4-5) without accessing mod.body — no AST
2881
+ # deserialization
2458
2882
  # until step 6 (pruning), which needs actual nodes anyway.
2459
2883
  has_se = False
2460
2884
  idx_exec_refs_set = {}
@@ -2468,26 +2892,50 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
2468
2892
  node.walk(new TreeWalker(_rv))
2469
2893
 
2470
2894
  for idx_stmt in toplevel.body:
2471
- if is_node_type(idx_stmt, AST_Function) or is_node_type(idx_stmt, AST_Class):
2895
+ if is_node_type(
2896
+ idx_stmt,
2897
+ AST_Function
2898
+ ) or is_node_type(idx_stmt, AST_Class):
2472
2899
  if idx_stmt.name:
2473
2900
  idx_pinned = False
2474
2901
  if idx_stmt.decorators:
2475
2902
  for idx_dec in idx_stmt.decorators:
2476
- if idx_dec.expression and is_node_type(idx_dec.expression, AST_SymbolRef) and idx_dec.expression.name == 'no_prune':
2903
+ if idx_dec.expression and is_node_type(
2904
+ idx_dec.expression,
2905
+ AST_SymbolRef
2906
+ ) and idx_dec.expression.name == 'no_prune':
2477
2907
  idx_pinned = True
2478
2908
  break
2479
2909
  idx_def_refs = {}
2480
2910
  _collect_refs_into(idx_stmt, idx_def_refs)
2481
- idx_top_defs[idx_stmt.name.name] = {'pinned': idx_pinned, 'refs': Object.keys(idx_def_refs)}
2911
+ idx_top_defs[idx_stmt.name.name] = {
2912
+ 'pinned': idx_pinned,
2913
+ 'refs': Object.keys(idx_def_refs),
2914
+ }
2482
2915
  elif is_node_type(idx_stmt, AST_Imports):
2483
2916
  for idx_imp in idx_stmt.imports:
2484
2917
  if idx_imp.argnames and idx_imp.argnames.length:
2485
2918
  for idx_arg in idx_imp.argnames:
2486
- idx_local = idx_arg.alias.name if idx_arg.alias else idx_arg.name
2487
- idx_import_bindings[idx_local] = {'source': idx_imp.key, 'imported_name': idx_arg.name, 'is_namespace': False}
2919
+ idx_local = (
2920
+ idx_arg.alias.name
2921
+ if idx_arg.alias else idx_arg.name
2922
+ )
2923
+ idx_import_bindings[idx_local] = {
2924
+ 'source': idx_imp.key,
2925
+ 'imported_name': idx_arg.name,
2926
+ 'is_namespace': False,
2927
+ }
2488
2928
  else:
2489
- idx_local = idx_imp.alias.name if idx_imp.alias else idx_imp.key.split('.')[0]
2490
- idx_import_bindings[idx_local] = {'source': idx_imp.key, 'imported_name': None, 'is_namespace': True}
2929
+ idx_local = (
2930
+ idx_imp.alias.name
2931
+ if idx_imp.alias
2932
+ else idx_imp.key.split('.')[0]
2933
+ )
2934
+ idx_import_bindings[idx_local] = {
2935
+ 'source': idx_imp.key,
2936
+ 'imported_name': None,
2937
+ 'is_namespace': True,
2938
+ }
2491
2939
  else:
2492
2940
  if not has_se:
2493
2941
  se_found = v'[false]'
@@ -2516,12 +2964,22 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
2516
2964
  'top_defs': idx_top_defs,
2517
2965
  },
2518
2966
  }
2519
- if options._file_mtime is not None and options._file_mtime is not undefined:
2967
+ if (options._file_mtime is not None
2968
+ and options._file_mtime is not undefined):
2520
2969
  cache_meta['mtime'] = options._file_mtime
2521
- # Binary format: metadata JSON followed by newline and binary AST pool.
2522
- await writefile(cache_file_name(options.filename, options.module_cache_dir), encode_cache(JSON.stringify(cache_meta), toplevel))
2970
+ # Binary format: metadata JSON followed by newline
2971
+ # and binary AST pool.
2972
+ await writefile(
2973
+ cache_file_name(options.filename, options.module_cache_dir),
2974
+ encode_cache(JSON.stringify(cache_meta), toplevel)
2975
+ )
2523
2976
  except as e:
2524
- console.error('Failed to write AST cache file:', options.filename, 'with error:', e)
2977
+ console.error(
2978
+ 'Failed to write AST cache file:',
2979
+ options.filename,
2980
+ 'with error:',
2981
+ e
2982
+ )
2525
2983
 
2526
2984
  return toplevel
2527
2985
 
@@ -2533,13 +2991,18 @@ async def parse(text, options):
2533
2991
  'filename': None, # name of the file being parsed
2534
2992
  'module_id': '__main__', # The id of the module being parsed
2535
2993
  'toplevel': None,
2536
- 'for_linting': False, # If True certain actions are not performed, such as importing modules
2994
+ # If True certain actions are not performed, such as importing modules
2995
+ 'for_linting': False,
2537
2996
  'import_dirs': v'[]',
2538
- 'classes': undefined, # Map of class names to AST_Class that are available in the global namespace (used by the REPL)
2997
+ # Map of class names to AST_Class that are available in the
2998
+ # global namespace (used by the REPL)
2999
+ 'classes': undefined,
2539
3000
  'scoped_flags': {}, # Global scoped flags (used by the REPL)
2540
3001
  'discard_asserts': False,
2541
3002
  'module_cache_dir': '',
2542
- 'recover_errors': False, # When True, continue parsing past syntax errors (used by the LSP). See run_parser/block_.
3003
+ # When True, continue parsing past syntax errors (used by the
3004
+ # LSP). See run_parser/block_.
3005
+ 'recover_errors': False,
2543
3006
  })
2544
3007
  import_dirs = [x for x in options.import_dirs]
2545
3008
  for location in v'[options.libdir, options.basedir]':
@@ -2550,16 +3013,21 @@ async def parse(text, options):
2550
3013
  imported_module_ids = []
2551
3014
  imported_modules = options.imported_modules or {}
2552
3015
  importing_modules = options.importing_modules or {}
2553
- # loading_promises tracks modules currently being loaded across the entire compilation.
2554
- # It is shared by passing it through options so parallel sub-parse() calls all see it.
3016
+ # loading_promises tracks modules currently being loaded across the
3017
+ # entire compilation.
3018
+ # It is shared by passing it through options so parallel sub-parse()
3019
+ # calls all see it.
2555
3020
  if not options.loading_promises:
2556
3021
  options.loading_promises = {}
2557
3022
  importing_modules[module_id] = True
2558
3023
 
2559
3024
  # The internal state of the parser
2560
3025
  S = {
2561
- 'input': tokenizer(text, options.filename, options.recover_errors) if jstype(text) is 'string' else text,
2562
- 'recovered_errors': v'[]', # syntax errors swallowed during recovery (recover_errors mode only)
3026
+ 'input': tokenizer(
3027
+ text, options.filename, options.recover_errors
3028
+ ) if jstype(text) is 'string' else text,
3029
+ # syntax errors swallowed during recovery (recover_errors mode only)
3030
+ 'recovered_errors': v'[]',
2563
3031
  'token': None,
2564
3032
  'prev': None,
2565
3033
  'peeked': [],
@@ -2595,9 +3063,22 @@ async def parse(text, options):
2595
3063
  if options.classes:
2596
3064
  for cname in options.classes:
2597
3065
  obj = options.classes[cname]
2598
- S.classes[0][cname] = {'static': obj.static, 'bound': obj.bound, 'classvars': obj.classvars}
3066
+ S.classes[0][cname] = {
3067
+ 'static': obj.static,
3068
+ 'bound': obj.bound,
3069
+ 'classvars': obj.classvars,
3070
+ }
2599
3071
 
2600
3072
  if jstype(text) is 'string' and not options._src_hash:
2601
3073
  options._src_hash = sha1sum(text)
2602
3074
 
2603
- return await create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_ids, imported_modules, importing_modules, options)()
3075
+ return await create_parser_ctx(
3076
+ S,
3077
+ import_dirs,
3078
+ module_id,
3079
+ baselib_items,
3080
+ imported_module_ids,
3081
+ imported_modules,
3082
+ importing_modules,
3083
+ options
3084
+ )()