import glob
import os
import re
import string
import types
import unittest

import compClust

if os.path.isdir(os.path.join(os.getcwd(), 'compClust','tests')):
  base_dir = os.path.join(os.getcwd(), 'compClust')
elif os.path.isdir(os.path.join(os.getcwd(), '..', '..', 'compClust','tests')):
  base_dir = os.path.join(os.getcwd(), '..', '..', 'compClust')
else:
  base_dir = None


class MakeTestPacakgeInitTestCases(unittest.TestCase):
  """Validate that makeTestPackageInits works correctly
  """
  def setUp(self):
    self.test_package = os.path.join(compClust.__path__[0],"tests")
    self.glob_pattern = os.path.join(self.test_package, "test*.py")
    self.init_module = os.path.join(self.test_package, "__init__.py")
    self.saved_module = os.path.join(self.test_package, ".__init__.py")
    if os.path.exists(self.init_module):
      os.rename(self.init_module, self.saved_module)
      
  def tearDown(self):
    if os.path.exists(self.saved_module):
      if os.path.exists(self.init_module):
        os.remove(self.init_module)
      os.rename(self.saved_module, self.init_module)
      
  def test_make_init(self):
    """Make sure that all the files in the package directory have a corresponding from x import line
    """
    
    makeTestPackageInits(self.test_package)
    init_contents = open(self.init_module,'r').readlines()
    test_files = glob.glob(self.glob_pattern)
    test_modules = [ string.replace(os.path.split(filename)[-1], ".py", "") for filename in test_files ]
    test_modules_copy = test_modules[:]
    
    for init_line in init_contents:
      # everything shoul
      init_list = init_line.split()
      if init_list[0] == "from":
        module_name = init_list[1]
        self.failUnless(module_name in test_modules_copy, "%s not in %s" % (module_name, test_modules_copy))
        test_modules_copy.remove(module_name)
        self.failUnless(init_list[2] == "import")
        self.failUnless(init_list[4] == "as")
    self.failUnless(len(test_modules_copy) == 0)
 
  def test_find_test_package(self):    
    tests = findTestPackages(self.test_package)
    
    # make sure we don't recurse into the .svn directory
    self.failUnless(len(tests.keys()) == 1, "%s" % (tests.keys()))
    self.failUnless(type(tests.values()[0] is types.ListType))
    self.failUnless(self.test_package in tests.keys())
    for filename in glob.glob(os.path.join(self.glob_pattern)):
      short_name = os.path.split(filename)[-1]
      self.failUnless(short_name in tests.values()[0], "%s in %s" % (short_name, tests.values()))
      
def findTestPackages(base_directory):
  test_modules = {}
  test_regexp = re.compile("^test.*\.py$")

  def isTestModule(t):
    # skip our master test program, but load any other test module
    if t == "testEverything.py":
      return 0
    elif test_regexp.match(t):
      return 1
    else:
      return 0
    
  # for all the items in our package
  version_directories = re.compile("(.svn)|(CVS)|(_darcs)")
  for path, dirs, files in os.walk(base_directory):
    # skip version control directories
    if version_directories.search(path):
      continue
    if os.path.split(path)[-1] != "tests":
      continue
    if len(files) > 0:
      test_modules[path] = []
    for f in files:
      if isTestModule(f):
        test_modules[path].append(f)

  return test_modules
    
def makeTestPackageInits(start_dir=base_dir):
  """For all of the test directories create a standard __init__.py file
  """
  
  file_header = "# This file is autogenerated, (C) 2005 Caltech\n"
  tests = findTestPackages(start_dir)
  
  for package, files in tests.items():
    # make sure its our file
    init_path = os.path.join(package, "__init__.py")
    if os.path.exists(init_path):
      init = open(init_path, 'r')
      header = string.strip(init.readline())
      if header != string.strip(file_header):
        msg = "%s was not one of our files\ngot     :%s\nexpected:%s" 
        msg %= (init_path, header, string.strip(file_header))
        raise ValueError(msg)
      init.close()
    # go ahead and write the new package file
    init = open(init_path, 'w')
    init.write(file_header)
    for filename in files:
      module_name = string.replace(filename, ".py", "")
      class_name = string.replace(module_name, "test", "") + "TestCases"
      package_parts = string.split(package, os.path.sep)
      # As all of our tests are in the package.tests, we need -2 to grab the
      # name "package"
      as_name = package_parts[-2] + class_name
      init.write("from %s import %s as %s\n" % (module_name, class_name, as_name))
    init.close()

if __name__ == "__main__":
 makeTestPackageInits(base_dir)
