5 new revisions:

Revision: 7fe5f5ec67a2
Author:   Pekka Klärck
Date:     Mon Jan  2 14:13:08 2012
Log: importing by path: require paths to be absolute. no need to require di...
http://code.google.com/p/robotframework/source/detail?r=7fe5f5ec67a2

Revision: 7bbc0dcb3f41
Author:   Pekka Klärck
Date:     Mon Jan  2 14:42:34 2012
Log: import by path: first verifying path exists generally gives better err...
http://code.google.com/p/robotframework/source/detail?r=7bbc0dcb3f41

Revision: 95ac39daaa95
Author:   Pekka Klärck
Date:     Mon Jan  2 14:56:46 2012
Log: convert paths to variable files and listeners into absolute format alr...
http://code.google.com/p/robotframework/source/detail?r=95ac39daaa95

Revision: 1cf831700b07
Author:   Pekka Klärck
Date:     Mon Jan  2 15:00:08 2012
Log:      test cleanup
http://code.google.com/p/robotframework/source/detail?r=1cf831700b07

Revision: 92fe00c4eaf0
Author:   Pekka Klärck
Date:     Mon Jan  2 15:01:11 2012
Log: namespace: cleanup. partly made possible by enhancements to importer
http://code.google.com/p/robotframework/source/detail?r=92fe00c4eaf0

==============================================================================
Revision: 7fe5f5ec67a2
Author:   Pekka Klärck
Date:     Mon Jan  2 14:13:08 2012
Log: importing by path: require paths to be absolute. no need to require dirs to contain / at the end afterwards.
http://code.google.com/p/robotframework/source/detail?r=7fe5f5ec67a2

Modified:
 /src/robot/utils/importer.py
 /utest/utils/test_importer_util.py

=======================================
--- /src/robot/utils/importer.py        Mon Jan  2 07:04:30 2012
+++ /src/robot/utils/importer.py        Mon Jan  2 14:13:08 2012
@@ -144,10 +144,10 @@


 class ByPathImporter(_Importer):
-    _import_path_endings = ('.py', '.java', '.class', '/', os.sep)
+    _valid_import_extensions = ('.py', '.java', '.class', '')

     def handles(self, path):
- return os.path.exists(path) and path.endswith(self._import_path_endings)
+        return os.path.isabs(path)

     def import_(self, path):
         self._verify_import_path(path)
@@ -155,22 +155,24 @@
         imported = self._get_class_from_module(module) or module
         return self._verify_type(imported), path

+    def _verify_import_path(self, path):
+        if not os.path.isabs(path):
+            raise DataError('Import path must be absolute.')
+        if not os.path.exists(path):
+            raise DataError('File or directory does not exist.')
+        if not os.path.splitext(path)[1] in self._valid_import_extensions:
+            raise DataError('Not a valid file or directory to import.')
+
     def _import_by_path(self, path):
         module_dir, module_name = self._split_path_to_module(path)
-        sys.path.insert(0, module_dir)
         if module_name in sys.modules:
             del sys.modules[module_name]
+        sys.path.insert(0, module_dir)
         try:
             return self._import(module_name)
         finally:
             sys.path.pop(0)

-    def _verify_import_path(self, path):
-        if not os.path.exists(path):
-            raise DataError('File or directory does not exist.')
-        if not path.endswith(self._import_path_endings):
-            raise DataError('Not a valid file or directory to import.')
-
     def _split_path_to_module(self, path):
         module_dir, module_file = os.path.split(abspath(path))
         module_name = os.path.splitext(module_file)[0]
=======================================
--- /utest/utils/test_importer_util.py  Mon Jan  2 07:04:30 2012
+++ /utest/utils/test_importer_util.py  Mon Jan  2 14:13:08 2012
@@ -136,21 +136,31 @@

 class TestInvalidImportPath(unittest.TestCase):

+    def test_non_absolute(self):
+        assert_raises_with_msg(DataError,
+ "Importing 'non.existing.py' failed: Import path must be absolute.",
+            Importer().import_class_or_module_by_path, 'non.existing.py')
+        assert_raises_with_msg(DataError,
+ "Importing file 'nonex.py' failed: Import path must be absolute.",
+            Importer('file').import_class_or_module_by_path, 'nonex.py')
+
     def test_non_existing(self):
