11# -*- coding: utf-8 -*-
2+ """Back-port compiler for Python 3.8 assignment expressions."""
23
34import argparse
45import glob
6+ import io
57import locale
68import os
79import re
3133 del multiprocessing
3234
3335# version string
34- __version__ = '0.1.1 '
36+ __version__ = '0.1.2 '
3537
3638# from configparser
3739BOOLEAN_STATES = {'1' : True , '0' : False ,
@@ -132,7 +134,7 @@ def __walrus_wrapper_%(name)s_%(uuid)s(expr):
132134''' .splitlines () # `str.splitlines` will remove trailing newline
133135
134136# special template for lambda
135- LAMBDA_CALL_TEMPLATE = '__walrus_wrapper_lambda_%(uuid)s(%(param)s) '
137+ LAMBDA_CALL_TEMPLATE = '__walrus_wrapper_lambda_%(uuid)s'
136138LAMBDA_FUNC_TEMPLATE = '''\
137139 def __walrus_wrapper_lambda_%(uuid)s(%(param)s):
138140%(tabsize)s"""Wrapper function for lambda definitions."""
@@ -332,12 +334,13 @@ def _process(self, node):
332334 # leaf node
333335 self += node .get_code ()
334336
335- def _process_suite_node (self , node , func = False , cls_ctx = None ):
337+ def _process_suite_node (self , node , func = False , raw = False , cls_ctx = None ):
336338 """Process indented suite (`suite` or ...).
337339
338340 Args:
339341 - `node` -- `Union[parso.python.tree.PythonNode, parso.python.tree.PythonLeaf]`, suite node
340342 - `func` -- `bool`, if the suite is of function definition
343+ - `raw` -- `bool`, raw processing flag
341344 - `cls_ctx` -- `Optional[str]`, class name when suite if of class contextion
342345
343346 """
@@ -357,15 +360,20 @@ def _process_suite_node(self, node, func=False, cls_ctx=None):
357360 if cls_ctx is None :
358361 ctx = Context (node = node , context = self ._context ,
359362 column = indent , tabsize = self ._tabsize ,
360- linesep = self ._linesep , keyword = keyword )
363+ linesep = self ._linesep , keyword = keyword , raw = raw )
361364 else :
362365 ctx = ClassContext (cls_ctx = cls_ctx ,
363366 node = node , context = self ._context ,
364367 column = indent , tabsize = self ._tabsize ,
365- linesep = self ._linesep , keyword = keyword )
368+ linesep = self ._linesep , keyword = keyword , raw = raw )
369+ self += ctx .string .lstrip ()
366370
371+ # keep records
372+ if raw :
373+ self ._lamb .extend (ctx .lambdef )
374+ self ._vars .extend (ctx .variables )
375+ self ._func .extend (ctx .functions )
367376 self ._context .extend (ctx .global_stmt )
368- self += ctx .string .lstrip ()
369377
370378 def _process_namedexpr_test (self , node ):
371379 """Process assignment expression (`namedexpr_test`).
@@ -529,11 +537,32 @@ def _process_lambdef(self, node):
529537 self += node .get_code ()
530538 return
531539
532- ctx = LambdaContext (node = node , column = self ._column ,
533- tabsize = self ._tabsize , linesep = self ._linesep ,
534- keyword = self ._keyword , context = self ._context )
535- self ._lamb .extend (ctx .lambdef )
536- self += ctx .string .lstrip ()
540+ children = iter (node .children )
541+
542+ # <Keyword: lambda>
543+ next (children )
544+
545+ # vararglist
546+ para_list = list ()
547+ for child in children :
548+ if child .type == 'operator' and child .value == ':' :
549+ break
550+ para_list .append (child )
551+ param = '' .join (map (lambda n : n .get_code (), para_list ))
552+
553+ # test_nocond | test
554+ indent = self ._column + self ._tabsize
555+ ctx = LambdaContext (node = next (children ), context = self ._context ,
556+ column = indent , tabsize = self ._tabsize ,
557+ linesep = self ._linesep , keyword = 'nonlocal' )
558+ suite = ctx .string .strip ()
559+
560+ # keep record
561+ nuid = uuid_gen .gen ()
562+ self ._lamb .append (dict (param = param , suite = suite , uuid = nuid ))
563+
564+ # replacing lambda
565+ self += LAMBDA_CALL_TEMPLATE % dict (uuid = nuid )
537566
538567 def _process_if_stmt (self , node ):
539568 """Process if statement (``if_stmt``).
@@ -723,7 +752,7 @@ def _concat(self):
723752
724753 # first, the prefix codes
725754 self ._buffer += self ._prefix + prefix
726- if flag and self ._linting and self ._vars and self . _buffer :
755+ if flag and self ._linting and self ._buffer :
727756 if (self ._node_before_walrus is not None \
728757 and self ._node_before_walrus .type in ('funcdef' , 'classdef' ) \
729758 and self ._column == 0 ):
@@ -746,26 +775,27 @@ def _concat(self):
746775 '%s%s' % (self ._linesep , indent )
747776 ).join (NAME_TEMPLATE ) % dict (tabsize = tabsize , name_list = name_list ) + self ._linesep
748777 for func in sorted (self ._func , key = lambda func : func ['name' ]):
749- self ._buffer += linesep + indent + (
778+ if self ._buffer :
779+ self ._buffer += linesep
780+ self ._buffer += indent + (
750781 '%s%s' % (self ._linesep , indent )
751782 ).join (FUNC_TEMPLATE ) % dict (tabsize = tabsize , ** func ) + self ._linesep
752783 for lamb in self ._lamb :
753- self ._buffer += linesep + indent + (
784+ if self ._buffer :
785+ self ._buffer += linesep
786+ self ._buffer += indent + (
754787 '%s%s' % (self ._linesep , indent )
755788 ).join (LAMBDA_FUNC_TEMPLATE ) % dict (tabsize = tabsize , ** lamb ) + self ._linesep
756789
757790 # finally, the suffix codes
758- if flag and self ._linting and self . _vars :
791+ if flag and self ._linting :
759792 blank = 2 if self ._column == 0 else 1
760793 self ._buffer += self ._linesep * self .missing_whitespaces (prefix = self ._buffer , suffix = suffix ,
761794 blank = blank , linesep = self ._linesep )
762795 self ._buffer += suffix
763796
764797 def _strip (self ):
765- """Strip comments from string.
766-
767- Args:
768- - `string` -- `str`, buffer string
798+ """Strip comments from suffix buffer.
769799
770800 Returns:
771801 - `str` -- prefix comments
@@ -775,7 +805,7 @@ def _strip(self):
775805 prefix = ''
776806 suffix = ''
777807
778- lines = iter (self ._suffix . splitlines ( True ) )
808+ lines = io . StringIO (self ._suffix , newline = self . _linesep )
779809 for line in lines :
780810 if line .strip ().startswith ('#' ):
781811 prefix += line
@@ -979,40 +1009,46 @@ def extract_whitespaces(node):
9791009
9801010
9811011class LambdaContext (Context ):
982- """Lambda (lambdef) conversion context."""
983-
984- def _process_lambdef (self , node ):
985- """Process lambda definition (``lambdef``).
986-
987- Args:
988- - `node` -- `parso.python.tree.Lambda`, lambda node
989-
990- """
991- children = iter (node .children )
992-
993- # <Keyword: lambda>
994- next (children )
1012+ """Lambda (suite) conversion context."""
9951013
996- # vararglist
997- para_list = list ()
998- for child in children :
999- if child .type == 'operator' and child .value == ':' :
1000- break
1001- para_list .append (child )
1002- param = '' .join (map (lambda n : n .get_code (), para_list ))
1014+ def _concat (self ):
1015+ """Concatenate final string."""
1016+ flag = self .has_walrus (self ._root )
10031017
1004- # test_nocond | test
1005- # test_node = parso.python.tree.ExprStmt([parso.python.tree.Name('lambdef', (0, 0)),
1006- # parso.python.tree.Operator('=', (0, 0)),
1007- # next(children)])
1008- # suite = self._process_suite_node(next(children), func=True, buffer=True)
1018+ # first, the variables and functions
1019+ indent = '\t ' .expandtabs (self ._column )
1020+ tabsize = '\t ' .expandtabs (self ._tabsize )
1021+ if self ._linting :
1022+ linesep = self ._linesep * (1 if self ._column > 0 else 2 )
1023+ else :
1024+ linesep = ''
1025+ if self ._vars :
1026+ name_list = ' = ' .join (sorted (set (self ._vars )))
1027+ self ._buffer += indent + (
1028+ '%s%s' % (self ._linesep , indent )
1029+ ).join (NAME_TEMPLATE ) % dict (tabsize = tabsize , name_list = name_list ) + self ._linesep
1030+ for func in sorted (self ._func , key = lambda func : func ['name' ]):
1031+ if self ._buffer :
1032+ self ._buffer += linesep
1033+ self ._buffer += indent + (
1034+ '%s%s' % (self ._linesep , indent )
1035+ ).join (FUNC_TEMPLATE ) % dict (tabsize = tabsize , ** func ) + self ._linesep
1036+ for lamb in self ._lamb :
1037+ if self ._buffer :
1038+ self ._buffer += linesep
1039+ self ._buffer += indent + (
1040+ '%s%s' % (self ._linesep , indent )
1041+ ).join (LAMBDA_FUNC_TEMPLATE ) % dict (tabsize = tabsize , ** lamb ) + self ._linesep
1042+ if flag and self ._linting :
1043+ blank = 2 if self ._column == 0 else 1
1044+ self ._buffer += self ._linesep * self .missing_whitespaces (prefix = self ._buffer , suffix = self ._prefix ,
1045+ blank = blank , linesep = self ._linesep )
10091046
1010- # keep record
1011- nuid = uuid_gen .gen ()
1012- # self._lamb.append(dict(param=param, suite=suite, uuid=nuid))
1047+ # then, the `return` statement
1048+ self ._buffer += indent + 'return'
10131049
1014- # replacing lambda
1015- self += LAMBDA_CALL_TEMPLATE % dict ( param = param , uuid = nuid )
1050+ # finally, the source codes
1051+ self . _buffer += self . _prefix + self . _suffix
10161052
10171053
10181054class ClassContext (Context ):
@@ -1022,22 +1058,23 @@ class ClassContext(Context):
10221058 def cls_var (self ):
10231059 return self ._cls_var
10241060
1025- def __init__ (self , cls_ctx , node ,
1061+ def __init__ (self , node ,
1062+ cls_ctx , cls_var = None ,
10261063 column = 0 , tabsize = None ,
10271064 linesep = None , keyword = None ,
1028- context = None , raw = False , cls_var = None ):
1065+ context = None , raw = False ):
10291066 """Conversion context.
10301067
10311068 Args:
1032- - `cls_ctx` -- `str`, class context name
10331069 - `node` -- `Union[parso.python.tree.PythonNode, parso.python.tree.PythonLeaf]`, parso AST
1070+ - `cls_ctx` -- `str`, class context name
1071+ - `cls_var` -- `Dict[str, str]`, mapping for assignment variable and its UUID
10341072 - `column` -- `int`, current indentation level
10351073 - `tabsize` -- `Optional[int]`, indentation tab size
10361074 - `linesep` -- `Optional[str]`, line seperator
10371075 - `keyword` -- `Optional[str]`, keyword for wrapper function
10381076 - `context` -- `Optional[List[str]]`, global context
10391077 - `raw` -- `bool`, raw context processing flag
1040- - `cls_var` -- `Dict[str, str]`, mapping for assignment variable and its UUID
10411078
10421079 Envs:
10431080 - `WALRUS_LINESEP` -- line separator to process source files (same as `--linesep` option in CLI)
@@ -1056,12 +1093,13 @@ def __init__(self, cls_ctx, node,
10561093 column = column , tabsize = tabsize ,
10571094 linesep = linesep , keyword = keyword , raw = raw )
10581095
1059- def _process_suite_node (self , node , func = False , cls_ctx = None ):
1096+ def _process_suite_node (self , node , func = False , raw = False , cls_ctx = None ):
10601097 """Process indented suite (`suite` or ...).
10611098
10621099 Args:
10631100 - `node` -- `Union[parso.python.tree.PythonNode, parso.python.tree.PythonLeaf]`, suite node
10641101 - `func` -- `bool`, if the suite is of function definition
1102+ - `raw` -- `bool`, raw context processing flag
10651103 - `cls_ctx` -- `Optional[str]`, class name when suite if of class contextion
10661104
10671105 """
@@ -1091,8 +1129,14 @@ def _process_suite_node(self, node, func=False, cls_ctx=None):
10911129 node = node , context = self ._context ,
10921130 column = indent , tabsize = self ._tabsize ,
10931131 linesep = self ._linesep , keyword = keyword )
1094-
10951132 self += ctx .string .lstrip ()
1133+
1134+ # keep record
1135+ if raw :
1136+ self ._lamb .extend (ctx .lambdef )
1137+ self ._vars .extend (ctx .variables )
1138+ self ._func .extend (ctx .functions )
1139+ self ._cls_var .update (ctx .cls_var )
10961140 self ._context .extend (ctx .global_stmt )
10971141
10981142 def _process_namedexpr_test (self , node ):
@@ -1113,6 +1157,7 @@ def _process_namedexpr_test(self, node):
11131157 column = self ._column , tabsize = self ._tabsize ,
11141158 linesep = self ._linesep , keyword = self ._keyword , raw = True )
11151159 expr = ctx .string .strip ()
1160+ self ._lamb .extend (ctx .lambdef )
11161161 self ._vars .extend (ctx .variables )
11171162 self ._func .extend (ctx .functions )
11181163 self ._cls_var .update (ctx .cls_var )
@@ -1214,7 +1259,9 @@ def _concat(self):
12141259 '%s%s' % (self ._linesep , indent )
12151260 ).join (CLS_NAME_TEMPLATE ) % dict (tabsize = tabsize , cls = self ._cls_ctx ) + linesep
12161261 for func in sorted (self ._func , key = lambda func : func ['name' ]):
1217- self ._buffer += linesep + indent + (
1262+ if self ._buffer :
1263+ self ._buffer += linesep
1264+ self ._buffer += indent + (
12181265 '%s%s' % (self ._linesep , indent )
12191266 ).join (CLS_FUNC_TEMPLATE ) % dict (tabsize = tabsize , cls = self ._cls_ctx , ** func ) + linesep
12201267
0 commit comments