github.com/grumpyhome/grumpy@v0.3.1-0.20201208125205-7b775405bdf1/grumpy-tools-src/grumpy_tools/compiler/stmt_test.py (about)

     1  # coding=utf-8
     2  
     3  # Copyright 2016 Google Inc. All Rights Reserved.
     4  #
     5  # Licensed under the Apache License, Version 2.0 (the "License");
     6  # you may not use this file except in compliance with the License.
     7  # You may obtain a copy of the License at
     8  #
     9  #     http://www.apache.org/licenses/LICENSE-2.0
    10  #
    11  # Unless required by applicable law or agreed to in writing, software
    12  # distributed under the License is distributed on an "AS IS" BASIS,
    13  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    14  # See the License for the specific language governing permissions and
    15  # limitations under the License.
    16  
    17  """Tests for StatementVisitor."""
    18  
    19  from __future__ import unicode_literals
    20  
    21  import re
    22  import subprocess
    23  import textwrap
    24  import unittest
    25  
    26  from grumpy_tools.compiler import block
    27  from grumpy_tools.compiler import imputil
    28  from grumpy_tools.compiler import shard_test
    29  from grumpy_tools.compiler import stmt
    30  from grumpy_tools.compiler import util
    31  import pythonparser
    32  from pythonparser import ast
    33  
    34  import pytest
    35  
    36  class StatementVisitorTest(unittest.TestCase):
    37  
    38    def testAssertNoMsg(self):
    39      self.assertEqual((0, 'AssertionError()\n'), _GrumpRun(textwrap.dedent("""\
    40          try:
    41            assert False
    42          except AssertionError as e:
    43            print repr(e)""")))
    44  
    45    def testAssertMsg(self):
    46      want = (0, "AssertionError('foo',)\n")
    47      self.assertEqual(want, _GrumpRun(textwrap.dedent("""\
    48          try:
    49            assert False, 'foo'
    50          except AssertionError as e:
    51            print repr(e)""")))
    52  
    53    def testBareAssert(self):
    54      # Assertion errors at the top level of a block should raise:
    55      # https://github.com/google/grumpy/issues/18
    56      want = (0, 'ok\n')
    57      self.assertEqual(want, _GrumpRun(textwrap.dedent("""\
    58          def foo():
    59           assert False
    60          try:
    61           foo()
    62          except AssertionError:
    63           print 'ok'
    64          else:
    65           print 'bad'""")))
    66  
    67    def testAssignAttribute(self):
    68      self.assertEqual((0, '123\n'), _GrumpRun(textwrap.dedent("""\
    69          e = Exception()
    70          e.foo = 123
    71          print e.foo""")))
    72  
    73    def testAssignName(self):
    74      self.assertEqual((0, 'bar\n'), _GrumpRun(textwrap.dedent("""\
    75          foo = 'bar'
    76          print foo""")))
    77  
    78    def testAssignMultiple(self):
    79      self.assertEqual((0, 'baz baz\n'), _GrumpRun(textwrap.dedent("""\
    80          foo = bar = 'baz'
    81          print foo, bar""")))
    82  
    83    def testAssignSubscript(self):
    84      self.assertEqual((0, "{'bar': None}\n"), _GrumpRun(textwrap.dedent("""\
    85          foo = {}
    86          foo['bar'] = None
    87          print foo""")))
    88  
    89    def testAssignTuple(self):
    90      self.assertEqual((0, 'a b\n'), _GrumpRun(textwrap.dedent("""\
    91          baz = ('a', 'b')
    92          foo, bar = baz
    93          print foo, bar""")))
    94  
    95    def testAugAssign(self):
    96      self.assertEqual((0, '42\n'), _GrumpRun(textwrap.dedent("""\
    97          foo = 41
    98          foo += 1
    99          print foo""")))
   100  
   101    def testAugAssignBitAnd(self):
   102      self.assertEqual((0, '3\n'), _GrumpRun(textwrap.dedent("""\
   103          foo = 7
   104          foo &= 3
   105          print foo""")))
   106  
   107    def testAugAssignPow(self):
   108      self.assertEqual((0, '64\n'), _GrumpRun(textwrap.dedent("""\
   109          foo = 8
   110          foo **= 2
   111          print foo""")))
   112  
   113    def testClassDef(self):
   114      self.assertEqual((0, "<type 'type'>\n"), _GrumpRun(textwrap.dedent("""\
   115          class Foo(object):
   116            pass
   117          print type(Foo)""")))
   118  
   119    def testClassDefWithVar(self):
   120      self.assertEqual((0, 'abc\n'), _GrumpRun(textwrap.dedent("""\
   121          class Foo(object):
   122            bar = 'abc'
   123          print Foo.bar""")))
   124  
   125    def testDeleteAttribute(self):
   126      self.assertEqual((0, 'False\n'), _GrumpRun(textwrap.dedent("""\
   127          class Foo(object):
   128            bar = 42
   129          del Foo.bar
   130          print hasattr(Foo, 'bar')""")))
   131  
   132    def testDeleteClassLocal(self):
   133      self.assertEqual((0, 'False\n'), _GrumpRun(textwrap.dedent("""\
   134          class Foo(object):
   135            bar = 'baz'
   136            del bar
   137          print hasattr(Foo, 'bar')""")))
   138  
   139    def testDeleteGlobal(self):
   140      self.assertEqual((0, 'False\n'), _GrumpRun(textwrap.dedent("""\
   141          foo = 42
   142          del foo
   143          print 'foo' in globals()""")))
   144  
   145    def testDeleteLocal(self):
   146      self.assertEqual((0, 'ok\n'), _GrumpRun(textwrap.dedent("""\
   147          def foo():
   148            bar = 123
   149            del bar
   150            try:
   151              print bar
   152              raise AssertionError
   153            except UnboundLocalError:
   154              print 'ok'
   155          foo()""")))
   156  
   157    def testDeleteNonexistentLocal(self):
   158      self.assertRaisesRegexp(
   159          util.ParseError, 'cannot delete nonexistent local',
   160          _ParseAndVisit, 'def foo():\n  del bar')
   161  
   162    def testDeleteSubscript(self):
   163      self.assertEqual((0, '{}\n'), _GrumpRun(textwrap.dedent("""\
   164          foo = {'bar': 'baz'}
   165          del foo['bar']
   166          print foo""")))
   167  
   168    def testExprCall(self):
   169      self.assertEqual((0, 'bar\n'), _GrumpRun(textwrap.dedent("""\
   170          def foo():
   171            print 'bar'
   172          foo()""")))
   173  
   174    def testExprNameGlobal(self):
   175      self.assertEqual((0, ''), _GrumpRun(textwrap.dedent("""\
   176          foo = 42
   177          foo""")))
   178  
   179    def testExprNameLocal(self):
   180      self.assertEqual((0, ''), _GrumpRun(textwrap.dedent("""\
   181          foo = 42
   182          def bar():
   183            foo
   184          bar()""")))
   185  
   186    def testFor(self):
   187      self.assertEqual((0, '1\n2\n3\n'), _GrumpRun(textwrap.dedent("""\
   188          for i in (1, 2, 3):
   189            print i""")))
   190  
   191    def testForBreak(self):
   192      self.assertEqual((0, '1\n'), _GrumpRun(textwrap.dedent("""\
   193          for i in (1, 2, 3):
   194            print i
   195            break""")))
   196  
   197    def testForContinue(self):
   198      self.assertEqual((0, '1\n2\n3\n'), _GrumpRun(textwrap.dedent("""\
   199          for i in (1, 2, 3):
   200            print i
   201            continue
   202            raise AssertionError""")))
   203  
   204    def testForElse(self):
   205      self.assertEqual((0, 'foo\nbar\n'), _GrumpRun(textwrap.dedent("""\
   206          for i in (1,):
   207            print 'foo'
   208          else:
   209            print 'bar'""")))
   210  
   211    def testForElseBreakNotNested(self):
   212      self.assertRaisesRegexp(
   213          util.ParseError, "'continue' not in loop",
   214          _ParseAndVisit, 'for i in (1,):\n  pass\nelse:\n  continue')
   215  
   216    def testForElseContinueNotNested(self):
   217      self.assertRaisesRegexp(
   218          util.ParseError, "'continue' not in loop",
   219          _ParseAndVisit, 'for i in (1,):\n  pass\nelse:\n  continue')
   220  
   221    def testFunctionDecorator(self):
   222      self.assertEqual((0, '<b>foo</b>\n'), _GrumpRun(textwrap.dedent("""\
   223          def bold(fn):
   224            return lambda: '<b>' + fn() + '</b>'
   225          @bold
   226          def foo():
   227            return 'foo'
   228          print foo()""")))
   229  
   230    def testFunctionDecoratorWithArg(self):
   231      self.assertEqual((0, '<b id=red>foo</b>\n'), _GrumpRun(textwrap.dedent("""\
   232          def tag(name):
   233            def bold(fn):
   234              return lambda: '<b id=' + name + '>' + fn() + '</b>'
   235            return bold
   236          @tag('red')
   237          def foo():
   238            return 'foo'
   239          print foo()""")))
   240  
   241    def testFunctionDef(self):
   242      self.assertEqual((0, 'bar baz\n'), _GrumpRun(textwrap.dedent("""\
   243          def foo(a, b):
   244            print a, b
   245          foo('bar', 'baz')""")))
   246  
   247    def testFunctionDefWithTupleArgs(self):
   248      self.assertEqual((0, "('bar', 'baz')\n"), _GrumpRun(textwrap.dedent("""\
   249          def foo((a, b)):
   250            print(a, b)
   251          foo(('bar', 'baz'))""")))
   252  
   253    def testFunctionDefWithNestedTupleArgs(self):
   254      self.assertEqual((0, "('bar', 'baz', 'qux')\n"), _GrumpRun(textwrap.dedent("""\
   255          def foo(((a, b), c)):
   256            print(a, b, c)
   257          foo((('bar', 'baz'), 'qux'))""")))
   258  
   259    def testFunctionDefWithMultipleTupleArgs(self):
   260      self.assertEqual((0, "('bar', 'baz')\n"), _GrumpRun(textwrap.dedent("""\
   261          def foo(((a, ), (b, ))):
   262            print(a, b)
   263          foo((('bar',), ('baz', )))""")))
   264  
   265    def testFunctionDefTupleArgsInLambda(self):
   266      self.assertEqual((0, "[(3, 2), (4, 3), (12, 1)]\n"), _GrumpRun(textwrap.dedent("""\
   267          c = {12: 1, 3: 2, 4: 3}
   268          top = sorted(c.items(), key=lambda (k,v): v)
   269          print (top)""")))
   270  
   271    def testFunctionDefGenerator(self):
   272      self.assertEqual((0, "['foo', 'bar']\n"), _GrumpRun(textwrap.dedent("""\
   273          def gen():
   274            yield 'foo'
   275            yield 'bar'
   276          print list(gen())""")))
   277  
   278    def testFunctionDefGeneratorReturnValue(self):
   279      self.assertRaisesRegexp(
   280          util.ParseError, 'returning a value in a generator function',
   281          _ParseAndVisit, 'def foo():\n  yield 1\n  return 2')
   282  
   283    def testFunctionDefLocal(self):
   284      self.assertEqual((0, 'baz\n'), _GrumpRun(textwrap.dedent("""\
   285          def foo():
   286            def bar():
   287              print 'baz'
   288            bar()
   289          foo()""")))
   290  
   291    def testIf(self):
   292      self.assertEqual((0, 'foo\n'), _GrumpRun(textwrap.dedent("""\
   293          if 123:
   294            print 'foo'
   295          if '':
   296            print 'bar'""")))
   297  
   298    def testIfElif(self):
   299      self.assertEqual((0, 'foo\nbar\n'), _GrumpRun(textwrap.dedent("""\
   300          if True:
   301            print 'foo'
   302          elif False:
   303            print 'bar'
   304          if False:
   305            print 'foo'
   306          elif True:
   307            print 'bar'""")))
   308  
   309    def testIfElse(self):
   310      self.assertEqual((0, 'foo\nbar\n'), _GrumpRun(textwrap.dedent("""\
   311          if True:
   312            print 'foo'
   313          else:
   314            print 'bar'
   315          if False:
   316            print 'foo'
   317          else:
   318            print 'bar'""")))
   319  
   320    def testImport(self):
   321      self.assertEqual((0, "<type 'dict'>\n"), _GrumpRun(textwrap.dedent("""\
   322          import sys
   323          print type(sys.modules)""")))
   324  
   325    def testImportFutureLateRaises(self):
   326      regexp = 'from __future__ imports must occur at the beginning of the file'
   327      self.assertRaisesRegexp(util.ImportError, regexp, _ParseAndVisit,
   328                              'foo = bar\nfrom __future__ import print_function')
   329  
   330    def testFutureUnicodeLiterals(self):
   331      want = "u'foo'\n"
   332      self.assertEqual((0, want), _GrumpRun(textwrap.dedent("""\
   333          from __future__ import unicode_literals
   334          print repr('foo')""")))
   335  
   336    def testImportMember(self):
   337      self.assertEqual((0, "<type 'dict'>\n"), _GrumpRun(textwrap.dedent("""\
   338          from sys import modules
   339          print type(modules)""")))
   340  
   341    def testImportConflictingPackage(self):
   342      self.assertEqual((0, ''), _GrumpRun(textwrap.dedent("""\
   343          import time
   344          from "__go__/time" import Now""")))
   345  
   346    def testImportNative(self):
   347      self.assertEqual((0, '1 1000000000\n'), _GrumpRun(textwrap.dedent("""\
   348          from "__go__/time" import Nanosecond, Second
   349          print Nanosecond, Second""")))
   350  
   351    def testImportGrumpy(self):
   352      self.assertEqual((0, ''), _GrumpRun(textwrap.dedent("""\
   353          from "__go__/grumpy" import Assert
   354          Assert(__frame__(), True, 'bad')""")))
   355  
   356    def testImportNativeType(self):
   357      self.assertEqual((0, "<type 'Duration'>\n"), _GrumpRun(textwrap.dedent("""\
   358          from "__go__/time" import Duration
   359          print Duration""")))
   360  
   361    def testPrintStatement(self):
   362      self.assertEqual((0, 'abc 123\nfoo bar\n'), _GrumpRun(textwrap.dedent("""\
   363          print 'abc',
   364          print '123'
   365          print 'foo', 'bar'""")))
   366  
   367    def testImportWildcard(self):
   368      result = _GrumpRun(textwrap.dedent("""\
   369          from time import *
   370          print sleep"""))
   371      self.assertEqual(0, result[0])
   372      self.assertIn('<function sleep at', result[1])
   373  
   374    def testImportTryExcept(self):
   375      result = _GrumpRun(textwrap.dedent("""\
   376          try:
   377            import inexistantmodule
   378          except ImportError:
   379            from time import sleep as inexistantmodule
   380          print inexistantmodule
   381      """))
   382      self.assertEqual(0, result[0])
   383      self.assertIn('<function sleep at', result[1])
   384  
   385    def testImportFromTryExcept(self):
   386      result = _GrumpRun(textwrap.dedent("""\
   387          try:
   388            from time import inexistantfunction
   389          except ImportError:
   390            from time import sleep
   391          print sleep
   392      """))
   393      self.assertEqual(0, result[0])
   394      self.assertIn('<function sleep at', result[1])
   395  
   396    def testPrintFunction(self):
   397      want = "abc\n123\nabc 123\nabcx123\nabc 123 "
   398      self.assertEqual((0, want), _GrumpRun(textwrap.dedent("""\
   399          "module docstring is ok to proceed __future__"
   400          from __future__ import print_function
   401          print('abc')
   402          print(123)
   403          print('abc', 123)
   404          print('abc', 123, sep='x')
   405          print('abc', 123, end=' ')""")))
   406  
   407    def testModuleDocstring(self):
   408      want = "__doc__ (unicode) is module docstring\n"
   409      self.assertEqual((0, want), _GrumpRun(textwrap.dedent("""\
   410          from __future__ import unicode_literals
   411          "module docstring"
   412          print "__doc__ (" + type(__doc__).__name__ + ") is " + str(__doc__)"""
   413      )))
   414  
   415    def testModuleDocstringAbsent(self):
   416      want = "__doc__ (NoneType) is None\n"
   417      self.assertEqual((0, want), _GrumpRun(textwrap.dedent("""\
   418          from __future__ import unicode_literals
   419          print "__doc__ (" + type(__doc__).__name__ + ") is " + str(__doc__)"""
   420      )))
   421  
   422    def testClassDocstring(self):
   423      want = "Foo.__doc__ (unicode) is class docstring\n"
   424      self.assertEqual((0, want), _GrumpRun(textwrap.dedent("""\
   425          from __future__ import unicode_literals
   426          "module docstring"
   427  
   428          class Foo(object):
   429            "class docstring"
   430            pass
   431  
   432          print "Foo.__doc__ (" + type(Foo.__doc__).__name__ + ") is " + str(Foo.__doc__)"""
   433      )))
   434  
   435    @pytest.mark.xfail
   436    def testClassDocstringAbsent(self):
   437      want = "Foo.__doc__ (NoneType) is None\n"
   438      self.assertEqual((0, want), _GrumpRun(textwrap.dedent("""\
   439          from __future__ import unicode_literals
   440          "module docstring"
   441  
   442          class Foo(object):
   443            pass
   444  
   445          print "Foo.__doc__ (" + type(Foo.__doc__).__name__ + ") is " + str(Foo.__doc__)"""
   446      )))
   447  
   448    @pytest.mark.xfail
   449    def testFunctionDocstring(self):
   450      want = "Foo.func.__doc__ (unicode) is function docstring\n"
   451      self.assertEqual((0, want), _GrumpRun(textwrap.dedent("""\
   452          from __future__ import unicode_literals
   453          "module docstring"
   454  
   455          class Foo(object):
   456            "class docstring"
   457  
   458            def func(self):
   459              "function docstring"
   460              return
   461  
   462          print "Foo.func.__doc__ (" + type(Foo.__doc__).__name__ + ") is " + str(Foo.func.__doc__)"""
   463      )))
   464  
   465    def testFunctionDocstringAbsent(self):
   466      want = "Foo.func.__doc__ (NoneType) is None\n"
   467      self.assertEqual((0, want), _GrumpRun(textwrap.dedent("""\
   468          from __future__ import unicode_literals
   469          "module docstring"
   470  
   471          class Foo(object):
   472            "class docstring"
   473  
   474            def func(self):
   475              return
   476  
   477          print "Foo.func.__doc__ (" + type(Foo.func.__doc__).__name__ + ") is " + str(Foo.func.__doc__)"""
   478      )))
   479  
   480    def testRaiseExitStatus(self):
   481      self.assertEqual(1, _GrumpRun('raise Exception')[0])
   482  
   483    def testRaiseInstance(self):
   484      self.assertEqual((0, 'foo\n'), _GrumpRun(textwrap.dedent("""\
   485          try:
   486            raise RuntimeError('foo')
   487            print 'bad'
   488          except RuntimeError as e:
   489            print e""")))
   490  
   491    def testRaiseTypeAndArg(self):
   492      self.assertEqual((0, 'foo\n'), _GrumpRun(textwrap.dedent("""\
   493          try:
   494            raise KeyError('foo')
   495            print 'bad'
   496          except KeyError as e:
   497            print e""")))
   498  
   499    def testRaiseAgain(self):
   500      self.assertEqual((0, 'foo\n'), _GrumpRun(textwrap.dedent("""\
   501          try:
   502            try:
   503              raise AssertionError('foo')
   504            except AssertionError:
   505              raise
   506          except Exception as e:
   507            print e""")))
   508  
   509    def testRaiseTraceback(self):
   510      self.assertEqual((0, ''), _GrumpRun(textwrap.dedent("""\
   511          import sys
   512          try:
   513            try:
   514              raise Exception
   515            except:
   516              e, _, tb = sys.exc_info()
   517              raise e, None, tb
   518          except:
   519            e2, _, tb2 = sys.exc_info()
   520          assert e is e2
   521          assert tb is tb2""")))
   522  
   523    def testReturn(self):
   524      self.assertEqual((0, 'bar\n'), _GrumpRun(textwrap.dedent("""\
   525          def foo():
   526            return 'bar'
   527          print foo()""")))
   528  
   529    def testTryBareExcept(self):
   530      self.assertEqual((0, ''), _GrumpRun(textwrap.dedent("""\
   531          try:
   532            raise AssertionError
   533          except:
   534            pass""")))
   535  
   536    def testTryElse(self):
   537      self.assertEqual((0, 'foo baz\n'), _GrumpRun(textwrap.dedent("""\
   538          try:
   539            print 'foo',
   540          except:
   541            print 'bar'
   542          else:
   543            print 'baz'""")))
   544  
   545    def testTryMultipleExcept(self):
   546      self.assertEqual((0, 'bar\n'), _GrumpRun(textwrap.dedent("""\
   547          try:
   548            raise AssertionError
   549          except RuntimeError:
   550            print 'foo'
   551          except AssertionError:
   552            print 'bar'
   553          except:
   554            print 'baz'""")))
   555  
   556    def testTryFinally(self):
   557      result = _GrumpRun(textwrap.dedent("""\
   558          try:
   559            print 'foo',
   560          finally:
   561            print 'bar'
   562          try:
   563            print 'foo',
   564            raise Exception
   565          finally:
   566            print 'bar'"""))
   567      self.assertEqual(1, result[0])
   568      self.assertIn('foo bar\nfoo bar\n', result[1])
   569      self.assertIn('Exception\n', result[1])
   570  
   571    def testWhile(self):
   572      self.assertEqual((0, '2\n1\n'), _GrumpRun(textwrap.dedent("""\
   573          i = 2
   574          while i:
   575            print i
   576            i -= 1""")))
   577  
   578    def testWhileElse(self):
   579      self.assertEqual((0, 'bar\n'), _GrumpRun(textwrap.dedent("""\
   580          while False:
   581            print 'foo'
   582          else:
   583            print 'bar'""")))
   584  
   585    def testWith(self):
   586      self.assertEqual((0, 'enter\n1\nexit\nenter\n2\nexit\n3\n'),
   587                       _GrumpRun(textwrap.dedent("""\
   588          class ContextManager(object):
   589            def __enter__(self):
   590              print "enter"
   591  
   592            def __exit__(self, exc_type, value, traceback):
   593              print "exit"
   594  
   595          a = ContextManager()
   596  
   597          with a:
   598            print 1
   599  
   600          try:
   601            with a:
   602              print 2
   603              raise RuntimeError
   604          except RuntimeError:
   605            print 3
   606          """)))
   607  
   608    def testWithAsMultiple(self):
   609      self.assertEqual((0, '1 2 3\n1 2 3\n'),
   610                       _GrumpRun(textwrap.dedent("""\
   611          class ContextManager(object):
   612            def __enter__(self):
   613              return (1, (2, 3))
   614            def __exit__(self, *args):
   615              pass
   616          with ContextManager() as [x, (y, z)], ContextManager() as [x2, (y2, z2)]:
   617            print x, y, z
   618            print x2, y2, z2
   619          """)))
   620  
   621    def testWithAs(self):
   622      self.assertEqual((0, '1 2 3\n'),
   623                       _GrumpRun(textwrap.dedent("""\
   624          class ContextManager(object):
   625            def __enter__(self):
   626              return (1, (2, 3))
   627            def __exit__(self, *args):
   628              pass
   629          with ContextManager() as [x, (y, z)]:
   630            print x, y, z
   631          """)))
   632  
   633    def testWriteExceptDispatcherBareExcept(self):
   634      visitor = stmt.StatementVisitor(_MakeModuleBlock())
   635      handlers = [ast.ExceptHandler(type=ast.Name(id='foo')),
   636                  ast.ExceptHandler(type=None)]
   637      self.assertEqual(visitor._write_except_dispatcher(  # pylint: disable=protected-access
   638          'exc', 'tb', handlers), [1, 2])
   639      expected = re.compile(r'ResolveGlobal\(.*foo.*\bIsInstance\(.*'
   640                            r'goto Label1.*goto Label2', re.DOTALL)
   641      self.assertRegexpMatches(visitor.writer.getvalue(), expected)
   642  
   643    def testWriteExceptDispatcherBareExceptionNotLast(self):
   644      visitor = stmt.StatementVisitor(_MakeModuleBlock())
   645      handlers = [ast.ExceptHandler(type=None),
   646                  ast.ExceptHandler(type=ast.Name(id='foo'))]
   647      self.assertRaisesRegexp(util.ParseError, r"default 'except:' must be last",
   648                              visitor._write_except_dispatcher,  # pylint: disable=protected-access
   649                              'exc', 'tb', handlers)
   650  
   651    def testWriteExceptDispatcherMultipleExcept(self):
   652      visitor = stmt.StatementVisitor(_MakeModuleBlock())
   653      handlers = [ast.ExceptHandler(type=ast.Name(id='foo')),
   654                  ast.ExceptHandler(type=ast.Name(id='bar'))]
   655      self.assertEqual(visitor._write_except_dispatcher(  # pylint: disable=protected-access
   656          'exc', 'tb', handlers), [1, 2])
   657      expected = re.compile(
   658          r'ResolveGlobal\(.*foo.*\bif .*\bIsInstance\(.*\{.*goto Label1.*'
   659          r'ResolveGlobal\(.*bar.*\bif .*\bIsInstance\(.*\{.*goto Label2.*'
   660          r'\bRaise\(exc\.ToObject\(\), nil, tb\.ToObject\(\)\)', re.DOTALL)
   661      self.assertRegexpMatches(visitor.writer.getvalue(), expected)
   662  
   663  
   664  def _MakeModuleBlock():
   665    return block.ModuleBlock(None, '__main__', '<test>', '',
   666                             imputil.FutureFeatures())
   667  
   668  
   669  def _ParseAndVisit(source):
   670    mod = pythonparser.parse(source)
   671    _, future_features = imputil.parse_future_features(mod)
   672    importer = imputil.Importer(None, 'foo', 'foo.py', False)
   673    b = block.ModuleBlock(importer, '__main__', '<test>',
   674                          source, future_features)
   675    visitor = stmt.StatementVisitor(b)
   676    visitor.visit(mod)
   677    return visitor
   678  
   679  
   680  def _GrumpRun(cmd):
   681    p = subprocess.Popen(['grumpy', 'run'], stdin=subprocess.PIPE,
   682                         stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
   683    out, _ = p.communicate(cmd)
   684    return p.returncode, out
   685  
   686  
   687  if __name__ == '__main__':
   688    shard_test.main()