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()