def testFixIsFrozen(embed_data): """ General test for tbe "tf is-frozen" command. """ filename = embed_data['testFixIsFrozen.py'] data_dir = embed_data.get_data_dir() original = """ import coilib50 from coilib50.basic import property if coilib50.IsFrozen(): print "Frozen" property.Create('') """ assert CreateFile(filename, dedent(original), encoding='UTF-8') app.TestScript( dedent(""" >terraformer fix-is-frozen %(filename)s - %(filename)s """ % locals())) assert GetFileContents(filename, encoding='UTF-8') == dedent(""" from ben10 import property_ from ben10.foundation.is_frozen import IsFrozen import coilib50 from coilib50.basic import property if IsFrozen(): print "Frozen" property_.Create('') """)
def testSymbols(embed_data): """ Test tf symbols command. This command is a WIP and should grow as "tf" interprets more and more symbols from python modules. """ filename = embed_data['testSymbols.py_'] original = """ import alpha class Alpha(object): def Method(self): pass def Function(): pass """ assert CreateFile(filename, dedent(original), encoding='UTF-8') app.TestScript( dedent(""" >terraformer symbols %(filename)s 1: IMPORT alpha """ % locals()))
def testSymbols(embed_data): """ Test tf symbols command. This command is a WIP and should grow as "tf" interprets more and more symbols from python modules. """ filename = embed_data['testSymbols.py_'] original = """ import alpha class Alpha(object): def Method(self): pass def Function(): pass """ assert CreateFile(filename, dedent(original), encoding='UTF-8') app.TestScript( dedent( """ >terraformer symbols %(filename)s 1: IMPORT alpha """ % locals() ) )
def test_dedent10(): """ Checking how dedent handles empty lines at the end of string without parameters. """ string = dedent( """ alpha """ ) assert string == 'alpha' string = dedent( """ alpha """ ) assert string == 'alpha\n' string = dedent( """ alpha """ ) assert string == 'alpha\n\n'
def test_fix_format_error(embed_data): """ Check _FixFormat error output (detailed traceback). """ filename = embed_data['test_fix_format_error.py'] data_dir = embed_data.get_data_dir() original = """ import zulu from bravo import Bravo import alpha class Alpha(object): def Method(self) pass def Function(): pass """ assert CreateFile(filename, dedent(original), encoding='UTF-8') app.TestScript(dedent(""" >>>terraformer fix-format --single-job --traceback-limit=0 %(data_dir)s - %(filename)s: ERROR: \b\b On TerraForming.ReorganizeImports with filename: %(filename)s Had problems parsing: > import zulu > from bravo import Bravo > import alpha >\b > class Alpha(object): >\b > def Method(self) > pass >\b > def Function(): > pass bad input: type=4, value=u'\\r\\n', context=('', (7, 20)) --- * --- """ % locals()).replace('\b', ' '), input_prefix='>>>') assert GetFileContents(filename, encoding='UTF-8') == dedent(""" import zulu from bravo import Bravo import alpha class Alpha(object): def Method(self) pass def Function(): pass """)
def testFixFormat(embed_data): """ General test for tbe "tf fix-format" command. This is a smoke test for the command interaction since most of the real testing is done on pytest_terra_former.py """ filename = embed_data['testFixFormat.py'] data_dir = embed_data.get_data_dir() original = """ import zulu from bravo import Bravo import alpha class Alpha(object): def Method(self): pass def Function(): pass """ assert CreateFile(filename, dedent(original), encoding='UTF-8') app.TestScript( dedent( """ >terraformer fix-format --single-job %(data_dir)s - %(filename)s: FIXED """ % locals() ) ) assert GetFileContents(filename, encoding='UTF-8') == dedent( """ from bravo import Bravo import alpha import zulu class Alpha(object): def Method(self): pass def Function(): pass """ )
def TestIt(input, symbols, expected, import_blocks): input = dedent(input) expected = dedent(expected) + '\n' terra_former = TerraFormer(input) for i_symbol in symbols: terra_former.AddImportSymbol(i_symbol) terra_former.ReorganizeImports() # Make sure that creating a TerraFormer won't make any changes to the # AST assert terra_former.GenerateSource() == expected assert list(map(str, terra_former.import_blocks)) == import_blocks
def TestFixEncoding(original, expected, encoding, lineno=0): filename = embed_data['testFixEncoding.py_'] assert CreateFile(filename, dedent(original), encoding=encoding) app.TestScript( dedent(""" >terraformer fix-encoding %(filename)s - %(filename)s: %(encoding)s (line:%(lineno)s) """ % locals())) obtained = GetFileContents(filename, encoding='UTF-8') assert obtained == dedent(expected)
def test_dedent11(): """ Check calling dedent more than once. """ string = dedent(""" alpha bravo charlie """) assert string == 'alpha\nbravo\ncharlie' string = dedent(string) assert string == 'alpha\nbravo\ncharlie' string = dedent(string) assert string == 'alpha\nbravo\ncharlie'
def testAddImportSymbol(embed_data): """ General test for the "tf add-import-symbol" command. """ filename = embed_data['testFixFormat.py'] data_dir = embed_data.get_data_dir() original = """ import zulu from bravo import Bravo import alpha class Alpha(object): def Method(self): pass def Function(): pass """ assert CreateFile(filename, dedent(original), encoding='UTF-8') app.TestScript( dedent( """ >terraformer add-import-symbol --single-job "__future__.unicode_literals" %(filename)s - %(filename)s: FIXED """ % locals() ) ) assert GetFileContents(filename, encoding='UTF-8') == dedent( """ from __future__ import unicode_literals from bravo import Bravo import alpha import zulu class Alpha(object): def Method(self): pass def Function(): pass """ )
def test_dedent4(): string = dedent(""" oneline tabbed detabbed """) assert string == 'oneline\n tabbed\ndetabbed'
def testDocs(): """ Test "tf" API by printing the general documentation. """ app.TestScript( dedent( """ >terraformer Usage: terraformer <subcommand> [options] Commands: symbols List all symbols in the given python source code. Currently only lists IMPORTS. fix-format Perform the format fixes on sources files, including tabs, eol, eol-spaces and imports. add-import-symbol Adds an import-symbol in all files. fix-commit Perform the format fixes on sources files on a git repository modified files. fix-is-frozen Fix some pre-determinated set of symbols usage with the format: fix-encoding Fix python module files encoding, converting all non-ascii encoded files to UTF-8. fix-stringio Fix StringIO usage. """ ) )
def testFixtureDecorator(self): app = App('test', color=False, buffered_console=True) @app.Fixture def Alpha(): return 'alpha' @app.Fixture() def Bravo(): return 'bravo' def Command(console_, alpha_, bravo_): console_.Print('The names are: %(alpha_)s and %(bravo_)s.' % locals()) app.Add(Command) self._TestMain( app, 'command', dedent( ''' The names are: alpha and bravo. ''' ) )
def testColor(self): app = App('test', color=True, buffered_console=True) assert app.console.color == True def Case(): ''' This is Case. ''' app.Add(Case) self._TestMain( app, '', dedent( ''' Usage: test <subcommand> [options] Commands: %(teal)scase%(reset)s This is Case. ''' % Console.COLOR_CODES ) )
def test_dedent1(): string = dedent( """ oneline """ ) assert string == 'oneline'
def test_dedent11(): """ Check calling dedent more than once. """ string = dedent( """ alpha bravo charlie """ ) assert string == 'alpha\nbravo\ncharlie' string = dedent(string) assert string == 'alpha\nbravo\ncharlie' string = dedent(string) assert string == 'alpha\nbravo\ncharlie'
def test_dedent6(): string = dedent( """ oneline """, ignore_last_linebreak=False ) assert string == 'oneline\n'
def test_dedent5(): string = dedent( """ oneline """, ignore_first_linebreak=False ) assert string == '\noneline'
def test_dedent3(): string = dedent( """ oneline tabbed """ ) assert string == 'oneline\n tabbed'
def test_dedent2(): string = dedent( """ oneline twoline """ ) assert string == 'oneline\ntwoline'
def testFixFormat(embed_data): """ General test for tbe "tf fix-format" command. This is a smoke test for the command interaction since most of the real testing is done on pytest_terra_former.py """ filename = embed_data['testFixFormat.py'] data_dir = embed_data.get_data_dir() original = """ import zulu from bravo import Bravo import alpha class Alpha(object): def Method(self): pass def Function(): pass """ assert CreateFile(filename, dedent(original), encoding='UTF-8') app.TestScript( dedent(""" >terraformer fix-format --single-job %(data_dir)s - %(filename)s: FIXED """ % locals())) assert GetFileContents(filename, encoding='UTF-8') == dedent(""" from bravo import Bravo import alpha import zulu class Alpha(object): def Method(self): pass def Function(): pass """)
def test_dedent9(): """ Test behavior when using \t at the start of a string. .. seealso:: BEN-21 @ JIRA """ string = dedent(""" alpha \tbravo """) assert string == ' alpha\n\tbravo'
def testAddImportSymbol(embed_data): """ General test for the "tf add-import-symbol" command. """ filename = embed_data['testFixFormat.py'] data_dir = embed_data.get_data_dir() original = """ import zulu from bravo import Bravo import alpha class Alpha(object): def Method(self): pass def Function(): pass """ assert CreateFile(filename, dedent(original), encoding='UTF-8') app.TestScript( dedent(""" >terraformer add-import-symbol --single-job "__future__.unicode_literals" %(filename)s - %(filename)s: FIXED """ % locals())) assert GetFileContents(filename, encoding='UTF-8') == dedent(""" from __future__ import unicode_literals from bravo import Bravo import alpha import zulu class Alpha(object): def Method(self): pass def Function(): pass """)
def Execute(cmd, expected_output, expected_retcode): obtained_retcode, obtained = self.TestCall(cmd) obtained_string = obtained.rstrip('\n') + '\n' expected_string = expected_output.rstrip('\n') + '\n' assert obtained_string == expected_string assert expected_retcode == obtained_retcode, dedent(''' >>> %(cmd)s Command finished with return code "%(obtained_retcode)s", was expecting "%(expected_retcode)s" Use ">>>my_command [retcode=X]" syntax to define the expected return code. ''' % locals())
def test_dedent10(): """ Checking how dedent handles empty lines at the end of string without parameters. """ string = dedent(""" alpha """) assert string == 'alpha' string = dedent(""" alpha """) assert string == 'alpha\n' string = dedent(""" alpha """) assert string == 'alpha\n\n'
def test_dedent8(): """ Test not the first line in the right indent. """ string = dedent(""" alpha bravo charlie """) assert string == ' alpha\n bravo\ncharlie'
def test_dedent9(): """ Test behavior when using \t at the start of a string. .. seealso:: BEN-21 @ JIRA """ string = dedent( """ alpha \tbravo """ ) assert string == ' alpha\n\tbravo'
def test_dedent7(): """ Test a string that has an 'empty line' with 4 spaces above indent level """ # Using a trick to avoid auto-format to remove the empty spaces. string = dedent(""" line %s other_line """ % ' ') assert string == 'line\n \nother_line'
def Execute(cmd, expected_output, expected_retcode): obtained_retcode, obtained = self.TestCall(cmd) obtained_string = obtained.rstrip('\n') + '\n' expected_string = expected_output.rstrip('\n') + '\n' assert obtained_string == expected_string assert expected_retcode == obtained_retcode, dedent( ''' >>> %(cmd)s Command finished with return code "%(obtained_retcode)s", was expecting "%(expected_retcode)s" Use ">>>my_command [retcode=X]" syntax to define the expected return code. ''' % locals() )
def TestFixEncoding(original, expected, encoding, lineno=0): filename = embed_data['testFixEncoding.py_'] assert CreateFile( filename, dedent(original), encoding=encoding ) app.TestScript( dedent( """ >terraformer fix-encoding %(filename)s - %(filename)s: %(encoding)s (line:%(lineno)s) """ % locals() ) ) obtained = GetFileContents(filename, encoding='UTF-8') assert obtained == dedent(expected)
def test_dedent8(): """ Test not the first line in the right indent. """ string = dedent( """ alpha bravo charlie """ ) assert string == ' alpha\n bravo\ncharlie'
def testFixIsFrozen(embed_data): """ General test for tbe "tf is-frozen" command. """ filename = embed_data['testFixIsFrozen.py'] data_dir = embed_data.get_data_dir() original = """ import coilib50 from coilib50.basic import property if coilib50.IsFrozen(): print "Frozen" property.Create('') """ assert CreateFile(filename, dedent(original), encoding='UTF-8') app.TestScript( dedent( """ >terraformer fix-is-frozen %(filename)s - %(filename)s """ % locals() ) ) assert GetFileContents(filename, encoding='UTF-8') == dedent( """ from ben10 import property_ from ben10.foundation.is_frozen import IsFrozen import coilib50 from coilib50.basic import property if IsFrozen(): print "Frozen" property_.Create('') """ )
def test_dedent7(): """ Test a string that has an 'empty line' with 4 spaces above indent level """ # Using a trick to avoid auto-format to remove the empty spaces. string = dedent( """ line %s other_line """ % ' ' ) assert string == 'line\n \nother_line'
def test_django_integration(embed_data): import django import django.template from django.conf import settings from django.template.loader import get_template config = { 'TEMPLATES': [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [ embed_data['includes'] ], 'OPTIONS': { 'context_processors': [ 'django.template.context_processors.debug', 'django.template.context_processors.request', 'django.contrib.auth.context_processors.auth', 'django.contrib.messages.context_processors.messages', 'django.core.context_processors.request' ], 'loaders': [ ( 'pypugly.django.Loader' ) ], }, } ] } settings.configure(**config) django.setup() t = get_template(embed_data['template.lang']) ctx = django.template.Context() result = t.render(ctx) assert result == dedent( ''' <html> <head> <script src="alpha.js" /> </head> <body> <h1>Hello, world!</h1> </body> </html> ''' )
def testUnknownOptionArgs(self): def Command(console_): '' app = App('test', color=False, buffered_console=True) app.Add(Command) app.TestScript( dedent(''' >test command --foo --bar [retcode=1] ERROR: Unrecognized arguments: --foo --bar (no description) Usage: command\s\s Parameters: Options: '''.replace('\s', ' ')))
def testDocs(): """ Test "tf" API by printing the general documentation. """ app.TestScript( dedent(""" >terraformer Usage: terraformer <subcommand> [options] Commands: symbols List all symbols in the given python source code. Currently only lists IMPORTS. fix-format Perform the format fixes on sources files, including tabs, eol, eol-spaces and imports. add-import-symbol Adds an import-symbol in all files. fix-commit Perform the format fixes on sources files on a git repository modified files. fix-is-frozen Fix some pre-determinated set of symbols usage with the format: fix-encoding Fix python module files encoding, converting all non-ascii encoded files to UTF-8. fix-stringio Fix StringIO usage. """))
def test_django_integration(embed_data): import django import django.template from django.conf import settings from django.template.loader import get_template config = { 'TEMPLATES': [{ 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [embed_data['includes']], 'OPTIONS': { 'context_processors': [ 'django.template.context_processors.debug', 'django.template.context_processors.request', 'django.contrib.auth.context_processors.auth', 'django.contrib.messages.context_processors.messages', 'django.core.context_processors.request' ], 'loaders': [('pypugly.django.Loader')], }, }] } settings.configure(**config) django.setup() t = get_template(embed_data['template.lang']) ctx = django.template.Context() result = t.render(ctx) assert result == dedent(''' <html> <head> <script src="alpha.js" /> </head> <body> <h1>Hello, world!</h1> </body> </html> ''')
def testColor(self): app = App('test', color=True, buffered_console=True) assert app.console.color == True def Case(): ''' This is Case. ''' app.Add(Case) self._TestMain( app, '', dedent(''' Usage: test <subcommand> [options] Commands: %(teal)scase%(reset)s This is Case. ''' % Console.COLOR_CODES))
def testUnknownOptionArgs(self): def Command(console_): '' app = App('test', color=False, buffered_console=True) app.Add(Command) app.TestScript(dedent( ''' >test command --foo --bar [retcode=1] ERROR: Unrecognized arguments: --foo --bar (no description) Usage: command\s\s Parameters: Options: '''.replace('\s', ' ') ))
def testFixtureDecorator(self): app = App('test', color=False, buffered_console=True) @app.Fixture def Alpha(): return 'alpha' @app.Fixture() def Bravo(): return 'bravo' def Command(console_, alpha_, bravo_): console_.Print('The names are: %(alpha_)s and %(bravo_)s.' % locals()) app.Add(Command) self._TestMain( app, 'command', dedent(''' The names are: alpha and bravo. '''))
def TestScript(self, script, input_prefix='>'): ''' Executes a test script, containing command calls (prefixed by ">") and expected results. Example: app = App('ii') app = TestScript(dedent( """ > ii list - alpha - bravo """ ) :param unicode string: A multi-line string with command calls and expected results. Consider the following syntax rules: - Lines starting with '>' are command execution (command); - Lines starting with "###" are ignored; - Everything else is expected output of the previous "command"; - Use [retcode=X] syntax to check for non-zero return from a command. ''' def Execute(cmd, expected_output, expected_retcode): obtained_retcode, obtained = self.TestCall(cmd) obtained_string = obtained.rstrip('\n') + '\n' expected_string = expected_output.rstrip('\n') + '\n' assert obtained_string == expected_string assert expected_retcode == obtained_retcode, dedent( ''' >>> %(cmd)s Command finished with return code "%(obtained_retcode)s", was expecting "%(expected_retcode)s" Use ">>>my_command [retcode=X]" syntax to define the expected return code. ''' % locals() ) def GetExpectedReturnCode(input_line): ''' Find the return code we expect from this command. Expected return code must be in format '[retcode=999]' If not specified, we assume that the expected retcode is 0 e.g. >>>DoSomethingThatFails [retcode=1] >>>DoSomethingOk [retcode=0] :param unicode input_line: ''' import re pattern = '\[retcode=(\d+)\]' match = re.search(pattern, input_line) if match: expected_retcode = int(match.groups()[0]) else: expected_retcode = 0 return re.sub(pattern, '', input_line), expected_retcode cmd = None expected_output = '' expected_retcode = 0 script = dedent(script) for i_line in script.splitlines(): if i_line.startswith('###'): continue elif i_line.startswith(input_prefix): if cmd is not None: Execute(cmd, expected_output, expected_retcode) expected_output = '' cmd = i_line[len(input_prefix):] cmd, expected_retcode = GetExpectedReturnCode(cmd) else: expected_output += i_line + '\n' if cmd is not None: Execute(cmd, expected_output, expected_retcode)
def test_dedent0(): string = dedent('oneline') assert string == 'oneline'
def testArguments(self): def Hello(console_, filename, option='yes', no_setup=False, no_default=None, *config): ''' Hello function. This is Hello. :param filename: The name of the file. :param no_setup: False if set :param no_default: Receives None :param config: Configurations ''' console_.Print('%s - %s' % (filename, option)) [console_.Item(i) for i in config] cmd = Command(Hello) assert cmd.names == ['Hello'] assert cmd.description == 'Hello function.' assert cmd.args.keys() == ['console_', 'filename', 'option', 'no_setup', 'no_default', 'config'] assert map(unicode, cmd.args.values()) == [ 'console_', 'filename', 'option=yes', 'no-setup', 'no-default=VALUE', '*config' ] assert map(repr, cmd.args.values()) == [ '<Arg console_>', '<Arg filename>', '<Arg option=yes>', '<Arg no-setup>', '<Arg no-default=VALUE>', '<Arg *config>', ] assert cmd.kwargs is None console = BufferedConsole() cmd.Call( fixtures={'console_' : (lambda:console, lambda:None)}, argd={'filename' : 'alpha.txt', 'config' : ['one', 'two', 'three']} ) assert console.GetOutput() == 'alpha.txt - yes\n- one\n- two\n- three\n' # Ignores all invalid arguments passed to Call. console = BufferedConsole() cmd.Call( fixtures={'console_' : (lambda:console, lambda:None)}, argd={'filename' : 'bravo.txt', 'INVALID' : 'INVALID'} ) assert console.GetOutput() == 'bravo.txt - yes\n' with pytest.raises(InvalidFixture): cmd.Call({}, {'filename' : 'alpha.txt'}) with pytest.raises(TypeError): cmd.Call({'console_' : console}, {}) assert cmd.description == 'Hello function.' assert cmd.long_description == dedent( ''' Hello function. This is Hello. ''' ) assert cmd.FormatHelp() == dedent( ''' Usage: Hello <filename> <*config> [--option=yes],[--no-setup],[--no-default=VALUE] Parameters: filename The name of the file. config Configurations Options: --option (no description) [default: yes] --no-setup False if set --no-default Receives None ''' ) assert cmd.FormatHelp() == dedent( ''' Usage: Hello <filename> <*config> [--option=yes],[--no-setup],[--no-default=VALUE] Parameters: filename The name of the file. config Configurations Options: --option (no description) [default: yes] --no-setup False if set --no-default Receives None ''' ) import argparse parser = argparse.ArgumentParser('TEST') cmd.ConfigureArgumentParser(parser) assert parser.format_help() == dedent( ''' usage: TEST [-h] [--option OPTION] [--no-setup] [--no-default NO_DEFAULT] filename [config [config ...]] positional arguments: filename config optional arguments: -h, --help show this help message and exit --option OPTION --no-setup --no-default NO_DEFAULT ''' )
def test_dedent6(): string = dedent(""" oneline """, ignore_last_linebreak=False) assert string == 'oneline\n'
def test_dedent5(): string = dedent(""" oneline """, ignore_first_linebreak=False) assert string == '\noneline'
def testHelp(self): def TestCmd(console_, first, second, option=1, option_no=False): ''' This is a test. :param first: This is the first parameter. :param second: This is the second and last parameter. :param option: This must be a number. :param option_no: If set, says nop. ''' app = App('test', color=False, buffered_console=True) app.Add(TestCmd) self._TestMain( app, '', dedent(''' Usage: test <subcommand> [options] Commands: test-cmd This is a test. ''')) self._TestMain( app, '--help', dedent(''' Usage: test <subcommand> [options] Commands: test-cmd This is a test. ''')) self._TestMain( app, 'test-cmd --help', dedent(''' This is a test. Usage: test-cmd <first> <second> [--option=1],[--option-no] Parameters: first This is the first parameter. second This is the second and last parameter. Options: --option This must be a number. [default: 1] --option-no If set, says nop. ''')) self._TestMain( app, 'test-cmd', dedent(''' ERROR: Too few arguments. This is a test. Usage: test-cmd <first> <second> [--option=1],[--option-no] Parameters: first This is the first parameter. second This is the second and last parameter. Options: --option This must be a number. [default: 1] --option-no If set, says nop. '''), app.RETCODE_ERROR)
def test_dedent0(): string = dedent('oneline') assert string == 'oneline'
def TestScript(self, script, input_prefix='>'): ''' Executes a test script, containing command calls (prefixed by ">") and expected results. Example: app = App('ii') app = TestScript(dedent( """ > ii list - alpha - bravo """ ) :param unicode string: A multi-line string with command calls and expected results. Consider the following syntax rules: - Lines starting with '>' are command execution (command); - Lines starting with "###" are ignored; - Everything else is expected output of the previous "command"; - Use [retcode=X] syntax to check for non-zero return from a command. ''' def Execute(cmd, expected_output, expected_retcode): obtained_retcode, obtained = self.TestCall(cmd) obtained_string = obtained.rstrip('\n') + '\n' expected_string = expected_output.rstrip('\n') + '\n' assert obtained_string == expected_string assert expected_retcode == obtained_retcode, dedent(''' >>> %(cmd)s Command finished with return code "%(obtained_retcode)s", was expecting "%(expected_retcode)s" Use ">>>my_command [retcode=X]" syntax to define the expected return code. ''' % locals()) def GetExpectedReturnCode(input_line): ''' Find the return code we expect from this command. Expected return code must be in format '[retcode=999]' If not specified, we assume that the expected retcode is 0 e.g. >>>DoSomethingThatFails [retcode=1] >>>DoSomethingOk [retcode=0] :param unicode input_line: ''' import re pattern = '\[retcode=(\d+)\]' match = re.search(pattern, input_line) if match: expected_retcode = int(match.groups()[0]) else: expected_retcode = 0 return re.sub(pattern, '', input_line), expected_retcode cmd = None expected_output = '' expected_retcode = 0 script = dedent(script) for i_line in script.splitlines(): if i_line.startswith('###'): continue elif i_line.startswith(input_prefix): if cmd is not None: Execute(cmd, expected_output, expected_retcode) expected_output = '' cmd = i_line[len(input_prefix):] cmd, expected_retcode = GetExpectedReturnCode(cmd) else: expected_output += i_line + '\n' if cmd is not None: Execute(cmd, expected_output, expected_retcode)
def test_dedent1(): string = dedent(""" oneline """) assert string == 'oneline'
def testArguments(self): def Hello(console_, filename, option='yes', no_setup=False, no_default=None, *config): ''' Hello function. This is Hello. :param filename: The name of the file. :param no_setup: False if set :param no_default: Receives None :param config: Configurations ''' console_.Print('%s - %s' % (filename, option)) [console_.Item(i) for i in config] cmd = Command(Hello) assert cmd.names == ['Hello'] assert cmd.description == 'Hello function.' assert cmd.args.keys() == [ 'console_', 'filename', 'option', 'no_setup', 'no_default', 'config' ] assert map(unicode, cmd.args.values()) == [ 'console_', 'filename', 'option=yes', 'no-setup', 'no-default=VALUE', '*config' ] assert map(repr, cmd.args.values()) == [ '<Arg console_>', '<Arg filename>', '<Arg option=yes>', '<Arg no-setup>', '<Arg no-default=VALUE>', '<Arg *config>', ] assert cmd.kwargs is None console = BufferedConsole() cmd.Call(fixtures={'console_': (lambda: console, lambda: None)}, argd={ 'filename': 'alpha.txt', 'config': ['one', 'two', 'three'] }) assert console.GetOutput( ) == 'alpha.txt - yes\n- one\n- two\n- three\n' # Ignores all invalid arguments passed to Call. console = BufferedConsole() cmd.Call(fixtures={'console_': (lambda: console, lambda: None)}, argd={ 'filename': 'bravo.txt', 'INVALID': 'INVALID' }) assert console.GetOutput() == 'bravo.txt - yes\n' with pytest.raises(InvalidFixture): cmd.Call({}, {'filename': 'alpha.txt'}) with pytest.raises(TypeError): cmd.Call({'console_': console}, {}) assert cmd.description == 'Hello function.' assert cmd.long_description == dedent(''' Hello function. This is Hello. ''') assert cmd.FormatHelp() == dedent(''' Usage: Hello <filename> <*config> [--option=yes],[--no-setup],[--no-default=VALUE] Parameters: filename The name of the file. config Configurations Options: --option (no description) [default: yes] --no-setup False if set --no-default Receives None ''') assert cmd.FormatHelp() == dedent(''' Usage: Hello <filename> <*config> [--option=yes],[--no-setup],[--no-default=VALUE] Parameters: filename The name of the file. config Configurations Options: --option (no description) [default: yes] --no-setup False if set --no-default Receives None ''') import argparse parser = argparse.ArgumentParser('TEST') cmd.ConfigureArgumentParser(parser) assert parser.format_help() == dedent(''' usage: TEST [-h] [--option OPTION] [--no-setup] [--no-default NO_DEFAULT] filename [config [config ...]] positional arguments: filename config optional arguments: -h, --help show this help message and exit --option OPTION --no-setup --no-default NO_DEFAULT ''')
def test_fix_format_error(embed_data): """ Check _FixFormat error output (detailed traceback). """ filename = embed_data['test_fix_format_error.py'] data_dir = embed_data.get_data_dir() original = """ import zulu from bravo import Bravo import alpha class Alpha(object): def Method(self) pass def Function(): pass """ assert CreateFile(filename, dedent(original), encoding='UTF-8') app.TestScript( dedent( """ >>>terraformer fix-format --single-job --traceback-limit=0 %(data_dir)s - %(filename)s: ERROR: \b\b On TerraForming.ReorganizeImports with filename: %(filename)s Had problems parsing: > import zulu > from bravo import Bravo > import alpha >\b > class Alpha(object): >\b > def Method(self) > pass >\b > def Function(): > pass bad input: type=4, value=u'\\r\\n', context=('', (7, 20)) --- * --- """ % locals() ).replace('\b', ' '), input_prefix='>>>' ) assert GetFileContents(filename, encoding='UTF-8') == dedent( """ import zulu from bravo import Bravo import alpha class Alpha(object): def Method(self) pass def Function(): pass """ )
def testApp(self): ''' Tests App usage and features. ''' def Case1(console_): ''' A "hello" message from case 1 ''' console_.Print('Hello from case 1') def Case2(console_): ''' A "hello" message from case 2 Additional help for this function is available. ''' console_.Print('Hello from case 2') def Case3(console_): console_.Print('Hello from case 3') def Case4(console_): console_.Print('Hello from case 4 (AKA: four)') app = App('test', color=False, buffered_console=True) app.Add(Case1, alias='cs') app.Add(Case2) case3_cmd = app.Add(Case3, alias=('c3', 'cs3')) app.Add(Case4, name='four') # Test duplicate name with pytest.raises(ValueError): app.Add(case3_cmd.func, alias='cs') # Test commands listing assert app.ListAllCommandNames() == [ 'case1', 'cs', 'case2', 'case3', 'c3', 'cs3', 'four' ] # Tests all commands output self._TestMain(app, 'case1', 'Hello from case 1\n') self._TestMain(app, 'cs', 'Hello from case 1\n') self._TestMain(app, 'case2', 'Hello from case 2\n') self._TestMain(app, 'case3', 'Hello from case 3\n') self._TestMain(app, 'c3', 'Hello from case 3\n') self._TestMain(app, 'cs3', 'Hello from case 3\n') self._TestMain(app, 'four', 'Hello from case 4 (AKA: four)\n') # Tests output when an invalid command is requested self._TestMain( app, 'INVALID', dedent(''' ERROR: Unknown command u'INVALID' Usage: test <subcommand> [options] Commands: case1, cs A "hello" message from case 1 case2 A "hello" message from case 2 case3, c3, cs3 (no description) four (no description) '''), app.RETCODE_ERROR)
def testSymbolVisitor(): def PrintScopes(scopes): result = [] for i in sorted(scopes, key=lambda x:x.name): result.append('- %s' % i) for j in sorted(i.uses): result.append(' - %s' % j) return '\n'.join(result) source_code = dedent( ''' from alpha import Alpha import coilib50 class Zulu(Alpha): """ Zulu class docs. """ def __init__(self, name): """ Zulu.__init__ docs. """ self._name = name alpha = bravo coilib50.Charlie() f = coilib50.Delta(echo, foxtrot) ''' ) from zerotk.terraformer._visitor import ASTVisitor code = TerraFormer._Parse(source_code) visitor = ASTVisitor() visitor.Visit(code) assert visitor._module.AsString() == dedent( ''' module (1, 0) module IMPORT-BLOCK (1, 0) import-block #0 IMPORT-FROM (0, 0) alpha IMPORT (1, 0) alpha.Alpha IMPORT (2, 0) coilib50 USE (3, 0) Alpha class (0, 0) Zulu def (8, 4) __init__ ARG (9, 17) self ARG (9, 23) name DEF (13, 8) self._name USE (13, 21) name DEF (14, 8) alpha USE (14, 16) bravo USE (15, 8) coilib50.Charlie DEF (16, 8) f USE (16, 12) coilib50.Delta USE (16, 27) echo USE (16, 33) foxtrot ''' ) # Compares the results with the one given by compiler.symbols.SymbolVisitor, our inspiration. from compiler.symbols import SymbolVisitor from compiler.transformer import parse from compiler.visitor import walk code = parse(source_code) symbol_visitor = SymbolVisitor() walk(code, symbol_visitor) assert PrintScopes(symbol_visitor.scopes.values()) == dedent( ''' - <ClassScope: Zulu> - <FunctionScope: __init__> - bravo - coilib50 - echo - foxtrot - name - self - <ModuleScope: global> - Alpha ''' )
def testHelp(self): def TestCmd(console_, first, second, option=1, option_no=False): ''' This is a test. :param first: This is the first parameter. :param second: This is the second and last parameter. :param option: This must be a number. :param option_no: If set, says nop. ''' app = App('test', color=False, buffered_console=True) app.Add(TestCmd) self._TestMain(app, '', dedent( ''' Usage: test <subcommand> [options] Commands: test-cmd This is a test. ''' ) ) self._TestMain(app, '--help', dedent( ''' Usage: test <subcommand> [options] Commands: test-cmd This is a test. ''' ) ) self._TestMain( app, 'test-cmd --help', dedent( ''' This is a test. Usage: test-cmd <first> <second> [--option=1],[--option-no] Parameters: first This is the first parameter. second This is the second and last parameter. Options: --option This must be a number. [default: 1] --option-no If set, says nop. ''' ) ) self._TestMain( app, 'test-cmd', dedent( ''' ERROR: Too few arguments. This is a test. Usage: test-cmd <first> <second> [--option=1],[--option-no] Parameters: first This is the first parameter. second This is the second and last parameter. Options: --option This must be a number. [default: 1] --option-no If set, says nop. ''' ), app.RETCODE_ERROR )
def testApp(self): ''' Tests App usage and features. ''' def Case1(console_): ''' A "hello" message from case 1 ''' console_.Print('Hello from case 1') def Case2(console_): ''' A "hello" message from case 2 Additional help for this function is available. ''' console_.Print('Hello from case 2') def Case3(console_): console_.Print('Hello from case 3') def Case4(console_): console_.Print('Hello from case 4 (AKA: four)') app = App('test', color=False, buffered_console=True) app.Add(Case1, alias='cs') app.Add(Case2) case3_cmd = app.Add(Case3, alias=('c3', 'cs3')) app.Add(Case4, name='four') # Test duplicate name with pytest.raises(ValueError): app.Add(case3_cmd.func, alias='cs') # Test commands listing assert app.ListAllCommandNames() == ['case1', 'cs', 'case2', 'case3', 'c3', 'cs3', 'four'] # Tests all commands output self._TestMain(app, 'case1', 'Hello from case 1\n') self._TestMain(app, 'cs', 'Hello from case 1\n') self._TestMain(app, 'case2', 'Hello from case 2\n') self._TestMain(app, 'case3', 'Hello from case 3\n') self._TestMain(app, 'c3', 'Hello from case 3\n') self._TestMain(app, 'cs3', 'Hello from case 3\n') self._TestMain(app, 'four', 'Hello from case 4 (AKA: four)\n') # Tests output when an invalid command is requested self._TestMain(app, 'INVALID', dedent( ''' ERROR: Unknown command u'INVALID' Usage: test <subcommand> [options] Commands: case1, cs A "hello" message from case 1 case2 A "hello" message from case 2 case3, c3, cs3 (no description) four (no description) '''), app.RETCODE_ERROR )
GRAMMAR['Grammar.txt'] = dedent(""" # Grammar for 2to3. This grammar supports Python 2.x and 3.x. # Note: Changing the grammar specified in this file will most likely # require corresponding changes in the parser module # (../Modules/parsermodule.c). If you can't make the changes to # that module yourself, please co-ordinate the required changes # with someone who can; ask around on python-dev for help. Fred # Drake <*****@*****.**> will probably be listening there. # NOTE WELL: You should also follow all the steps listed in PEP 306, # "How to Change Python's Grammar" # Commands for Kees Blom's railroad program #diagram:token NAME #diagram:token NUMBER #diagram:token STRING #diagram:token NEWLINE #diagram:token ENDMARKER #diagram:token INDENT #diagram:output\input python.bla #diagram:token DEDENT #diagram:output\textwidth 20.04cm\oddsidemargin 0.0cm\evensidemargin 0.0cm #diagram:rules # Start symbols for the grammar: # file_input is a module or sequence of commands read from an input file; # single_input is a single interactive statement; # eval_input is the input for the eval() and input() functions. # NB: compound_stmt in single_input is followed by extra NEWLINE! file_input: (NEWLINE | stmt)* ENDMARKER single_input: NEWLINE | simple_stmt | compound_stmt NEWLINE eval_input: testlist NEWLINE* ENDMARKER decorator: '@' dotted_name [ '(' [arglist] ')' ] NEWLINE decorators: decorator+ decorated: decorators (classdef | funcdef) funcdef: 'def' NAME parameters ['->' test] ':' suite parameters: '(' [typedargslist] ')' typedargslist: ((tfpdef ['=' test] ',')* ('*' [tname] (',' tname ['=' test])* [',' '**' tname] | '**' tname) | tfpdef ['=' test] (',' tfpdef ['=' test])* [',']) tname: NAME [':' test] tfpdef: tname | '(' tfplist ')' tfplist: tfpdef (',' tfpdef)* [','] varargslist: ((vfpdef ['=' test] ',')* ('*' [vname] (',' vname ['=' test])* [',' '**' vname] | '**' vname) | vfpdef ['=' test] (',' vfpdef ['=' test])* [',']) vname: NAME vfpdef: vname | '(' vfplist ')' vfplist: vfpdef (',' vfpdef)* [','] stmt: simple_stmt | compound_stmt simple_stmt: small_stmt (';' small_stmt)* [';'] NEWLINE small_stmt: (expr_stmt | print_stmt | del_stmt | pass_stmt | flow_stmt | import_stmt | global_stmt | exec_stmt | assert_stmt) expr_stmt: testlist_star_expr (augassign (yield_expr|testlist) | ('=' (yield_expr|testlist_star_expr))*) testlist_star_expr: (test|star_expr) (',' (test|star_expr))* [','] augassign: ('+=' | '-=' | '*=' | '@=' | '/=' | '%=' | '&=' | '|=' | '^=' | '<<=' | '>>=' | '**=' | '//=') # For normal assignments, additional restrictions enforced by the interpreter print_stmt: 'print' ( [ test (',' test)* [','] ] | '>>' test [ (',' test)+ [','] ] ) del_stmt: 'del' exprlist pass_stmt: 'pass' flow_stmt: break_stmt | continue_stmt | return_stmt | raise_stmt | yield_stmt break_stmt: 'break' continue_stmt: 'continue' return_stmt: 'return' [testlist] yield_stmt: yield_expr raise_stmt: 'raise' [test ['from' test | ',' test [',' test]]] import_stmt: import_name | import_from import_name: 'import' dotted_as_names import_from: ('from' ('.'* dotted_name | '.'+) 'import' ('*' | '(' import_as_names ')' | import_as_names)) import_as_name: NAME ['as' NAME] dotted_as_name: dotted_name ['as' NAME] import_as_names: import_as_name (',' import_as_name)* [','] dotted_as_names: dotted_as_name (',' dotted_as_name)* dotted_name: NAME ('.' NAME)* global_stmt: ('global' | 'nonlocal') NAME (',' NAME)* exec_stmt: 'exec' expr ['in' test [',' test]] assert_stmt: 'assert' test [',' test] compound_stmt: if_stmt | while_stmt | for_stmt | try_stmt | with_stmt | funcdef | classdef | decorated if_stmt: 'if' test ':' suite ('elif' test ':' suite)* ['else' ':' suite] while_stmt: 'while' test ':' suite ['else' ':' suite] for_stmt: 'for' exprlist 'in' testlist ':' suite ['else' ':' suite] try_stmt: ('try' ':' suite ((except_clause ':' suite)+ ['else' ':' suite] ['finally' ':' suite] | 'finally' ':' suite)) with_stmt: 'with' with_item (',' with_item)* ':' suite with_item: test ['as' expr] with_var: 'as' expr # NB compile.c makes sure that the default except clause is last except_clause: 'except' [test [(',' | 'as') test]] suite: simple_stmt | NEWLINE INDENT stmt+ DEDENT # Backward compatibility cruft to support: # [ x for x in lambda: True, lambda: False if x() ] # even while also allowing: # lambda x: 5 if x else 2 # (But not a mix of the two) testlist_safe: old_test [(',' old_test)+ [',']] old_test: or_test | old_lambdef old_lambdef: 'lambda' [varargslist] ':' old_test test: or_test ['if' or_test 'else' test] | lambdef or_test: and_test ('or' and_test)* and_test: not_test ('and' not_test)* not_test: 'not' not_test | comparison comparison: expr (comp_op expr)* comp_op: '<'|'>'|'=='|'>='|'<='|'<>'|'!='|'in'|'not' 'in'|'is'|'is' 'not' star_expr: '*' expr expr: xor_expr ('|' xor_expr)* xor_expr: and_expr ('^' and_expr)* and_expr: shift_expr ('&' shift_expr)* shift_expr: arith_expr (('<<'|'>>') arith_expr)* arith_expr: term (('+'|'-') term)* term: factor (('*'|'@'|'/'|'%'|'//') factor)* factor: ('+'|'-'|'~') factor | power power: atom trailer* ['**' factor] atom: ('(' [yield_expr|testlist_gexp] ')' | '[' [listmaker] ']' | '{' [dictsetmaker] '}' | '`' testlist1 '`' | NAME | NUMBER | STRING+ | '.' '.' '.') listmaker: (test|star_expr) ( comp_for | (',' (test|star_expr))* [','] ) testlist_gexp: (test|star_expr) ( comp_for | (',' (test|star_expr))* [','] ) lambdef: 'lambda' [varargslist] ':' test trailer: '(' [arglist] ')' | '[' subscriptlist ']' | '.' NAME subscriptlist: subscript (',' subscript)* [','] subscript: test | [test] ':' [test] [sliceop] sliceop: ':' [test] exprlist: (expr|star_expr) (',' (expr|star_expr))* [','] testlist: test (',' test)* [','] dictsetmaker: ( (test ':' test (comp_for | (',' test ':' test)* [','])) | (test (comp_for | (',' test)* [','])) ) classdef: 'class' NAME ['(' [arglist] ')'] ':' suite arglist: (argument ',')* (argument [','] |'*' test (',' argument)* [',' '**' test] |'**' test) argument: test [comp_for] | test '=' test # Really [keyword '='] test comp_iter: comp_for | comp_if comp_for: 'for' exprlist 'in' testlist_safe [comp_iter] comp_if: 'if' old_test [comp_iter] testlist1: test (',' test)* # not used in grammar, but may appear in "node" passed from Parser to Compiler encoding_decl: NAME yield_expr: 'yield' [yield_arg] yield_arg: 'from' test | testlist """)
def test_dedent2(): string = dedent(""" oneline twoline """) assert string == 'oneline\ntwoline'
GRAMMAR['Grammar.txt'] = dedent( """ # Grammar for 2to3. This grammar supports Python 2.x and 3.x. # Note: Changing the grammar specified in this file will most likely # require corresponding changes in the parser module # (../Modules/parsermodule.c). If you can't make the changes to # that module yourself, please co-ordinate the required changes # with someone who can; ask around on python-dev for help. Fred # Drake <*****@*****.**> will probably be listening there. # NOTE WELL: You should also follow all the steps listed in PEP 306, # "How to Change Python's Grammar" # Commands for Kees Blom's railroad program #diagram:token NAME #diagram:token NUMBER #diagram:token STRING #diagram:token NEWLINE #diagram:token ENDMARKER #diagram:token INDENT #diagram:output\input python.bla #diagram:token DEDENT #diagram:output\textwidth 20.04cm\oddsidemargin 0.0cm\evensidemargin 0.0cm #diagram:rules # Start symbols for the grammar: # file_input is a module or sequence of commands read from an input file; # single_input is a single interactive statement; # eval_input is the input for the eval() and input() functions. # NB: compound_stmt in single_input is followed by extra NEWLINE! file_input: (NEWLINE | stmt)* ENDMARKER single_input: NEWLINE | simple_stmt | compound_stmt NEWLINE eval_input: testlist NEWLINE* ENDMARKER decorator: '@' dotted_name [ '(' [arglist] ')' ] NEWLINE decorators: decorator+ decorated: decorators (classdef | funcdef) funcdef: 'def' NAME parameters ['->' test] ':' suite parameters: '(' [typedargslist] ')' typedargslist: ((tfpdef ['=' test] ',')* ('*' [tname] (',' tname ['=' test])* [',' '**' tname] | '**' tname) | tfpdef ['=' test] (',' tfpdef ['=' test])* [',']) tname: NAME [':' test] tfpdef: tname | '(' tfplist ')' tfplist: tfpdef (',' tfpdef)* [','] varargslist: ((vfpdef ['=' test] ',')* ('*' [vname] (',' vname ['=' test])* [',' '**' vname] | '**' vname) | vfpdef ['=' test] (',' vfpdef ['=' test])* [',']) vname: NAME vfpdef: vname | '(' vfplist ')' vfplist: vfpdef (',' vfpdef)* [','] stmt: simple_stmt | compound_stmt simple_stmt: small_stmt (';' small_stmt)* [';'] NEWLINE small_stmt: (expr_stmt | print_stmt | del_stmt | pass_stmt | flow_stmt | import_stmt | global_stmt | exec_stmt | assert_stmt) expr_stmt: testlist_star_expr (augassign (yield_expr|testlist) | ('=' (yield_expr|testlist_star_expr))*) testlist_star_expr: (test|star_expr) (',' (test|star_expr))* [','] augassign: ('+=' | '-=' | '*=' | '@=' | '/=' | '%=' | '&=' | '|=' | '^=' | '<<=' | '>>=' | '**=' | '//=') # For normal assignments, additional restrictions enforced by the interpreter print_stmt: 'print' ( [ test (',' test)* [','] ] | '>>' test [ (',' test)+ [','] ] ) del_stmt: 'del' exprlist pass_stmt: 'pass' flow_stmt: break_stmt | continue_stmt | return_stmt | raise_stmt | yield_stmt break_stmt: 'break' continue_stmt: 'continue' return_stmt: 'return' [testlist] yield_stmt: yield_expr raise_stmt: 'raise' [test ['from' test | ',' test [',' test]]] import_stmt: import_name | import_from import_name: 'import' dotted_as_names import_from: ('from' ('.'* dotted_name | '.'+) 'import' ('*' | '(' import_as_names ')' | import_as_names)) import_as_name: NAME ['as' NAME] dotted_as_name: dotted_name ['as' NAME] import_as_names: import_as_name (',' import_as_name)* [','] dotted_as_names: dotted_as_name (',' dotted_as_name)* dotted_name: NAME ('.' NAME)* global_stmt: ('global' | 'nonlocal') NAME (',' NAME)* exec_stmt: 'exec' expr ['in' test [',' test]] assert_stmt: 'assert' test [',' test] compound_stmt: if_stmt | while_stmt | for_stmt | try_stmt | with_stmt | funcdef | classdef | decorated if_stmt: 'if' test ':' suite ('elif' test ':' suite)* ['else' ':' suite] while_stmt: 'while' test ':' suite ['else' ':' suite] for_stmt: 'for' exprlist 'in' testlist ':' suite ['else' ':' suite] try_stmt: ('try' ':' suite ((except_clause ':' suite)+ ['else' ':' suite] ['finally' ':' suite] | 'finally' ':' suite)) with_stmt: 'with' with_item (',' with_item)* ':' suite with_item: test ['as' expr] with_var: 'as' expr # NB compile.c makes sure that the default except clause is last except_clause: 'except' [test [(',' | 'as') test]] suite: simple_stmt | NEWLINE INDENT stmt+ DEDENT # Backward compatibility cruft to support: # [ x for x in lambda: True, lambda: False if x() ] # even while also allowing: # lambda x: 5 if x else 2 # (But not a mix of the two) testlist_safe: old_test [(',' old_test)+ [',']] old_test: or_test | old_lambdef old_lambdef: 'lambda' [varargslist] ':' old_test test: or_test ['if' or_test 'else' test] | lambdef or_test: and_test ('or' and_test)* and_test: not_test ('and' not_test)* not_test: 'not' not_test | comparison comparison: expr (comp_op expr)* comp_op: '<'|'>'|'=='|'>='|'<='|'<>'|'!='|'in'|'not' 'in'|'is'|'is' 'not' star_expr: '*' expr expr: xor_expr ('|' xor_expr)* xor_expr: and_expr ('^' and_expr)* and_expr: shift_expr ('&' shift_expr)* shift_expr: arith_expr (('<<'|'>>') arith_expr)* arith_expr: term (('+'|'-') term)* term: factor (('*'|'@'|'/'|'%'|'//') factor)* factor: ('+'|'-'|'~') factor | power power: atom trailer* ['**' factor] atom: ('(' [yield_expr|testlist_gexp] ')' | '[' [listmaker] ']' | '{' [dictsetmaker] '}' | '`' testlist1 '`' | NAME | NUMBER | STRING+ | '.' '.' '.') listmaker: (test|star_expr) ( comp_for | (',' (test|star_expr))* [','] ) testlist_gexp: (test|star_expr) ( comp_for | (',' (test|star_expr))* [','] ) lambdef: 'lambda' [varargslist] ':' test trailer: '(' [arglist] ')' | '[' subscriptlist ']' | '.' NAME subscriptlist: subscript (',' subscript)* [','] subscript: test | [test] ':' [test] [sliceop] sliceop: ':' [test] exprlist: (expr|star_expr) (',' (expr|star_expr))* [','] testlist: test (',' test)* [','] dictsetmaker: ( (test ':' test (comp_for | (',' test ':' test)* [','])) | (test (comp_for | (',' test)* [','])) ) classdef: 'class' NAME ['(' [arglist] ')'] ':' suite arglist: (argument ',')* (argument [','] |'*' test (',' argument)* [',' '**' test] |'**' test) argument: test [comp_for] | test '=' test # Really [keyword '='] test comp_iter: comp_for | comp_if comp_for: 'for' exprlist 'in' testlist_safe [comp_iter] comp_if: 'if' old_test [comp_iter] testlist1: test (',' test)* # not used in grammar, but may appear in "node" passed from Parser to Compiler encoding_decl: NAME yield_expr: 'yield' [yield_arg] yield_arg: 'from' test | testlist """ )