""" 
test the import order of loading libraries which are all dependent to libcaldb4
"""

from __future__ import print_function

import unittest
import sys,os
from os import *
from sys import *

def whoami():
    return sys._getframe(1).f_code.co_filename+'.'+sys._getframe(1).f_code.co_name


DEBUG=0
class TestImports(unittest.TestCase):
    def setUp(self):
        global DEBUG
        if "-v" in  sys.argv:
            DEBUG=1

#=============================================================================
#
#   --- The Tester ---
#
#=============================================================================
   
#======================================================
# test_failOrder* - test the abnormal procedure on OS X
#=======================================================
    def _test_000_okOrder1(self):
        try:
            __import__("pixlib")
            __import__("caldb4")
            print("Okay to 'import pixlib,caldb4'") 
        except ImportError as e:
            raise ImportError("fail to 'import pixlib,caldb4'\n%s" % e)
        except OSError as e:
            raise OSError("fail to 'import pixlib,caldb4'\n%s" % e)
        except e:
            raise "fail to 'import pixlib,caldb4'\n" 
     

    def _test_000_okOrder2(self):
        try:
            t1 = __import__("pixlib")
            t4 = __import__("paramio")
            t2 = __import__("caldb4")
            print("Okay to 'import pixlib,paramio,caldb4'") 
        except ImportError as e:
            raise ImportError("fail to 'import pixlib,paramio,caldb4'\n%s" % e)
        except OSError as e:
            raise OSError("fail to 'import pixlib,paramio,caldb4'\n%s" % e)
        except:
            raise ImportError("fail to 'import pixlib,paramio,caldb4'\n")
                        

    def test_failOrder1(self):
        try:
            t2 = __import__("caldb4")
            t1 = __import__("pixlib")
            print("Okay to 'import caldb4,pixlib'") 
        except ImportError as e:
            raise ImportError("fail to 'import caldb4,pixlib'\n%s" % e)
        except OSError as e:
            raise OSError("fail to 'import caldb4,pixlib'\n%s" % e)
        except:
            raise ImportError("fail to 'import caldb4,pixlib'\n") 
        

    def test_failOrder2(self):
        try:
            t2 = __import__("caldb4")
            t3 = __import__("psf")
            print("Okay to 'import caldb4,psf'") 
        except ImportError as e:
            raise ImportError("fail to 'import psf,caldb4'\n%s" % e)
        except OSError as e:
            raise OSError("fail to 'import psf,caldb4'\n%s" % e)
        except:
            raise ImportError("fail to 'import psf,caldb4'\n") 

    def test_failOrder3(self):
        try:
            __import__("pixlib")
            __import__("psf")
            print("Okay to 'import pixlib,psf'") 
        except ImportError as e:
            raise ImportError("fail to 'import pixlib,psf'\n%s" % e)
        except OSError as e:
            raise OSError("fail to 'import pixlib,psf'\n%s" % e)
        except:
            raise ImportError("fail to 'import pixlib,psf'\n") 

    def test_failOrder4(self):
        try:
            t2 = __import__("caldb4")
            t1 = __import__("pixlib")
            t3 = __import__("psf")
            print("Okay to 'import caldb4,pixlib,psf'") 
        except ImportError as e:
            raise ImportError("fail to 'import caldb4,pixlib,psf'\n%s" % e)
        except OSError as e:
            raise OSError("fail to 'import caldb4,pixlib,psf'\n%s" % e)
        except :
            raise ImportError("fail to 'import caldb4,pixlib,psf'\n" )
 
    def test_failOrder5(self):
        try:
            t3 = __import__("psf")
            t2 = __import__("caldb4")
            print("Okay to 'import psf,caldb4'") 
        except ImportError as e:
            raise ImportError("fail to 'import psf,caldb4'\n%s" % e)
        except OSError as e:
            raise OSError("fail to 'import psf,caldb4'\n%s" % e)
        except :
            raise ImportError("fail to 'import psf,caldb4'\n")

   
    def test_namespaceConfilict(self):
        '''test name space confilict'''

        libname='libpix'
        LDLIBPATH='ASCDS_INSTALL'

        # create a lib file in a temp dir
        tmpdir='/tmp/tmplib%s' %os.getpid()
        os.mkdir(tmpdir,0o755)
        libfile='%s/%s' % (tmpdir,libname)
 
        if sys.platform[:3] in ('dar', 'os2'): # Mac
            libfile='%s/%s.dylib' % (tmpdir,libname)
        else:                                  # assume UNIX-like
            libfile='%s/%s.so' % (tmpdir,libname)

        # preserve 'ASCDS_INSTALL' values
        curldlib =os.environ[LDLIBPATH]
        curpypath=os.environ["PYTHONPATH"]

        # case 1: expected fail
        #
        # set 'ASCDS_INSTALL with the only tempdir 
        os.environ[LDLIBPATH]='%s' % (tmpdir)
        os.environ["PYTHONPATH"]='%s' % (tmpdir)
    




# -----------------------------------------------------------------------------------------
# Reference on __import__  vs sys.modules
#
# 5.3.1. The module cache

# The first place checked during import search is sys.modules. This mapping serves as 
# a cache of all modules that have been previously imported, including the intermediate paths. 
# So if foo.bar.baz was previously imported, sys.modules will contain entries for foo, foo.bar, 
# and foo.bar.baz. Each key will have as its value the corresponding module object.

# During import, the module name is looked up in sys.modules and if                   <-----
# present, the associated value is the module satisfying the import, and
# the process completes. 
# However, if the value is None, then a ModuleNotFoundError is raised.                <-----
# If the module name is missing, Python will continue searching for the module.

# sys.modules is writable. Deleting a key may not destroy the associated              <-----
# module (as other modules may hold references to it), but it will 
# invalidate the cache entry for the named module, causing Python to search 
# anew for the named module upon its next import. 
# The key can also be assigned to None, forcing the next import of the module to result in a ModuleNotFoundError.
#
# ----------------------------------------------------------------------------------------------------


        # clean up the pixlib module from the system if any
        try: 
            # the "del" lines may not be necessary, but if kept, 
            # the order of "del" followed by "None" must be.
            # the updates of the addtion of 
            #  sys.modules["pixlib"]       =None
            #  sys.modules["pixlib.pixlib"]=None
            #
            # this update is only for osx-Sieera platform
            #

            del sys.modules["pixlib"]
            del sys.modules["pixlib.pixlib"] #must delete this otherwise not clean out enough
            sys.modules["pixlib"]       =None
            sys.modules["pixlib.pixlib"]=None
        except:
            pass

        # try to import pixlib module and also try to test the module attribute, 
        try:
            __import__( "pixlib")
            print("Success to read \"%s/%s.so|dylib\"" % ('/tmp/tmplib<pid>', libname)) 
        except:
            print("Fail to read \"%s/%s.so|dylib\"" % ('/tmp/tmplib<pid>', libname)) 

        # case 2: expected success
        # set back 'ASCDS_INSTALL' with the preserved value 
        os.environ[LDLIBPATH]='%s' % (curldlib)
        os.environ["PYTHONPATH"]='%s' % (curpypath)

         # clean up the pixlib module from the system if any
        try: 
            del sys.modules["pixlib"]
            del sys.modules["pixlib.pixlib"] #must delete this otherwise not clean out enough
        except:
            pass
        
        try:
            __import__("pixlib")
            print("Success to read \"%s/lib/%s.so|dylib\" ." % (LDLIBPATH,libname))
        except:
            print("Fail to read \"%s/lib/%s.so|dylib\" ." % (LDLIBPATH,libname))


        os.rmdir(tmpdir)

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