import functools
import importlib.util
import os
import py_compile
import shutil
import stat
import subprocess
import sys
import tempfile
import unittest

from test import support
from test.support import os_helper, script_helper


def without_source_date_epoch(fxn):
    """Runs function with SOURCE_DATE_EPOCH unset."""
    @functools.wraps(fxn)
    def wrapper(*args, **kwargs):
        with os_helper.EnvironmentVarGuard() as env:
            env.unset('SOURCE_DATE_EPOCH')
            return fxn(*args, **kwargs)
    return wrapper


def with_source_date_epoch(fxn):
    """Runs function with SOURCE_DATE_EPOCH set."""
    @functools.wraps(fxn)
    def wrapper(*args, **kwargs):
        with os_helper.EnvironmentVarGuard() as env:
            env['SOURCE_DATE_EPOCH'] = '123456789'
            return fxn(*args, **kwargs)
    return wrapper


# Run tests with SOURCE_DATE_EPOCH set or unset explicitly.
class SourceDateEpochTestMeta(type(unittest.TestCase)):
    def __new__(mcls, name, bases, dct, *, source_date_epoch):
        cls = super().__new__(mcls, name, bases, dct)

        for attr in dir(cls):
            if attr.startswith('test_'):
                meth = getattr(cls, attr)
                if source_date_epoch:
                    wrapper = with_source_date_epoch(meth)
                else:
                    wrapper = without_source_date_epoch(meth)
                setattr(cls, attr, wrapper)

        return cls