+        path = abspath('non-existing.py')
         assert_raises_with_msg(DataError,
- "Importing 'non-existing.py' failed: File or directory does not exist.",
-            Importer().import_class_or_module_by_path, 'non-existing.py')
+ "Importing '%s' failed: File or directory does not exist." % path,
+            Importer().import_class_or_module_by_path, path)
         assert_raises_with_msg(DataError,
- "Importing test file 'non-existing.py' failed: File or directory does not exist.", - Importer('test file').import_class_or_module_by_path, 'non-existing.py') + "Importing test file '%s' failed: File or directory does not exist." % path,
+            Importer('test file').import_class_or_module_by_path, path)

     def test_invalid_format(self):
+        path = join(CURDIR, '..', '..', 'README.txt')
         assert_raises_with_msg(DataError,
- "Importing '%s' failed: Not a valid file or directory to import." % CURDIR,
-            Importer().import_class_or_module_by_path, CURDIR)
+ "Importing '%s' failed: Not a valid file or directory to import." % path,
+            Importer().import_class_or_module_by_path, path)
         assert_raises_with_msg(DataError,
- "Importing xxx '%s' failed: Not a valid file or directory to import." % CURDIR,
-            Importer('xxx').import_class_or_module_by_path, CURDIR)
+ "Importing xxx '%s' failed: Not a valid file or directory to import." % path,
+            Importer('xxx').import_class_or_module_by_path, path)


 class TestImportClassOrModule(unittest.TestCase):

==============================================================================
Revision: 7bbc0dcb3f41
Author:   Pekka Klärck
Date:     Mon Jan  2 14:42:34 2012
Log: import by path: first verifying path exists generally gives better error messages than first checking it is absolute
http://code.google.com/p/robotframework/source/detail?r=7bbc0dcb3f41

Modified:
 /src/robot/utils/importer.py
 /utest/utils/test_importer_util.py

=======================================
--- /src/robot/utils/importer.py        Mon Jan  2 14:13:08 2012
+++ /src/robot/utils/importer.py        Mon Jan  2 14:42:34 2012
@@ -156,10 +156,10 @@
         return self._verify_type(imported), path

     def _verify_import_path(self, path):
-        if not os.path.isabs(path):
-            raise DataError('Import path must be absolute.')
         if not os.path.exists(path):
             raise DataError('File or directory does not exist.')
+        if not os.path.isabs(path):
+            raise DataError('Import path must be absolute.')
         if not os.path.splitext(path)[1] in self._valid_import_extensions:
             raise DataError('Not a valid file or directory to import.')

=======================================
--- /utest/utils/test_importer_util.py  Mon Jan  2 14:13:08 2012
+++ /utest/utils/test_importer_util.py  Mon Jan  2 14:42:34 2012
@@ -136,23 +136,25 @@

 class TestInvalidImportPath(unittest.TestCase):

-    def test_non_absolute(self):
-        assert_raises_with_msg(DataError,
- "Importing 'non.existing.py' failed: Import path must be absolute.",
-            Importer().import_class_or_module_by_path, 'non.existing.py')
-        assert_raises_with_msg(DataError,
- "Importing file 'nonex.py' failed: Import path must be absolute.",
-            Importer('file').import_class_or_module_by_path, 'nonex.py')
-
     def test_non_existing(self):
-        path = abspath('non-existing.py')
+        path = 'non-existing.py'
         assert_raises_with_msg(DataError,
"Importing '%s' failed: File or directory does not exist." % path,
             Importer().import_class_or_module_by_path, path)
+        path = abspath(path)
         assert_raises_with_msg(DataError,
"Importing test file '%s' failed: File or directory does not exist." % path,
             Importer('test file').import_class_or_module_by_path, path)

