Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 9 additions & 5 deletions atest/robot/test_libraries/library_decorator.robot
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ Library decorator with arguments disables automatic keyword discovery by default
Library decorator can enable automatic keyword discovery
Check Test Case ${TESTNAME}

Library decorator can signal possible absence of keywords
Check Test Case ${TESTNAME}

When importing a module and there is one decorated class, the class is used as a library
Check Test Case ${TESTNAME}

Expand All @@ -29,11 +32,12 @@ Imported decorated classes are not considered to be libraries automatically

Set library info
[Template] Library should have been imported
LibraryDecorator.py scope=TEST keywords=3
LibraryDecoratorWithArgs.py scope=SUITE keywords=1 version=1.2.3 listener=True
LibraryDecoratorWithAutoKeywords.py scope=GLOBAL keywords=2
multiple_library_decorators.Class2 scope=SUITE keywords=1
extend_decorated_library.py scope=TEST keywords=2 version=extended
LibraryDecorator.py scope=TEST keywords=3
LibraryDecoratorWithArgs.py scope=SUITE keywords=1 version=1.2.3 listener=True
LibraryDecoratorWithAutoKeywords.py scope=GLOBAL keywords=2
LibraryDecoratorWithAutoKeywordsNone.py scope=TEST keywords=0 listener=False
multiple_library_decorators.Class2 scope=SUITE keywords=1
extend_decorated_library.py scope=TEST keywords=2 version=extended

*** Keywords ***
Library should have been imported
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
from robot.api.deco import library


@library(auto_keywords=None)
class LibraryDecorator:

def not_keyword_v3(self):
raise RuntimeError("Should not be executed!")
5 changes: 5 additions & 0 deletions atest/testdata/test_libraries/library_decorator.robot
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
Library LibraryDecorator.py
Library LibraryDecoratorWithArgs.py
Library LibraryDecoratorWithAutoKeywords.py
Library LibraryDecoratorWithAutoKeywordsNone.py
Library library_decorator_when_class_and_module_names_do_not_match.py
Library extend_decorated_library.py
Library multiple_library_decorators.Class2
Expand All @@ -27,6 +28,10 @@ Library decorator can enable automatic keyword discovery
Undecorated method is keyword
Decorated method is keyword as well

Library decorator can signal possible absence of keywords
[Documentation] FAIL No keyword with name 'Not keyword v3' found.
Not keyword v3

When importing a module and there is one decorated class, the class is used as a library
Class name does not match module name

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -402,13 +402,18 @@ override possible existing class attributes.

When a class is decorated with the `@library` decorator, it is used as a library
even when a `library import refers only to a module containing it`__. This is done
regardless does the class name match the module name or not.
whether or not the class name matches the module name.

.. note:: The `@library` decorator is new in Robot Framework 3.2,
the `converters` argument is new in Robot Framework 5.0, and
specifying that a class in an imported module should be used as
.. note:: The `@library` decorator is new in Robot Framework 3.2.

The `converters` argument is new in Robot Framework 5.0.

Specifying that a class in an imported module should be used as
a library is new in Robot Framework 7.2.

The `auto_keywords=None` option, to suppress the 'library contains no
keywords' warning, is new in Robot Framework 7.3.

__ `library scope`_
__ `library version`_
__ `Custom argument converters`_
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -827,9 +827,9 @@ That method is always called when the library goes out of its scope.
Listener examples
-----------------

This section contains examples using the listener interface. First examples
illustrate getting notifications during execution and latter examples modify
executed tests and created results.
This section contains examples using the listener interface. The first examples
illustrate how to get notifications during execution. Later examples also
modify executed tests and created results.

Getting information
~~~~~~~~~~~~~~~~~~~
Expand Down
6 changes: 4 additions & 2 deletions src/robot/api/deco.py
Original file line number Diff line number Diff line change
Expand Up @@ -145,15 +145,16 @@ def library(
converters: "dict[type, Converter]|None" = None,
doc_format: "DocFormat|None" = None,
listener: "Any|None" = None,
auto_keywords: bool = False,
auto_keywords: "bool|None" = False,
) -> "L|LibraryDecorator":
"""Class decorator to control keyword discovery and other library settings.

Disables automatic keyword detection by setting class attribute
``ROBOT_AUTO_KEYWORDS = False`` to the decorated library by default. In that
mode only methods decorated explicitly with the :func:`keyword` decorator
become keywords. If that is not desired, automatic keyword discovery can be
enabled by using ``auto_keywords=True``.
enabled by using ``auto_keywords=True``. If the library intentionally contains
no keywords, use ``auto_keywords=None`` to suppress the 'no keywords' warning.

Arguments ``scope``, ``version``, ``converters``, ``doc_format`` and ``listener``
set library's scope, version, converters, documentation format and listener by
Expand Down Expand Up @@ -182,6 +183,7 @@ class LibraryConfiguration:

The ``@library`` decorator is new in Robot Framework 3.2.
The ``converters`` argument is new in Robot Framework 5.0.
The ``auto_keywords=None`` option is new in Robot Framework 7.3.
"""
if isinstance(scope, type):
return library()(scope)
Expand Down
2 changes: 1 addition & 1 deletion src/robot/running/importer.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ def _log_imported_library(self, name, args_str, lib):
f"(version {lib.version or '<unknown>'}, {kind} type, "
f"{lib.scope.name} scope, {len(lib.keywords)} keywords{listener})."
)
if not (lib.keywords or lib.listeners):
if not (lib.keywords or lib.listeners) and lib._attr("ROBOT_AUTO_KEYWORDS") != "None":
LOGGER.warn(f"Imported library '{name}' contains no keywords.")


Expand Down