class PyCompileTestsBase:

    def setUp(self):
        self.directory = tempfile.mkdtemp(dir=os.getcwd())
        self.source_path = os.path.join(self.directory, '_test.py')
        self.pyc_path = self.source_path + 'c'
        try:
            self.cache_path = importlib.util.cache_from_source(self.source_path)
        except NotImplementedError:
            self.cache_path = None
        self.cwd_drive = os.path.splitdrive(os.getcwd())[0]
        # In these tests we compute relative paths.  When using Windows, the
        # current working directory path and the 'self.source_path' might be
        # on different drives.  Therefore we need to switch to the drive where
        # the temporary source file lives.
        drive = os.path.splitdrive(self.source_path)[0]
        if drive:
            os.chdir(drive)
        with open(self.source_path, 'w') as file:
            file.write('x = 123\n')

    def tearDown(self):
        shutil.rmtree(self.directory)
        if self.cwd_drive:
            os.chdir(self.cwd_drive)

    def assert_cache_path_exists(self, should_exist=True):
        if self.cache_path:
            if should_exist:
                self.assertTrue(os.path.exists(self.cache_path))
            else:
                self.assertFalse(os.path.exists(self.cache_path))
            return
        cache_dir = os.path.join(self.directory, '__pycache__')
        if not os.path.isdir(cache_dir):
            if should_exist:
                self.fail('no __pycache__ directory exists')
            return
        for f in os.listdir(cache_dir):
            if f.startswith('_test.') and f.endswith('.pyc'):
                if should_exist:
                    return
                self.fail(f'__pycache__/{f} was created')
        else:
            if should_exist:
                self.fail('no __pycache__/_test.*.pyc file exists')

    def test_absolute_path(self):
        py_compile.compile(self.source_path, self.pyc_path)
        self.assertTrue(os.path.exists(self.pyc_path))
        self.assert_cache_path_exists(False)

    def test_do_not_overwrite_symlinks(self):
        # In the face of a cfile argument being a symlink, bail out.
        # Issue #17222
        try:
            os.symlink(self.pyc_path + '.actual', self.pyc_path)
        except (NotImplementedError, OSError):
            self.skipTest('need to be able to create a symlink for a file')
        else:
            assert os.path.islink(self.pyc_path)
            with self.assertRaises(FileExistsError):
                py_compile.compile(self.source_path, self.pyc_path)

    @unittest.skipIf(not os.path.exists(os.devnull) or os.path.isfile(os.devnull),
                     'requires os.devnull and for it to be a non-regular file')
    def test_do_not_overwrite_nonregular_files(self):
        # In the face of a cfile argument being a non-regular file, bail out.
        # Issue #17222
        with self.assertRaises(FileExistsError):
            py_compile.compile(self.source_path, os.devnull)

    @unittest.skipIf(sys.implementation.cache_tag is None,
                     'requires sys.implementation.cache_tag is not None')
    def test_cache_path(self):
        py_compile.compile(self.source_path)
        self.assert_cache_path_exists(True)

    def test_cwd(self):
        with os_helper.change_cwd(self.directory):
            py_compile.compile(os.path.basename(self.source_path),
                               os.path.basename(self.pyc_path))
        self.assertTrue(os.path.exists(self.pyc_path))
        self.assert_cache_path_exists(False)

    def test_relative_path(self):
        py_compile.compile(os.path.relpath(self.source_path),
                           os.path.relpath(self.pyc_path))
        self.assertTrue(os.path.exists(self.pyc_path))
        self.assert_cache_path_exists(False)

    @os_helper.skip_if_dac_override
    @unittest.skipIf(os.name == 'nt',
                     'cannot control directory permissions on Windows')
    @os_helper.skip_unless_working_chmod
    def test_exceptions_propagate(self):
        # Make sure that exceptions raised thanks to issues with writing
        # bytecode.
        # http://bugs.python.org/issue17244
        mode = os.stat(self.directory)
        os.chmod(self.directory, stat.S_IREAD)
        try:
            with self.assertRaises(IOError):
                py_compile.compile(self.source_path, self.pyc_path)
        finally:
            os.chmod(self.directory, mode.st_mode)

    def test_bad_coding(self):
        bad_coding = os.path.join(os.path.dirname(__file__),
                                  'tokenizedata',
                                  'bad_coding2.py')
        with support.captured_stderr():
            self.assertIsNone(py_compile.compile(bad_coding, self.pyc_path,
                                                 doraise=False))
        self.assertFalse(os.path.exists(self.pyc_path))

    def test_source_date_epoch(self):
        py_compile.compile(self.source_path, self.pyc_path)
        self.assertTrue(os.path.exists(self.pyc_path))
        self.assert_cache_path_exists(False)
        with open(self.pyc_path, 'rb') as fp:
            flags = importlib._bootstrap_external._classify_pyc(
                fp.read(), 'test', {})
        if os.environ.get('SOURCE_DATE_EPOCH'):
            expected_flags = 0b11
        else:
            expected_flags = 0b00

        self.assertEqual(flags, expected_flags)

    @unittest.skipIf(sys.flags.optimize > 0, 'test does not work with -O')
    @unittest.skipIf(sys.implementation.cache_tag is None,
                     'requires sys.implementation.cache_tag is not None')
    def test_double_dot_no_clobber(self):
        # http://bugs.python.org/issue22966
        # py_compile foo.bar.py -> __pycache__/foo.cpython-34.pyc
        weird_path = os.path.join(self.directory, 'foo.bar.py')
        cache_path = importlib.util.cache_from_source(weird_path)
        pyc_path = weird_path + 'c'
        head, tail = os.path.split(cache_path)
        penultimate_tail = os.path.basename(head)
        self.assertEqual(
            os.path.join(penultimate_tail, tail),
            os.path.join(
                '__pycache__',
                'foo.bar.{}.pyc'.format(sys.implementation.cache_tag)))
        with open(weird_path, 'w') as file:
            file.write('x = 123\n')
        py_compile.compile(weird_path)
        self.assertTrue(os.path.exists(cache_path))
        self.assertFalse(os.path.exists(pyc_path))

    @unittest.skipIf(sys.implementation.cache_tag is None,
                     'requires sys.implementation.cache_tag is not None')
    def test_optimization_path(self):
        # Specifying optimized bytecode should lead to a path reflecting that.
        self.assertIn('opt-2', py_compile.compile(self.source_path, optimize=2))

    def test_invalidation_mode(self):
        py_compile.compile(
            self.source_path,
            self.pyc_path,
            invalidation_mode=py_compile.PycInvalidationMode.CHECKED_HASH,
        )
        with open(self.pyc_path, 'rb') as fp:
            flags = importlib._bootstrap_external._classify_pyc(
                fp.read(), 'test', {})
        self.assertEqual(flags, 0b11)
        py_compile.compile(
            self.source_path,
            self.pyc_path,
            invalidation_mode=py_compile.PycInvalidationMode.UNCHECKED_HASH,
        )
        with open(self.pyc_path, 'rb') as fp:
            flags = importlib._bootstrap_external._classify_pyc(
                fp.read(), 'test', {})
        self.assertEqual(flags, 0b1)

    def test_quiet(self):
        bad_coding = os.path.join(os.path.dirname(__file__),
                                  'tokenizedata',
                                  'bad_coding2.py')
        with support.captured_stderr() as stderr:
            self.assertIsNone(py_compile.compile(bad_coding, self.pyc_path, doraise=False, quiet=2))
            self.assertIsNone(py_compile.compile(bad_coding, self.pyc_path, doraise=True, quiet=2))
            self.assertEqual(stderr.getvalue(), '')
            with self.assertRaises(py_compile.PyCompileError):
                py_compile.compile(bad_coding, self.pyc_path, doraise=True, quiet=1)

    def test_utf7_decoded_cr_compiles(self):
        with open(self.source_path, 'wb') as file:
            file.write(b"#coding=U7+AA0''\n")

        pyc_path = py_compile.compile(self.source_path, self.pyc_path, doraise=True)
        self.assertEqual(pyc_path, self.pyc_path)
        self.assertTrue(os.path.exists(self.pyc_path))