+    def test_non_absolute(self):
+        path = os.listdir('.')[0]
+        assert_raises_with_msg(DataError,
+            "Importing '%s' failed: Import path must be absolute." % path,
+            Importer().import_class_or_module_by_path, path)
+        assert_raises_with_msg(DataError,
+ "Importing file '%s' failed: Import path must be absolute." % path,
+            Importer('file').import_class_or_module_by_path, path)
+
     def test_invalid_format(self):
         path = join(CURDIR, '..', '..', 'README.txt')
         assert_raises_with_msg(DataError,

==============================================================================
Revision: 95ac39daaa95
Author:   Pekka Klärck
Date:     Mon Jan  2 14:56:46 2012
Log: convert paths to variable files and listeners into absolute format already in settings - this is required because nowadays imports by path must use absolute paths
http://code.google.com/p/robotframework/source/detail?r=95ac39daaa95

Modified:
 /src/robot/conf/settings.py
 /utest/conf/test_settings.py

=======================================
--- /src/robot/conf/settings.py Tue Dec 13 15:10:56 2011
+++ /src/robot/conf/settings.py Mon Jan  2 14:56:46 2012
@@ -95,7 +95,7 @@
         if name in ['SuiteStatLevel', 'MonitorWidth']:
return self._convert_to_positive_integer_or_default(name, value)
         if name in ['Listeners', 'VariableFiles']:
-            return [self._split_args_from_name(item) for item in value]
+ return [self._split_args_from_name_or_path(item) for item in value]
         if name == 'ReportBackground':
             return self._process_report_background(value)
         if name == 'TagStatCombine':
@@ -215,14 +215,17 @@
     def _get_default_value(self, name):
         return self._cli_opts[name][1]

-    def _split_args_from_name(self, name):
+    def _split_args_from_name_or_path(self, name):
         if ':' not in name or os.path.exists(name):
-            return name, []
-        args = name.split(':')
-        name = args.pop(0)
-        # Handle absolute Windows paths with arguments
-        if len(name) == 1 and args[0].startswith(('/', '\\')):
-            name = name + ':' + args.pop(0)
+            args = []
+        else:
+            args = name.split(':')
+            name = args.pop(0)
+            # Handle absolute Windows paths with arguments
+            if len(name) == 1 and args[0].startswith(('/', '\\')):
+                name = name + ':' + args.pop(0)
+        if os.path.exists(name):
+            name = os.path.abspath(name)
         return name, args

     def __contains__(self, setting):
=======================================
--- /utest/conf/test_settings.py        Wed Oct  5 05:34:12 2011
+++ /utest/conf/test_settings.py        Mon Jan  2 14:56:46 2012
@@ -1,5 +1,6 @@
 import unittest
 import os
+from os.path import abspath

 from robot.conf.settings import _BaseSettings, RobotSettings, RebotSettings
 from robot.utils.asserts import assert_equals, assert_false
@@ -11,10 +12,10 @@
         pass


-class TestSplitArgsFromName(unittest.TestCase):
+class TestSplitArgsFromNameOrPath(unittest.TestCase):

     def setUp(self):
-        self.method = SettingWrapper()._split_args_from_name
+        self.method = SettingWrapper()._split_args_from_name_or_path

     def test_with_no_args(self):
         assert_equals(self.method('name'), ('name', []))
@@ -40,14 +41,23 @@
                       ('D:\\APPS\\listener', ['v1', 'b2', 'z3']))
assert_equals(self.method('C:/varz.py:arg'), ('C:/varz.py', ['arg']))

+    def test_existing_paths_are_made_absolute(self):
+        path = 'robot-framework-unit-test-file-12q3405909qasf'
+        open(path, 'w').close()
+        try:
+            assert_equals(self.method(path), (abspath(path), []))
+ assert_equals(self.method(path+':arg'), (abspath(path), ['arg']))
+        finally:
+            os.remove(path)
+
     def test_existing_path_with_colons(self):
         # Colons aren't allowed in Windows paths (other than in "c:")
         if os.sep == '\\':
             return
         path = 'robot:framework:test:1:2:42'
+        os.mkdir(path)
         try:
