"""
Test for import machinery
"""
import unittest
import sys
import textwrap
import subprocess
import os
from modulegraph import modulegraph

class TestNativeImport (unittest.TestCase):
    # The tests check that Python's import statement
    # works as these tests expect.

    def importModule(self, name):
        if '.' in name:
            script = textwrap.dedent("""\
                try:
                    import %s
                except ImportError:
                    import %s
                print (%s.__name__)
            """) %(name, name.rsplit('.', 1)[0], name)
        else:
            script = textwrap.dedent("""\
                import %s
                print (%s.__name__)
            """) %(name, name)

        p = subprocess.Popen([sys.executable, '-c', script],
                stdout=subprocess.PIPE,
                stderr=subprocess.STDOUT,
                cwd=os.path.join(
                    os.path.dirname(os.path.abspath(__file__)),
                    'testpkg-relimport'),
        )
        data = p.communicate()[0]
        if sys.version_info[0] != 2:
            data = data.decode('UTF-8')
        data = data.strip()

        if data.endswith(' refs]'):
            # with --with-pydebug builds
            data = data.rsplit('\n', 1)[0].strip()

        sts = p.wait()

        if sts != 0:
            print (data)
        self.assertEqual(sts, 0)
        return data


    def testRootModule(self):
        m = self.importModule('mod')
        self.assertEqual(m, 'mod')

    def testRootPkg(self):
        m = self.importModule('pkg')
        self.assertEqual(m, 'pkg')

    def testSubModule(self):
        m = self.importModule('pkg.mod')
        self.assertEqual(m, 'pkg.mod')

    if sys.version_info[0] == 2:
        def testOldStyle(self):
            m = self.importModule('pkg.oldstyle.mod')
            self.assertEqual(m, 'pkg.mod')
    else:
        # python3 always has __future__.absolute_import
        def testOldStyle(self):
            m = self.importModule('pkg.oldstyle.mod')
            self.assertEqual(m, 'mod')

    def testNewStyle(self):
        m = self.importModule('pkg.toplevel.mod')
        self.assertEqual(m, 'mod')

    def testRelativeImport(self):
        m = self.importModule('pkg.relative.mod')
        self.assertEqual(m, 'pkg.mod')

        m = self.importModule('pkg.subpkg.relative.mod')
        self.assertEqual(m, 'pkg.mod')

        m = self.importModule('pkg.subpkg.mod2.mod')
        self.assertEqual(m, 'pkg.sub2.mod')

        m = self.importModule('pkg.subpkg.relative2')
        self.assertEqual(m, 'pkg.subpkg.relative2')