class PyCompileTestsWithSourceEpoch(PyCompileTestsBase,
                                    unittest.TestCase,
                                    metaclass=SourceDateEpochTestMeta,
                                    source_date_epoch=True):
    pass


class PyCompileTestsWithoutSourceEpoch(PyCompileTestsBase,
                                       unittest.TestCase,
                                       metaclass=SourceDateEpochTestMeta,
                                       source_date_epoch=False):
    pass


class PyCompileCLITestCase(unittest.TestCase):

    def setUp(self):
        self.directory = tempfile.mkdtemp()
        self.source_path = os.path.join(self.directory, '_test.py')
        try:
            self.cache_path = importlib.util.cache_from_source(self.source_path,
                                    optimization='' if __debug__ else 1)
        except NotImplementedError:
            # py_compile.main() assumes legacy pyc path if there is no cache_tag
            self.cache_path = self.source_path + 'c'
        with open(self.source_path, 'w') as file:
            file.write('x = 123\n')

    def tearDown(self):
        os_helper.rmtree(self.directory)

    @support.requires_subprocess()
    def pycompilecmd(self, *args, **kwargs):
        # assert_python_* helpers don't return proc object. We'll just use
        # subprocess.run() instead of spawn_python() and its friends to test
        # stdin support of the CLI.
        opts = '-m' if __debug__ else '-Om'
        if args and args[0] == '-' and 'input' in kwargs:
            return subprocess.run([sys.executable, opts, 'py_compile', '-'],
                                  input=kwargs['input'].encode(),
                                  capture_output=True)
        return script_helper.assert_python_ok(opts, 'py_compile', *args, **kwargs)

    def pycompilecmd_failure(self, *args):
        return script_helper.assert_python_failure('-m', 'py_compile', *args)

    def test_stdin(self):
        self.assertFalse(os.path.exists(self.cache_path))
        result = self.pycompilecmd('-', input=self.source_path)
        self.assertEqual(result.returncode, 0)
        self.assertEqual(result.stdout, b'')
        self.assertEqual(result.stderr, b'')
        self.assertTrue(os.path.exists(self.cache_path))

    def test_with_files(self):
        rc, stdout, stderr = self.pycompilecmd(self.source_path, self.source_path)
        self.assertEqual(rc, 0)
        self.assertEqual(stdout, b'')
        self.assertEqual(stderr, b'')
        self.assertTrue(os.path.exists(self.cache_path))

    def test_bad_syntax(self):
        bad_syntax = os.path.join(os.path.dirname(__file__),
                                  'tokenizedata',
                                  'badsyntax_3131.py')
        rc, stdout, stderr = self.pycompilecmd_failure(bad_syntax)
        self.assertEqual(rc, 1)
        self.assertEqual(stdout, b'')
        self.assertIn(b'SyntaxError', stderr)

    def test_bad_syntax_with_quiet(self):
        bad_syntax = os.path.join(os.path.dirname(__file__),
                                  'tokenizedata',
                                  'badsyntax_3131.py')
        rc, stdout, stderr = self.pycompilecmd_failure('-q', bad_syntax)
        self.assertEqual(rc, 1)
        self.assertEqual(stdout, b'')
        self.assertEqual(stderr, b'')

    def test_file_not_exists(self):
        should_not_exists = os.path.join(os.path.dirname(__file__), 'should_not_exists.py')
        rc, stdout, stderr = self.pycompilecmd_failure(self.source_path, should_not_exists)
        self.assertEqual(rc, 1)
        self.assertEqual(stdout, b'')
        self.assertIn(b'no such file or directory', stderr.lower())

    def test_file_not_exists_with_quiet(self):
        should_not_exists = os.path.join(os.path.dirname(__file__), 'should_not_exists.py')
        rc, stdout, stderr = self.pycompilecmd_failure('-q', self.source_path, should_not_exists)
        self.assertEqual(rc, 1)
        self.assertEqual(stdout, b'')
        self.assertEqual(stderr, b'')


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