-            os.mkdir(path)
-            assert_equals(self.method(path), (path, []))
+            assert_equals(self.method(path), (abspath(path), []))
         finally:
             os.rmdir(path)


==============================================================================
Revision: 1cf831700b07
Author:   Pekka Klärck
Date:     Mon Jan  2 15:00:08 2012
Log:      test cleanup
http://code.google.com/p/robotframework/source/detail?r=1cf831700b07

Modified:
 /atest/robot/variables/commandline_variable_files.txt

=======================================
--- /atest/robot/variables/commandline_variable_files.txt Thu Dec 22 02:31:46 2011 +++ /atest/robot/variables/commandline_variable_files.txt Mon Jan 2 15:00:08 2012
@@ -15,22 +15,34 @@
     Check Test Case  Arguments To Variable Files

 Non-Existing Variable File
- Check Stderr Contains [ ERROR ] Importing variable file 'non_existing.py' failed: File or directory does not exist. + Check Stderr Contains [ ERROR ] Importing variable file '${VF3}' failed: File or directory does not exist. + Check Stderr Contains [ ERROR ] Importing variable file '${VF4}' failed: File or directory does not exist.

 Too Few Arguments To Variable File
- Check Stderr Contains [ ERROR ] Processing variable file '${VARFILE2}' failed: TypeError: get_variables() + Check Stderr Contains [ ERROR ] Processing variable file '${VF2}' failed: TypeError: get_variables()

 Too Many Arguments To Variable File
- Check Stderr Contains [ ERROR ] Processing variable file '${VARFILE2}' with arguments [ too | many | args ] failed: TypeError: get_variables() + Check Stderr Contains [ ERROR ] Processing variable file '${VF2}' with arguments [ too | many | args ] failed: TypeError: get_variables()

 Invalid Variable File
- Check Stderr Contains [ ERROR ] Processing variable file '${VARFILE2}' with arguments [ FAIL ] failed: ZeroDivisionError: + Check Stderr Contains [ ERROR ] Processing variable file '${VF2}' with arguments [ FAIL ] failed: ZeroDivisionError:

 *** Keywords ***
 Run Test Data
-    ${varfile} =  Normalize Path  ${VARFILEDIR}/cli_vars.py
-    ${varfile2} =  Normalize Path  ${VARFILEDIR}/cli_vars_2.py
-    ${varfile3} =  Normalize Path  ${VARFILEDIR}/cli_vars_invalid.py
- Run Tests --variablefile ${varfile} -V ${varfile2}:arg -V ${varfile2}:arg2:given --variablefile non_existing.py --variablefile ${varfile2} -V ${varfile2}:too:many:args -V ${varfile2}:FAIL variables/commandline_variable_files.txt
-    Set Suite Variable  $VARFILE2
-
+    ${vf1} =  Normalize Path  ${VARFILEDIR}/cli_vars.py
+    ${vf2} =  Normalize Path  ${VARFILEDIR}/cli_vars_2.py
+    ${vf3} =  Normalize Path  ${VARFILEDIR}/non_existing.py
+    ${vf4} =  Set Variable  non_absolute_non_existing.py
+    ${varfiles} =  Catenate
+    ...  --variablefile ${vf1}
+    ...  -V ${vf2}:arg
+    ...  -V ${vf2}:arg2:given
+    ...  --variablefile ${vf2}
+    ...  -V ${vf2}:FAIL
+    ...  -V ${vf2}:too:many:args
+    ...  --variablefile ${vf3}
+    ...  --variablefile ${vf4}
+    Run Tests  ${varfiles}  variables/commandline_variable_files.txt
+    Set Suite Variable  $VF2
+    Set Suite Variable  $VF3
+    Set Suite Variable  $VF4

==============================================================================
Revision: 92fe00c4eaf0
Author:   Pekka Klärck
Date:     Mon Jan  2 15:01:11 2012
Log: namespace: cleanup. partly made possible by enhancements to importer
http://code.google.com/p/robotframework/source/detail?r=92fe00c4eaf0

Modified:
 /src/robot/running/namespace.py
 /utest/running/test_namespace.py