class TestModuleGraphImport (unittest.TestCase):
    if not hasattr(unittest.TestCase, 'assertIsInstance'):
        def assertIsInstance(self, value, types):
            if not isinstance(value, types):
                self.fail("%r is not an instance of %r"%(value, types))

    def setUp(self):
        root = os.path.join(
                os.path.dirname(os.path.abspath(__file__)),
                'testpkg-relimport')
        self.mf = modulegraph.ModuleGraph(path=[ root ] + sys.path)
        #self.mf.debug = 999
        self.mf.run_script(os.path.join(root, 'script.py'))


    def testRootModule(self):
        node = self.mf.findNode('mod')
        self.assertIsInstance(node, modulegraph.SourceModule)
        self.assertEqual(node.identifier, 'mod')

    def testRootPkg(self):
        node = self.mf.findNode('pkg')
        self.assertIsInstance(node, modulegraph.Package)
        self.assertEqual(node.identifier, 'pkg')

    def testSubModule(self):
        node = self.mf.findNode('pkg.mod')
        self.assertIsInstance(node, modulegraph.SourceModule)
        self.assertEqual(node.identifier, 'pkg.mod')

    if sys.version_info[0] == 2:
        def testOldStyle(self):
            node = self.mf.findNode('pkg.oldstyle')
            self.assertIsInstance(node, modulegraph.SourceModule)
            self.assertEqual(node.identifier, 'pkg.oldstyle')
            sub = [ n for n in self.mf.get_edges(node)[0] if n.identifier != '__future__' ][0]
            self.assertEqual(sub.identifier, 'pkg.mod')
    else:
        # python3 always has __future__.absolute_import
        def testOldStyle(self):
            node = self.mf.findNode('pkg.oldstyle')
            self.assertIsInstance(node, modulegraph.SourceModule)
            self.assertEqual(node.identifier, 'pkg.oldstyle')
            sub = [ n for n in self.mf.get_edges(node)[0] if n.identifier != '__future__' ][0]
            self.assertEqual(sub.identifier, 'mod')

    def testNewStyle(self):
        node = self.mf.findNode('pkg.toplevel')
        self.assertIsInstance(node, modulegraph.SourceModule)
        self.assertEqual(node.identifier, 'pkg.toplevel')
        sub = [ n for n in self.mf.get_edges(node)[0] if n.identifier != '__future__' ][0]
        self.assertEqual(sub.identifier, 'mod')

    def testRelativeImport(self):
        node = self.mf.findNode('pkg.relative')
        self.assertIsInstance(node, modulegraph.SourceModule)
        self.assertEqual(node.identifier, 'pkg.relative')
        sub = [ n for n in self.mf.get_edges(node)[0] if n.identifier != '__future__' ][0]
        self.assertIsInstance(sub, modulegraph.Package)
        self.assertEqual(sub.identifier, 'pkg')

        node = self.mf.findNode('pkg.subpkg.relative')
        self.assertIsInstance(node, modulegraph.SourceModule)
        self.assertEqual(node.identifier, 'pkg.subpkg.relative')
        sub = [ n for n in self.mf.get_edges(node)[0] if n.identifier != '__future__' ][0]
        self.assertIsInstance(sub, modulegraph.Package)
        self.assertEqual(sub.identifier, 'pkg')

        node = self.mf.findNode('pkg.subpkg.mod2')
        self.assertIsInstance(node, modulegraph.SourceModule)
        self.assertEqual(node.identifier, 'pkg.subpkg.mod2')
        sub = [ n for n in self.mf.get_edges(node)[0] if n.identifier != '__future__' ][0]
        self.assertIsInstance(sub, modulegraph.SourceModule)
        self.assertEqual(sub.identifier, 'pkg.sub2.mod')

        node = self.mf.findNode('pkg.subpkg.relative2')
        self.assertIsInstance(node, modulegraph.SourceModule)
        self.assertEqual(node.identifier, 'pkg.subpkg.relative2')

        node = self.mf.findNode('pkg.relimport')
        self.assertIsInstance(node, modulegraph.SourceModule)

class TestRegressions1 (unittest.TestCase):
    if not hasattr(unittest.TestCase, 'assertIsInstance'):
        def assertIsInstance(self, value, types):
            if not isinstance(value, types):
                self.fail("%r is not an instance of %r", value, types)

    def setUp(self):
        root = os.path.join(
                os.path.dirname(os.path.abspath(__file__)),
                'testpkg-regr1')
        self.mf = modulegraph.ModuleGraph(path=[ root ] + sys.path)
        self.mf.run_script(os.path.join(root, 'main_script.py'))

    def testRegr1(self):
        node = self.mf.findNode('pkg.a')
        self.assertIsInstance(node, modulegraph.SourceModule)
        node = self.mf.findNode('pkg.b')
        self.assertIsInstance(node, modulegraph.SourceModule)


    def testMissingPathEntry(self):
        root = os.path.join(
                os.path.dirname(os.path.abspath(__file__)),
                'nosuchdirectory')
        try:
            mf = modulegraph.ModuleGraph(path=[ root ] + sys.path)
        except os.error:
            self.fail('modulegraph initialiser raises os.error')

