import common
import os, doctest, glob, sys
from django.conf import settings
from django.db import connection
import django.test.utils

# doctest takes a copy+paste log of a Python interactive session, runs a Python
# interpreter, and replays all the inputs from the log, checking that the
# outputs all match the log.  This allows us to easily test behavior and
# document functions at the same time, since the log shows exactly how functions
# are called and what their outputs look like.  See
# http://www.python.org/doc/2.4.3/lib/module-doctest.html for more details.

# In this file, we run doctest on all files found in the doctests/ directory.
# We use django.test.utils to run the tests against a fresh test database every
# time.

class DoctestRunner(object):
    _PRINT_AFTER = 'Ran %d tests from %s'

    def __init__(self, app_dir, app_module_name):
        self._app_dir = app_dir
        self._app_module_name = app_module_name


    def _get_doctest_paths(self):
        doctest_dir = os.path.join(self._app_dir, 'doctests')
        doctest_paths = [os.path.join(doctest_dir, filename) for filename
                         in os.listdir(doctest_dir)
                         if not filename.startswith('.')
                         if not filename.endswith('~')]
        return sorted(doctest_paths)


    def _get_modules(self):
        modules = []
        module_names = [os.path.basename(filename)[:-3]
                        for filename
                        in glob.glob(os.path.join(self._app_dir, '*.py'))
                        if '__init__' not in filename
                        and 'test.py' not in filename]
        # TODO: use common.setup_modules.import_module()
        app_module = __import__(self._app_module_name, globals(), locals(),
                                module_names)
        for module_name in module_names:
            modules.append(getattr(app_module, module_name))
        return modules


    def run_tests(self):
        """
        module_list is ignored - we're just required to have this signature as a
        Django test runner.
        """
        doctest_paths = self._get_doctest_paths()
        modules = self._get_modules()
        total_errors = 0
        old_db = settings.DATABASES['default']['NAME']
        django.test.utils.setup_test_environment()
        connection.creation.create_test_db()
        try:
            for module in modules:
                failures, test_count = doctest.testmod(module)
                print self._PRINT_AFTER % (test_count, module.__name__)
                total_errors += failures
            for path in doctest_paths:
                failures, test_count = doctest.testfile(path,
                                                        module_relative=False)
                print self._PRINT_AFTER % (test_count, path)
                total_errors += failures
        finally:
            connection.creation.destroy_test_db(old_db)
            django.test.utils.teardown_test_environment()
        print
        if total_errors == 0:
            print 'OK'
        else:
            print 'FAIL: %d errors' % total_errors
        return total_errors