tests for the asdl parser in parserasdl py import importlib machinery import importlib util import os from os path import dirname import sys import sysconfig import unittest this test is only relevant for fromsource builds of python if not sysconfig ispythonbuild raise unittest skiptest test irrelevant for an installed python srcbase dirnamedirnamedirnamefile parserdir os path joinsrcbase parser class testasdlparserunittest testcase classmethod def setupclasscls loads the asdl module dynamically since it s not in a real importable package parses python asdl into an ast module and run the check on it there s no need to do this for each test method hence setupclass sys path insert0 parserdir loader importlib machinery sourcefileloader asdl os path joinparserdir asdl py spec importlib util specfromloader asdl loader module importlib util modulefromspecspec loader execmodulemodule cls asdl module cls mod cls asdl parseos path joinparserdir python asdl cls asserttruecls asdl checkcls mod module validation failed classmethod def teardownclasscls del sys path0 def setupself alias stuff from the class for convenience self asdl testasdlparser asdl self mod testasdlparser mod self types self mod types def testmoduleself self assertequalself mod name python self assertin stmt self types self assertin expr self types self assertin mod self types def testdefinitionsself defs self mod dfns self assertisinstancedefs0 self asdl type self assertisinstancedefs0 value self asdl sum self assertisinstanceself types withitem self asdl product self assertisinstanceself types alias self asdl product def testproductself alias self types alias self assertequal stralias productfieldidentifier name fieldidentifier asname opttrue fieldint lineno fieldint coloffset fieldint endlineno opttrue fieldint endcoloffset opttrue def testattributesself stmt self types stmt self assertequallenstmt attributes 4 self assertequalreprstmt attributes0 fieldint lineno self assertequalreprstmt attributes1 fieldint coloffset self assertequalreprstmt attributes2 fieldint endlineno opttrue self assertequalreprstmt attributes3 fieldint endcoloffset opttrue def testconstructorfieldsself ehandler self types excepthandler self assertequallenehandler types 1 self assertequallenehandler attributes 4 cons ehandler types0 self assertisinstancecons self asdl constructor self assertequallencons fields 3 f0 cons fields0 self assertequalf0 type expr self assertequalf0 name type self asserttruef0 opt f1 cons fields1 self assertequalf1 type identifier self assertequalf1 name name self asserttruef1 opt f2 cons fields2 self assertequalf2 type stmt self assertequalf2 name body self assertfalsef2 opt self asserttruef2 seq def testvisitorself class customvisitorself asdl visitorbase def initself super init self nameswithseq def visitmoduleself mod for dfn in mod dfns self visitdfn def visittypeself type self visittype value def visitsumself sum for t in sum types self visitt def visitconstructorself cons for f in cons fields if f seq self nameswithseq appendcons name v customvisitor v visitself types mod self assertequalv nameswithseq module module interactive functiontype if name main unittest main this test is only relevant for from source builds of python loads the asdl module dynamically since it s not in a real importable package parses python asdl into an ast module and run the check on it there s no need to do this for each test method hence setupclass alias stuff from the class for convenience
import importlib.machinery
import importlib.util
import os
from os.path import dirname
import sys
import sysconfig
import unittest



if not sysconfig.is_python_build():
    raise unittest.SkipTest('test irrelevant for an installed Python')

src_base = dirname(dirname(dirname(__file__)))
parser_dir = os.path.join(src_base, 'Parser')


class TestAsdlParser(unittest.TestCase):
    @classmethod
    def setUpClass(cls):
        
        
        
        
        sys.path.insert(0, parser_dir)
        loader = importlib.machinery.SourceFileLoader(
                'asdl', os.path.join(parser_dir, 'asdl.py'))
        spec = importlib.util.spec_from_loader('asdl', loader)
        module = importlib.util.module_from_spec(spec)
        loader.exec_module(module)
        cls.asdl = module
        cls.mod = cls.asdl.parse(os.path.join(parser_dir, 'Python.asdl'))
        cls.assertTrue(cls.asdl.check(cls.mod), 'Module validation failed')

    @classmethod
    def tearDownClass(cls):
        del sys.path[0]

    def setUp(self):
        
        self.asdl = TestAsdlParser.asdl
        self.mod = TestAsdlParser.mod
        self.types = self.mod.types

    def test_module(self):
        self.assertEqual(self.mod.name, 'Python')
        self.assertIn('stmt', self.types)
        self.assertIn('expr', self.types)
        self.assertIn('mod', self.types)

    def test_definitions(self):
        defs = self.mod.dfns
        self.assertIsInstance(defs[0], self.asdl.Type)
        self.assertIsInstance(defs[0].value, self.asdl.Sum)

        self.assertIsInstance(self.types['withitem'], self.asdl.Product)
        self.assertIsInstance(self.types['alias'], self.asdl.Product)

    def test_product(self):
        alias = self.types['alias']
        self.assertEqual(
            str(alias),
            'Product([Field(identifier, name), Field(identifier, asname, opt=True)], '
            '[Field(int, lineno), Field(int, col_offset), '
            'Field(int, end_lineno, opt=True), Field(int, end_col_offset, opt=True)])')

    def test_attributes(self):
        stmt = self.types['stmt']
        self.assertEqual(len(stmt.attributes), 4)
        self.assertEqual(repr(stmt.attributes[0]), 'Field(int, lineno)')
        self.assertEqual(repr(stmt.attributes[1]), 'Field(int, col_offset)')
        self.assertEqual(repr(stmt.attributes[2]), 'Field(int, end_lineno, opt=True)')
        self.assertEqual(repr(stmt.attributes[3]), 'Field(int, end_col_offset, opt=True)')

    def test_constructor_fields(self):
        ehandler = self.types['excepthandler']
        self.assertEqual(len(ehandler.types), 1)
        self.assertEqual(len(ehandler.attributes), 4)

        cons = ehandler.types[0]
        self.assertIsInstance(cons, self.asdl.Constructor)
        self.assertEqual(len(cons.fields), 3)

        f0 = cons.fields[0]
        self.assertEqual(f0.type, 'expr')
        self.assertEqual(f0.name, 'type')
        self.assertTrue(f0.opt)

        f1 = cons.fields[1]
        self.assertEqual(f1.type, 'identifier')
        self.assertEqual(f1.name, 'name')
        self.assertTrue(f1.opt)

        f2 = cons.fields[2]
        self.assertEqual(f2.type, 'stmt')
        self.assertEqual(f2.name, 'body')
        self.assertFalse(f2.opt)
        self.assertTrue(f2.seq)

    def test_visitor(self):
        class CustomVisitor(self.asdl.VisitorBase):
            def __init__(self):
                super().__init__()
                self.names_with_seq = []

            def visitModule(self, mod):
                for dfn in mod.dfns:
                    self.visit(dfn)

            def visitType(self, type):
                self.visit(type.value)

            def visitSum(self, sum):
                for t in sum.types:
                    self.visit(t)

            def visitConstructor(self, cons):
                for f in cons.fields:
                    if f.seq:
                        self.names_with_seq.append(cons.name)

        v = CustomVisitor()
        v.visit(self.types['mod'])
        self.assertEqual(v.names_with_seq,
                         ['Module', 'Module', 'Interactive', 'FunctionType'])


if __name__ == '__main__':
    unittest.main()