Repository: robotframework/PythonLibCore

Issue:
With decorators containing arguments, argument specifucation is not correctly resolved.
If library is using decorator which takes in arguments, the arguments are not correctly resolved. Example if there is this decorator: 
```
def _my_deco(old_args: Tuple[str, str], new_args: Tuple[str, str]):
    def actual_decorator(method):
        @wraps(method)
        def wrapper(*args, **kwargs):
            for index, old_arg in enumerate(old_args):
                logger.warn(
                    f"{old_arg} has deprecated, use {new_args[index]}",
                )
            return method(*args, **kwargs)

        return wrapper

    return actual_decorator
```
Then then in that vase arguments are not correctly resolved.

Discussion:

Patch:
diff --git a/src/robotlibcore.py b/src/robotlibcore.py
index cb05e02..be90717 100644
--- a/src/robotlibcore.py
+++ b/src/robotlibcore.py
@@ -164,6 +164,8 @@ class KeywordBuilder(object):
 
     @classmethod
     def build(cls, function):
+        if not PY2:
+            function = inspect.unwrap(function)
         return KeywordSpecification(
             argument_specification=cls._get_arguments(function),
             documentation=inspect.getdoc(function) or '',


Test patch:
diff --git a/atest/DynamicTypesAnnotationsLibrary.py b/atest/DynamicTypesAnnotationsLibrary.py
index a53edd2..7a1eb6d 100644
--- a/atest/DynamicTypesAnnotationsLibrary.py
+++ b/atest/DynamicTypesAnnotationsLibrary.py
@@ -1,5 +1,6 @@
 from enum import Enum
-from typing import List, Union, NewType, Optional
+from functools import wraps
+from typing import List, Union, NewType, Optional, Tuple
 
 from robot.api import logger
 
@@ -10,6 +11,21 @@ UserId = NewType('UserId', int)
 penum = Enum("penum", "ok")
 
 
+def _my_deco(old_args: Tuple[str, str], new_args: Tuple[str, str]):
+    def actual_decorator(method):
+        @wraps(method)
+        def wrapper(*args, **kwargs):
+            for index, old_arg in enumerate(old_args):
+                logger.warn(
+                    f"{old_arg} has deprecated, use {new_args[index]}",
+                )
+            return method(*args, **kwargs)
+
+        return wrapper
+
+    return actual_decorator
+
+
 class CustomObject(object):
 
     def __init__(self, x, y):
@@ -126,3 +142,8 @@ class DynamicTypesAnnotationsLibrary(DynamicCore):
         logger.info(f'OK {param}')
         logger.info(param.ok)
         return f'OK {param}'
+
+    @keyword
+    @_my_deco(old_args=("arg1", ), new_args=("arg2", ))
+    def keyword_with_deco_and_signature(self, arg1: bool = False, arg2: bool = False):
+        return f"{arg1}: {type(arg1)}, {arg2}: {type(arg2)}"
diff --git a/utest/test_get_keyword_types.py b/utest/test_get_keyword_types.py
index 0397392..1105813 100644
--- a/utest/test_get_keyword_types.py
+++ b/utest/test_get_keyword_types.py
@@ -239,3 +239,9 @@ def test_keyword_self_and_types(lib_types):
 def test_keyword_self_and_keyword_only_types(lib_types):
     types = lib_types.get_keyword_types('keyword_self_and_keyword_only_types')
     assert types == {'varargs': int, 'other': bool, 'kwargs': int}
+
+
+@pytest.mark.skipif(PY2, reason='Only applicable on Python 3')
+def test_keyword_with_decorator_arguments(lib_types):
+    types = lib_types.get_keyword_types('keyword_with_deco_and_signature')
+    assert types == {'arg1': bool, 'arg2': bool}