=======================================
--- /src/robot/running/namespace.py     Thu Dec 22 02:31:46 2011
+++ /src/robot/running/namespace.py     Mon Jan  2 15:01:11 2012
@@ -17,7 +17,7 @@
 import copy

 from robot import utils
-from robot.errors import FrameworkError, DataError
+from robot.errors import DataError
 from robot.variables import GLOBAL_VARIABLES, is_scalar_var
 from robot.common import UserErrorHandler
 from robot.output import LOGGER
@@ -30,16 +30,17 @@
 from .context import EXECUTION_CONTEXTS


-STDLIB_NAMES = ['BuiltIn', 'Collections', 'Dialogs', 'Easter', 'OperatingSystem',
-                'Remote', 'Reserved', 'Screenshot', 'String', 'Telnet']
+STDLIB_NAMES = set(('BuiltIn', 'Collections', 'Dialogs', 'Easter',
+                    'OperatingSystem', 'Remote', 'Reserved',
+                    'Screenshot', 'String', 'Telnet'))
 IMPORTER = Importer()


 class Namespace:
-    """A database for keywords and variables.
-
-    A new instance of this class is created for each test suite.
-    """
+    _default_libraries = ('BuiltIn', 'Reserved', 'Easter')
+    _deprecated_libraries = {'BuiltIn': 'DeprecatedBuiltIn',
+                             'OperatingSystem': 'DeprecatedOperatingSystem'}
+ _library_import_by_path_endings = ('.py', '.java', '.class', '/', os.sep)

     def __init__(self, suite, parent_vars):
         if suite is not None:
@@ -65,7 +66,7 @@
         return variables

     def _import_default_libraries(self):
-        for name in 'BuiltIn', 'Reserved', 'Easter':
+        for name in self._default_libraries:
             self.import_library(name)

     def _handle_imports(self, import_settings):
@@ -74,17 +75,14 @@
                 if not item.name:
raise DataError('%s setting requires a name' % item.type)
                 self._import(item)
-            except:
-                item.report_invalid_syntax(utils.get_error_message())
+            except DataError, err:
+                item.report_invalid_syntax(unicode(err))

     def _import(self, import_setting):
-        try:
-            action = {'Library': self._import_library,
-                      'Resource': self._import_resource,
- 'Variables': self._import_variables}[import_setting.type]
-            action(import_setting, self.variables.current)
-        except KeyError:
- raise FrameworkError("Invalid import setting: %s" % import_setting)
+        action = {'Library': self._import_library,
+                  'Resource': self._import_resource,
+                  'Variables': self._import_variables}[import_setting.type]
+        action(import_setting, self.variables.current)

     def import_resource(self, name, overwrite=True):
         self._import_resource(Resource(None, name), overwrite=overwrite)
@@ -122,7 +120,7 @@
self._import_library(Library(None, name, args=args, alias=alias), variables)

     def _import_library(self, import_setting, variables):
-        name = self._get_library_name(import_setting, variables)
+        name = self._resolve_name(import_setting, variables)
         lib = IMPORTER.import_library(name, import_setting.args,
                                       import_setting.alias, variables)
         if lib.name in self._testlibs:
@@ -135,66 +133,58 @@
             lib.start_test()
         self._import_deprecated_standard_libs(lib.name)

-    def _get_library_name(self, import_setting, variables):
-        name = self._resolve_name(import_setting, variables)
-        if os.path.exists(name):
-            return name
-        return name.replace(' ', '')
-
     def _resolve_name(self, import_setting, variables):
-        """Resolves variables from the import_setting name
-
- Returns absolute path to file if it exists or resolved import_setting name.
-        """
+        name = import_setting.name
         if variables:
             try:
-                name = variables.replace_string(import_setting.name)
+                name = variables.replace_string(name)
             except DataError, err:
