Revision: 9921cff8ef7b
Author:   Pekka Klärck
Date:     Thu May 19 13:13:43 2011
Log: Refactored import logic and at the same time fixed problem with importing two libraries with same name using physical path

Update issue 822
Status: Done
The problem is now fixed (or at least the test I created earlier passes).

The code changes were quite a bit larger than absolutely needed, but I wanted
to cleanup the import logic at the same time. After the refactoring libs
specified with a path are imported using the same code that is used for
importing variable files which already had a fix for importing module with
a same name as an earlier imported different module.
http://code.google.com/p/robotframework/source/detail?r=9921cff8ef7b

Modified:
 /atest/robot/test_libraries/library_import_failing.txt
 /atest/robot/test_libraries/library_imports_by_path.txt
 /src/robot/utils/importing.py

=======================================
--- /atest/robot/test_libraries/library_import_failing.txt Thu May 19 12:38:24 2011 +++ /atest/robot/test_libraries/library_import_failing.txt Thu May 19 13:13:43 2011
@@ -7,7 +7,8 @@

 *** Test Cases ***
 Library Import Fails Because Not a Library
- Check Failure From Output 0 Importing test library 'MyInvalidLibFile' failed: ImportError: I'm not really a library! raise ImportError("I'm not really a library!") + ${path} = Normalize Path ${CURDIR}/../../testdata/test_libraries/MyInvalidLibFile.py + Check Failure From Output 0 Importing test library '${path}' failed: ImportError: I'm not really a library! raise ImportError("I'm not really a library!")

 Library Import Fails Because Initialization Fails
Check Failure From Output 2 Creating an instance of the test library 'InitializationFailLibrary' with no arguments failed: Initialization failed! InitializationFailLibrary.py", line 4, in __init__
=======================================
--- /atest/robot/test_libraries/library_imports_by_path.txt Thu May 19 04:27:08 2011 +++ /atest/robot/test_libraries/library_imports_by_path.txt Thu May 19 13:13:43 2011
@@ -39,7 +39,8 @@
     Check Test Case  Importing By Path Having Spaces

 Importing Invalid Python File Fails
- Check Stderr Contains Importing test library 'MyInvalidLibFile' failed: ImportError: I'm not really a library! + ${path} = Normalize Path ${CURDIR}/../../testdata/test_libraries/MyInvalidLibFile.py + Check Stderr Contains Importing test library '${path}' failed: ImportError: I'm not really a library!

 Inporting Dir Library Without Trailing "/" Fails
Check Stderr Contains Importing test library 'MyLibDir' failed: ImportError: No module named MyLibDir
=======================================
--- /src/robot/utils/importing.py       Thu May 19 05:39:25 2011
+++ /src/robot/utils/importing.py       Thu May 19 13:13:43 2011
@@ -36,7 +36,8 @@
     sys.path.insert(0, moddir)
     try:
         module = __import__(modname)
-        if normpath(os.path.dirname(module.__file__)) != normpath(moddir):
+        if hasattr(module, '__file__') and \
+ normpath(os.path.dirname(module.__file__)) != normpath(moddir):
             del sys.modules[modname]
             module = __import__(modname)
         return module
@@ -69,58 +70,50 @@
     the module is also 'MyLibrary' then it is possible to use only
     name 'MyLibrary'.
     """
-    if os.path.exists(name):
-        moddir, name = _split_path_to_module(name)
-        sys.path.insert(0, moddir)
-        pop_sys_path = True
+    if '.' not in name or os.path.exists(name):
+        code, module = _non_dotted_import(name, type_)
     else:
-        pop_sys_path = False
-    try:
-        code, module = _import(name, type_)
-    finally:
-        if pop_sys_path:
-            sys.path.pop(0)
+        code, module = _dotted_import(name, type_)
     source = _get_module_source(module)
     return code, source

-
-def _import(name, type_):
-    modname, classname, fromlist = _get_import_params(name)
+def _non_dotted_import(name, type_):
+    try:
+        if os.path.exists(name):
+            module = _import_module_by_path(name)
+        else:
+            module = __import__(name)
+    except:
+        _raise_import_failed(type_, name)
+    try:
+        code = getattr(module, module.__name__)
+        if not inspect.isclass(code):
+            raise AttributeError
+    except AttributeError:
+        code = module
+    return code, module
+
+def _dotted_import(name, type_):
+    parentname, libname = name.rsplit('.', 1)
     try:
         try:
- # It seems that we get class when importing java class from file system - # or from a default package of a jar file. Otherwise we get a module.
-            imported = __import__(modname, {}, {}, fromlist)
+            module = __import__(parentname, fromlist=[str(libname)])
         except ImportError:
-            # Hack to support standalone Jython:
+            # Hack to support standalone Jython:
             # http://code.google.com/p/robotframework/issues/detail?id=515
             if not sys.platform.startswith('java'):
-                raise
+                raise
             __import__(name)
-            imported = __import__(modname, {}, {}, fromlist)
+            module = __import__(parentname, fromlist=[str(libname)])
     except:
         _raise_import_failed(type_, name)
     try:
-        code = getattr(imported, classname)
+        code = getattr(module, libname)
     except AttributeError:
-        if fromlist:
-            _raise_no_lib_in_module(type_, modname, fromlist[0])
-        code = imported
+        _raise_no_lib_in_module(type_, parentname, libname)
     if not (inspect.ismodule(code) or inspect.isclass(code)):
-        if fromlist:
-            _raise_invalid_type(type_, code)
-        else:
-            code = imported
-    return code, imported
-
-def _get_import_params(name):
-    if '.' not in name:
-        return name, name, []
-    parts = name.split('.')
-    modname = '.'.join(parts[:-1])
-    classname = parts[-1]
-    fromlist = [str(classname)]  # Unicode not generally accepted
-    return modname, classname, fromlist
+        _raise_invalid_type(type_, code)
+    return code, module

 def _get_module_source(module):
     source = getattr(module, '__file__', None)

Reply via email to