16 from functools
import partial
23 from robot.utils import (getdoc, get_error_details, Importer, is_dict_like, is_init,
24 is_list_like, normalize, seq2str2, type_name)
26 from .arguments
import EmbeddedArguments, CustomArgumentConverters
27 from .context
import EXECUTION_CONTEXTS
28 from .dynamicmethods
import (GetKeywordArguments, GetKeywordDocumentation,
29 GetKeywordNames, GetKeywordTags, RunKeyword)
30 from .handlers
import Handler, InitHandler, DynamicHandler, EmbeddedArgumentsHandler
31 from .handlerstore
import HandlerStore
32 from .libraryscopes
import LibraryScope
33 from .outputcapture
import OutputCapturer
36 def TestLibrary(name, args=None, variables=None, create_handlers=True, logger=LOGGER):
38 import_name =
'robot.libraries.' + name
42 importer = Importer(
'library', logger=LOGGER)
43 libcode, source = importer.import_class_or_module(import_name,
46 lib = libclass(libcode, name, args
or [], source, logger, variables)
53 if inspect.ismodule(libcode):
57 return _DynamicLibrary
64 get_handler_error_level =
'INFO'
66 def __init__(self, libcode, name, args, source, logger, variables):
67 if os.path.exists(name):
68 name = os.path.splitext(os.path.basename(os.path.abspath(name)))[0]
83 self.positional_args, self.named_args \
84 = self.
initinit.resolve_arguments(args, variables)
96 if self.
_doc_doc
is None:
104 if inspect.ismodule(self.
_libcode_libcode):
107 lines, start_lineno = inspect.getsourcelines(self.
_libcode_libcode)
108 except (TypeError, OSError, IOError):
110 for increment, line
in enumerate(lines):
111 if line.strip().startswith(
'class '):
112 return start_lineno + increment
120 return self.
handlershandlers.get_handlers(name)
139 details_level='INFO'):
140 prefix =
'Error in' if level
in (
'ERROR',
'WARN')
else 'In'
141 self.
loggerlogger.
write(
"%s library '%s': %s" % (prefix, self.
namename, message),
144 self.
loggerlogger.
write(
'Details:\n%s' % details, details_level)
147 return self.
_get_attr_get_attr(libcode,
'ROBOT_LIBRARY_VERSION') \
148 or self.
_get_attr_get_attr(libcode,
'__version__')
150 def _get_attr(self, object, attr, default='', upper=False):
151 value = str(getattr(object, attr, default))
153 value =
normalize(value, ignore=
'_').upper()
157 return self.
_get_attr_get_attr(libcode,
'ROBOT_LIBRARY_DOC_FORMAT', upper=
True)
163 init = getattr(libcode,
'__init__',
None)
164 return init
if is_init(init)
else None
167 converters = getattr(libcode,
'ROBOT_LIBRARY_CONVERTERS',
None)
171 self.
report_errorreport_error(f
'Argument converters must be given as a dictionary, '
172 f
'got {type_name(converters)}.')
174 return CustomArgumentConverters.from_dict(converters, self.
report_errorreport_error)
178 if not self.
scopescope.is_global:
194 return libcode(*self.positional_args, **dict(self.named_args))
201 listeners = getattr(libinst,
'ROBOT_LIBRARY_LISTENER',
None)
202 if listeners
is None:
211 listeners = EXECUTION_CONTEXTS.current.output.library_listeners
213 except DataError
as err:
217 self.
report_errorreport_error(
"Registering listeners failed: %s" % err)
221 listeners = EXECUTION_CONTEXTS.current.output.library_listeners
222 listeners.unregister(self, close)
225 if self.
scopescope.is_global:
230 method = (getattr(listener,
'close',
None)
or
231 getattr(listener,
'_close',
None))
237 name = getattr(listener,
'__name__',
None)
or type_name(listener)
238 self.
report_errorreport_error(
"Calling method '%s' of listener '%s' failed: %s"
239 % (method.__name__, name, message), details)
246 raise DataError(
"Getting keyword names from library '%s' failed: %s"
247 % (self.
namename, message), details)
254 self.
handlershandlers.add(handler, embedded)
255 except DataError
as err:
258 self.
loggerlogger.
debug(
"Created keyword '%s'" % handler.name)
261 def has_robot_name(name):
266 return hasattr(handler,
'robot_name')
268 auto_keywords = getattr(libcode,
'ROBOT_AUTO_KEYWORDS',
True)
270 predicate =
lambda name: name[:1] !=
'_' or has_robot_name(name)
272 predicate = has_robot_name
273 return [name
for name
in dir(libcode)
if predicate(name)]
278 except DataError
as err:
284 "Adding keyword '%s' failed: %s" % (name, error.message),
287 details_level=
'DEBUG'
292 method = getattr(libcode, name)
295 raise DataError(f
'Getting handler method failed: {message}', details)
301 if not (inspect.isroutine(method)
or isinstance(method, partial)):
302 raise DataError(
'Not a method or function.')
303 if getattr(method,
'robot_not_keyword',
False):
304 raise DataError(
'Not exposed as a keyword.')
310 except DataError
as err:
315 except DataError
as err:
320 return Handler(self, handler_name, handler_method)
323 embedded = EmbeddedArguments.from_name(handler.name)
327 return handler,
False
330 if not (arguments.minargs <= len(embedded.args) <= arguments.maxargs):
331 raise DataError(
'Embedded argument count does not match number of '
332 'accepted arguments.')
336 if self.positional_args
or self.named_args:
337 args = self.positional_args + [
'%s=%s' % item
for item
in self.named_args]
338 args_text =
'arguments %s' %
seq2str2(args)
340 args_text =
'no arguments'
341 raise DataError(
"Initializing library '%s' with %s failed: %s\n%s"
342 % (self.
namename, args_text, msg, details))
349 for item
in (libinst,) + inspect.getmro(libinst.__class__):
352 if hasattr(item,
'__dict__')
and name
in item.__dict__:
354 return getattr(libinst, name)
355 raise DataError(
'No non-implicit implementation found.')
361 method = _BaseTestLibrary._get_handler_method(self, libcode, name)
362 if hasattr(libcode,
'__all__')
and name
not in libcode.__all__:
363 raise DataError(
'Not exposed as a keyword.')
378 get_handler_error_level =
'ERROR'
385 get_handler_error_level =
'ERROR'
387 def __init__(self, libcode, name, args, source, logger, variables=None):
388 _BaseTestLibrary.__init__(self, libcode, name, args, source, logger,
397 _BaseTestLibrary.doc.fget(self))
425 docgetter =
lambda: self.
_get_kw_doc_get_kw_doc(
'__init__')
def _get_version(self, libcode)
def reset_instance(self, instance=None)
def _get_handler_names(self, libcode)
def _get_doc_format(self, libcode)
def _get_converters(self, libcode)
def _raise_creating_instance_failed(self)
def _get_instance(self, libcode)
def create_handlers(self)
def handlers_for(self, name)
def close_global_listeners(self)
string get_handler_error_level
def _create_init_handler(self, libcode)
def _get_possible_embedded_args_handler(self, handler)
def report_error(self, message, details=None, level='ERROR', details_level='INFO')
def _validate_embedded_count(self, embedded, arguments)
def _create_handlers(self, libcode)
def _resolve_init_method(self, libcode)
def get_instance(self, create=True)
def register_listeners(self)
def _get_attr(self, object, attr, default='', upper=False)
def get_listeners(self, libinst=None)
def _close_listener(self, listener)
def __init__(self, libcode, name, args, source, logger, variables)
def _try_to_get_handler_method(self, libcode, name)
def _validate_handler_method(self, method)
def unregister_listeners(self, close=False)
def _try_to_create_handler(self, name, method)
def _get_handler_method(self, libcode, name)
def _adding_keyword_failed(self, name, error, level='ERROR')
def _create_handler(self, handler_name, handler_method)
def _get_handler_method(self, libinst, name)
def _create_init_handler(self, libcode)
def _get_kw_tags(self, name)
def _get_handler_method(self, instance, name)
def _get_kw_doc(self, name)
def _get_handler_names(self, instance)
def _create_handler(self, name, method)
def _get_kw_args(self, name)
def __init__(self, libcode, name, args, source, logger, variables=None)
def _get_handler_names(self, instance)
def get_instance(self, create=True)
def _create_init_handler(self, libcode)
def _get_handler_method(self, libcode, name)
def debug(msg, html=False)
Writes the message to the log file using the DEBUG level.
def write(msg, level='INFO', html=False)
Writes the message to the log file using the given level.
def InitHandler(library, method=None, docgetter=None)
def Handler(library, name, method)
def DynamicHandler(library, name, method, doc, argspec, tags=None)
def LibraryScope(libcode, library)
def _get_lib_class(libcode)
def TestLibrary(name, args=None, variables=None, create_handlers=True, logger=LOGGER)
def get_error_details(full_traceback=True, exclude_robot_traces=EXCLUDE_ROBOT_TRACES)
Returns error message and details of the last occurred exception.
def seq2str2(sequence)
Returns sequence in format [ item 1 | item 2 | ...
def normalize(string, ignore=(), caseless=True, spaceless=True)
Normalizes given string according to given spec.
def type_name(item, capitalize=False)
Return "non-technical" type name for objects and types.