-                self._report_replacing_vars_failed(import_setting, err)
-        else:
-            name = import_setting.name
-        basedir = import_setting.directory or ''
-        return self._get_path(import_setting.type, name, basedir)
-
-    def _report_replacing_vars_failed(self, import_setting, err):
+                self._raise_replacing_vars_failed(import_setting, err)
+ return self._get_path(name, import_setting.directory, import_setting.type)
+
+    def _raise_replacing_vars_failed(self, import_setting, err):
         raise DataError("Replacing variables from setting '%s' failed: %s"
                         % (import_setting.type, unicode(err)))

-    def _resolve_args(self, import_setting, variables):
-        if not variables:
-            return import_setting.args
+    def _get_path(self, name, basedir, type):
+        if type == 'Library' and not self._is_library_by_path(name):
+            return name.replace(' ', '')
         try:
-            return variables.replace_list(import_setting.args)
-        except DataError, err:
-            self._report_replacing_vars_failed(import_setting, err)
-
-    def _get_path(self, setting_name, path, basedir):
- if setting_name == 'Library' and not self._is_library_by_path(path):
-            return path
- path = self._resolve_path(setting_name, path.replace('/', os.sep), basedir)
-        ending = os.sep if path.endswith(os.sep) else ''
-        return utils.abspath(path) + ending
+            return self._resolve_path(name.replace('/', os.sep), basedir)
+        except DataError:
+            self._raise_imported_does_not_exist(type, name)

     def _is_library_by_path(self, path):
- return path.lower().endswith(('.py', '.java', '.class', '/', os.sep))
-
-    def _resolve_path(self, setting_name, path, basedir):
+        return path.lower().endswith(self._library_import_by_path_endings)
+
+    def _resolve_path(self, path, basedir):
         for base in [basedir] + sys.path:
-            if not os.path.isdir(base):
+            if not (base and os.path.isdir(base)):
                 continue
             ret = os.path.join(base, path)
             if os.path.isfile(ret):
                 return ret
if os.path.isdir(ret) and os.path.isfile(os.path.join(ret, '__init__.py')):
                 return ret
-        name = {'Library': 'Test library',
+        raise DataError
+
+    def _raise_imported_does_not_exist(self, type, path):
+        type = {'Library': 'Test library',
                 'Variables': 'Variable file',
-                'Resource': 'Resource file'}[setting_name]
-        raise DataError("%s '%s' does not exist." % (name, path))
+                'Resource': 'Resource file'}[type]
+        raise DataError("%s '%s' does not exist." % (type, path))
+
+    def _resolve_args(self, import_setting, variables):
+        if not variables:
+            return import_setting.args
+        try:
+            return variables.replace_list(import_setting.args)
+        except DataError, err:
+            self._raise_replacing_vars_failed(import_setting, err)

     def _import_deprecated_standard_libs(self, name):
-        if name in ['BuiltIn', 'OperatingSystem']:
-            self.import_library('Deprecated' + name)
+        if name in self._deprecated_libraries:
+            self.import_library(self._deprecated_libraries[name])

     def start_test(self, test):
         self.variables.start_test(test)
@@ -240,9 +230,8 @@
             handler = self._get_handler(name)
             if handler is None:
                 raise DataError("No keyword with name '%s' found." % name)
-        except:
-            error = utils.get_error_message()
-            handler = UserErrorHandler(name, error)
+        except DataError, err:
+            handler = UserErrorHandler(name, unicode(err))
         self._replace_variables_from_user_handlers(handler)
         return handler

=======================================
--- /utest/running/test_namespace.py    Thu Oct 13 15:21:11 2011
+++ /utest/running/test_namespace.py    Mon Jan  2 15:01:11 2012
@@ -11,9 +11,9 @@

     def test_standard_library_names(self):
         module_path = os.path.dirname(libraries.__file__)
- exp_libs = [name for _, name, _ in pkgutil.iter_modules([module_path]) - if name[0].isupper() and not name.startswith('Deprecated')]
-        assert_equals(exp_libs, namespace.STDLIB_NAMES)
+ exp_libs = (name for _, name, _ in pkgutil.iter_modules([module_path]) + if name[0].isupper() and not name.startswith('Deprecated'))
+        assert_equals(set(exp_libs), namespace.STDLIB_NAMES)

 class TestVariableScopes(unittest.TestCase):

Reply via email to