class TestRegressions2 (unittest.TestCase):
    if not hasattr(unittest.TestCase, 'assertIsInstance'):
        def assertIsInstance(self, value, types):
            if not isinstance(value, types):
                self.fail("%r is not an instance of %r"%(value, types))

    def setUp(self):
        root = os.path.join(
                os.path.dirname(os.path.abspath(__file__)),
                'testpkg-regr2')
        self.mf = modulegraph.ModuleGraph(path=[ root ] + sys.path)
        self.mf.run_script(os.path.join(root, 'main_script.py'))

    def testRegr1(self):
        node = self.mf.findNode('pkg.base')
        self.assertIsInstance(node, modulegraph.SourceModule)
        node = self.mf.findNode('pkg.pkg')
        self.assertIsInstance(node, modulegraph.SourceModule)

class TestRegressions3 (unittest.TestCase):
    if not hasattr(unittest.TestCase, 'assertIsInstance'):
        def assertIsInstance(self, value, types):
            if not isinstance(value, types):
                self.fail("%r is not an instance of %r"%(value, types))

    def setUp(self):
        root = os.path.join(
                os.path.dirname(os.path.abspath(__file__)),
                'testpkg-regr3')
        self.mf = modulegraph.ModuleGraph(path=[ root ] + sys.path)
        self.mf.run_script(os.path.join(root, 'script.py'))

    def testRegr1(self):
        node = self.mf.findNode('mypkg.distutils')
        self.assertIsInstance(node, modulegraph.Package)
        node = self.mf.findNode('mypkg.distutils.ccompiler')
        self.assertIsInstance(node, modulegraph.SourceModule)
        self.assertTrue(node.filename.startswith(os.path.dirname(__file__)))

        import distutils.sysconfig, distutils.ccompiler
        node = self.mf.findNode('distutils.ccompiler')
        self.assertIsInstance(node, modulegraph.SourceModule)
        self.assertEqual(os.path.dirname(node.filename),
                os.path.dirname(distutils.ccompiler.__file__))

        node = self.mf.findNode('distutils.sysconfig')
        self.assertIsInstance(node, modulegraph.SourceModule)
        self.assertEqual(os.path.dirname(node.filename),
                os.path.dirname(distutils.sysconfig.__file__))

class TestRegression4 (unittest.TestCase):
    if not hasattr(unittest.TestCase, 'assertIsInstance'):
        def assertIsInstance(self, value, types):
            if not isinstance(value, types):
                self.fail("%r is not an instance of %r"%(value, types))

    def setUp(self):
        root = os.path.join(
                os.path.dirname(os.path.abspath(__file__)),
                'testpkg-regr4')
        self.mf = modulegraph.ModuleGraph(path=[ root ] + sys.path)
        self.mf.run_script(os.path.join(root, 'script.py'))

    def testRegr1(self):
        node = self.mf.findNode('pkg.core')
        self.assertIsInstance(node, modulegraph.Package)

        node = self.mf.findNode('pkg.core.callables')
        self.assertIsInstance(node, modulegraph.SourceModule)

        node = self.mf.findNode('pkg.core.listener')
        self.assertIsInstance(node, modulegraph.SourceModule)

        node = self.mf.findNode('pkg.core.listenerimpl')
        self.assertIsInstance(node, modulegraph.SourceModule)

class TestRegression5 (unittest.TestCase):
    if not hasattr(unittest.TestCase, 'assertIsInstance'):
        def assertIsInstance(self, value, types):
            if not isinstance(value, types):
                self.fail("%r is not an instance of %r"%(value, types))

    def setUp(self):
        root = os.path.join(
                os.path.dirname(os.path.abspath(__file__)),
                'testpkg-regr5')
        self.mf = modulegraph.ModuleGraph(path=[ root ] + sys.path)
        self.mf.run_script(os.path.join(root, 'script.py'))

    def testRegr1(self):
        node = self.mf.findNode('distutils')
        self.assertIsInstance(node, modulegraph.Package)
        self.assertIn('distutils/__init__', node.filename)

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