Revision: 57c50c4902a4
Author:   Janne Härkönen <[email protected]>
Date:     Fri Sep 16 00:41:42 2011
Log:      testlibraries: support intro and init doc in dynamic libraries

Also added unit tests and some simple test libs for the tests.

Update issue 186
http://code.google.com/p/robotframework/source/detail?r=57c50c4902a4

Added:
 /atest/testresources/testlibs/dynlibs.py
Modified:
 /atest/testresources/testlibs/ArgDocDynamicJavaLibrary.class
 /atest/testresources/testlibs/ArgDocDynamicJavaLibrary.java
 /src/robot/running/handlers.py
 /src/robot/running/testlibraries.py
 /utest/running/test_testlibrary.py

=======================================
--- /dev/null
+++ /atest/testresources/testlibs/dynlibs.py    Fri Sep 16 00:41:42 2011
@@ -0,0 +1,41 @@
+class _BaseDynamicLibrary(object):
+
+    def get_keyword_names(self):
+        return []
+
+    def run_keyword(self, name, *args):
+        return None
+
+class StaticDocsLib(_BaseDynamicLibrary):
+    """This is lib intro."""
+    def __init__(self, some=None, args=[]):
+        """Init doc."""
+
+class DynamicDocsLib(_BaseDynamicLibrary):
+    def __init__(self, *args): pass
+
+    def get_keyword_documentation(self, name):
+        if name == '__intro__':
+            return 'Dynamic intro doc.'
+        if name == '__init__':
+            return 'Dynamic init doc.'
+        return ''
+
+class StaticAndDynamicDocsLib(_BaseDynamicLibrary):
+    """This is static doc."""
+    def __init__(self, an_arg=None):
+        """This is static doc."""
+    def get_keyword_documentation(self, name):
+        if name == '__intro__':
+            return 'dynamic override'
+        if name == '__init__':
+            return 'dynamic override'
+        return ''
+
+class FailingDynamicDocLib(_BaseDynamicLibrary):
+    """intro-o-o"""
+    def __init__(self):
+        """initoo-o-o"""
+    def get_keyword_documentation(self, name):
+        raise RuntimeError('This should be ignored')
+
=======================================
--- /atest/testresources/testlibs/ArgDocDynamicJavaLibrary.class Tue May 24 06:01:12 2011 +++ /atest/testresources/testlibs/ArgDocDynamicJavaLibrary.class Fri Sep 16 00:41:42 2011
Binary file, no diff available.
=======================================
--- /atest/testresources/testlibs/ArgDocDynamicJavaLibrary.java Tue May 24 06:01:12 2011 +++ /atest/testresources/testlibs/ArgDocDynamicJavaLibrary.java Fri Sep 16 00:41:42 2011
@@ -1,4 +1,8 @@
 public class ArgDocDynamicJavaLibrary {
+
+    public ArgDocDynamicJavaLibrary() {}
+
+    public ArgDocDynamicJavaLibrary(String name) {}

     public String[] getKeywordNames() {
         return new String[] {"Java No Arg",
@@ -17,6 +21,10 @@
     public String getKeywordDocumentation(String name) {
         if (name.equals("Invalid Java Doc"))
             throw new RuntimeException("Get doc failure");
+        if (name.equals("__intro__"))
+            return "Dynamic Java intro doc.";
+        else if (name.equals("__init__"))
+            return "Dynamic Java init doc.";
         return "Keyword documentation for " + name;
     }

=======================================
--- /src/robot/running/handlers.py      Fri Aug 26 05:59:46 2011
+++ /src/robot/running/handlers.py      Fri Sep 16 00:41:42 2011
@@ -54,11 +54,9 @@
     return _DynamicHandler(library, name, method, doc, argspec)


-def InitHandler(library, method):
-    if method is None:
-        method = lambda: None
+def InitHandler(library, method, doc=''):
Init = _PythonInitHandler if not _is_java_init(method) else _JavaInitHandler
-    return Init(library, '__init__', method)
+    return Init(library, '__init__', method, doc)


 class _BaseHandler(object):
@@ -252,7 +250,7 @@
     def _variable_syntax_in(self, kw_name, context):
         try:
             resolved = context.namespace.variables.replace_string(kw_name)
-            #Variable can contain value, but it might be wrong,
+            #Variable can contain value, but it might be wrong,
             #therefore it cannot be returned
             return resolved != kw_name
         except DataError:
@@ -261,7 +259,7 @@
 class _XTimesHandler(_RunKeywordHandler):

     def __init__(self, handler, name):
-        _RunKeywordHandler.__init__(self, handler.library, handler.name,
+        _RunKeywordHandler.__init__(self, handler.library, handler.name,
                                     handler._handler_method)
         self.name = name
self.doc = "*DEPRECATED* Replace X times syntax with 'Repeat Keyword'."
@@ -282,11 +280,19 @@

 class _PythonInitHandler(_PythonHandler):

+    def __init__(self, library, handler_name, handler_method, doc):
+ _PythonHandler.__init__(self, library, handler_name, handler_method)
+        self.doc = doc or self.doc
+
     def _parse_arguments(self, handler_method):
         return PythonInitArguments(handler_method, self.library.name)


 class _JavaInitHandler(_BaseHandler):

+    def __init__(self, library, handler_name, handler_method, doc):
+        _BaseHandler.__init__(self, library, handler_name, handler_method)
+        self.doc = doc or ''
+
     def _parse_arguments(self, handler_method):
         return JavaInitArguments(handler_method, self.library.name)
=======================================
--- /src/robot/running/testlibraries.py Tue Sep 13 08:23:33 2011
+++ /src/robot/running/testlibraries.py Fri Sep 16 00:41:42 2011
@@ -66,8 +66,8 @@
         try:
             return self._method(*args)
         except:
-            raise DataError("Calling dynamic method '%s' failed: %s"
- % (self._method.__name__, utils.get_error_message()))
+            raise DataError("Calling dynamic method '%s' failed: %s" %
+ (self._method.__name__, utils.get_error_message()))

     def __nonzero__(self):
         return self._method is not None
@@ -140,10 +140,11 @@
                 return '<unknown>'

     def _create_init_handler(self, libcode):
-        init_method =  getattr(libcode, '__init__', None)
-        if not self._valid_init(init_method):
-            init_method = None
-        return InitHandler(self, init_method)
+        return InitHandler(self, self._resolve_init_method(libcode))
+
+    def _resolve_init_method(self, libcode):
+        init_method = getattr(libcode, '__init__', None)
+ return init_method if self._valid_init(init_method) else lambda: None

     def _valid_init(self, init_method):
         if inspect.ismethod(init_method):
@@ -305,7 +306,7 @@
         return self._libcode

     def _create_init_handler(self, libcode):
-        return InitHandler(self, None)
+        return InitHandler(self, lambda: None)


 class _HybridLibrary(_BaseTestLibrary):
@@ -322,15 +323,15 @@
     _log_failure = LOGGER.warn

     def __init__(self, libcode, source, name, args, variables=None):
- _BaseTestLibrary.__init__(self, libcode, source, name, args, variables)
         self._get_kw_doc = \
_DynamicMethod(libcode, 'get_keyword_documentation', default='')
         self._get_kw_args = \
             _DynamicMethod(libcode, 'get_keyword_arguments', default=None)
+ _BaseTestLibrary.__init__(self, libcode, source, name, args, variables)

     @property
     def doc(self):
-        return self._get_kw_doc(self.get_instance(), '__intro__')
+        return self._get_special_documentation('__intro__') or self._doc

     def _get_handler_names(self, instance):
         try:
@@ -348,3 +349,13 @@
         doc = self._get_kw_doc(self._libinst, handler_name)
         argspec = self._get_kw_args(self._libinst, handler_name)
return DynamicHandler(self, handler_name, handler_method, doc, argspec)
+
+    def _create_init_handler(self, libcode):
+        return InitHandler(self, self._resolve_init_method(libcode),
+                           self._get_special_documentation('__init__'))
+
+    def _get_special_documentation(self, doc_type):
+        try:
+            return self._get_kw_doc(self.get_instance(), doc_type)
+        except DataError:
+            return ''
=======================================
--- /utest/running/test_testlibrary.py  Fri Jul  1 06:53:26 2011
+++ /utest/running/test_testlibrary.py  Fri Sep 16 00:41:42 2011
@@ -7,10 +7,11 @@
 from robot import utils
 from robot.errors import DataError

-from classes import (NameLibrary, DocLibrary, ArgInfoLibrary, GetattrLibrary,
-                     SynonymLibrary)
+from classes import (NameLibrary, DocLibrary, ArgInfoLibrary,
+                     GetattrLibrary, SynonymLibrary)
 if utils.is_jython:
- import ArgumentTypes, Extended, MultipleArguments, MultipleSignatures, NoHandlers + import ArgumentTypes, Extended, MultipleArguments, MultipleSignatures, \
+            NoHandlers


 # Valid keyword names and arguments for some libraries
@@ -481,6 +482,58 @@
             self._assert_handler_args(handler, minargs, maxargs)


+class TestDynamicLibraryIntroDocumentation(unittest.TestCase):
+
+    def test_doc_from_class_definition(self):
+        self._assert_intro_doc('dynlibs.StaticDocsLib',
+                               'This is lib intro.')
+
+    def test_doc_from_dynamic_method(self):
+        self._assert_intro_doc('dynlibs.DynamicDocsLib',
+                               'Dynamic intro doc.')
+
+    def test_dynamic_doc_overrides_class_doc(self):
+        self._assert_intro_doc('dynlibs.StaticAndDynamicDocsLib',
+                                         'dynamic override')
+
+    def test_failure_in_dynamic_resolving_of_doc_ignored(self):
+        self._assert_intro_doc('dynlibs.FailingDynamicDocLib',
+                                         'intro-o-o')
+
+    def _assert_intro_doc(self, library_name, expected_doc):
+        assert_equals(TestLibrary(library_name).doc, expected_doc)
+
+    if utils.is_jython:
+        def test_dynamic_init_doc_from_java_library(self):
+            self._assert_intro_doc('ArgDocDynamicJavaLibrary',
+                                   'Dynamic Java intro doc.')
+
+
+class TestDynamicLibraryInitDocumentation(unittest.TestCase):
+
+    def test_doc_from_class_init(self):
+        self._assert_init_doc('dynlibs.StaticDocsLib', 'Init doc.')
+
+    def test__doc_from_dynamic_method(self):
+ self._assert_init_doc('dynlibs.DynamicDocsLib', 'Dynamic init doc.')
+
+    def test_dynamic_doc_overrides_method_doc(self):
+        self._assert_init_doc('dynlibs.StaticAndDynamicDocsLib',
+                              'dynamic override')
+
+    def test_failure_in_dynamic_resolving_of_doc_ignored(self):
+        self._assert_init_doc('dynlibs.FailingDynamicDocLib',
+                              'initoo-o-o')
+
+    def _assert_init_doc(self, library_name, expected_doc):
+        assert_equals(TestLibrary(library_name).init.doc, expected_doc)
+
+    if utils.is_jython:
+        def test_dynamic_init_doc_from_java_library(self):
+            self._assert_init_doc('ArgDocDynamicJavaLibrary',
+                                  'Dynamic Java init doc.')
+
+
 class _FakeNamespace:
     def __init__(self):
         self.variables = _FakeVariableScope()

Reply via email to