Skip to content

None and perhaps bool type should not return type hints when used as defaults. #58

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Jun 1, 2020
Merged
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
10 changes: 6 additions & 4 deletions atest/DynamicTypesAnnotationsLibrary.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ def keyword_with_webdriver(self, arg: CustomObject):
return arg

@keyword
def keyword_default_and_annotation(self: 'DynamicTypesAnnotationsLibrary', arg1: int, arg2=False) -> str:
def keyword_default_and_annotation(self: 'DynamicTypesAnnotationsLibrary', arg1: int, arg2: Union[bool, str] = False) -> str:
return '%s: %s, %s: %s' % (arg1, type(arg1), arg2, type(arg2))

@keyword(types={'arg': str})
Expand All @@ -67,7 +67,7 @@ def keyword_robot_types_disabled_and_annotations(self, arg: int):
return '%s: %s' % (arg, type(arg))

@keyword(types={'arg1': str})
def keyword_robot_types_and_bool_defaults(self, arg1, arg2=False):
def keyword_robot_types_and_bool_hint(self, arg1, arg2: bool):
return '%s: %s, %s: %s' % (arg1, type(arg1), arg2, type(arg2))

@keyword
Expand All @@ -87,7 +87,9 @@ def keyword_only_arguments_no_vararg(self, *, other):
return f'{other}: {type(other)}'

@keyword
def keyword_only_arguments_many_positional_and_default(self: 'DynamicTypesAnnotationsLibrary', *varargs, one, two, three, four=True, five=None, six=False):
def keyword_only_arguments_many_positional_and_default(self: 'DynamicTypesAnnotationsLibrary', *varargs, one, two,
three, four: Union[int, str] = 1, five=None,
six: Union[bool, str] = False):
return f'{varargs}, {one}, {two}, {three}, {four}, {five}, {six}'

@keyword
Expand All @@ -99,7 +101,7 @@ def keyword_only_arguments_many(self, *varargs, some='value', other=None):
return f'{some}: {type(some)}, {other}: {type(other)}, {varargs}: {type(varargs)}'

@keyword
def keyword_mandatory_and_keyword_only_arguments(self, arg: int, *vararg, some=True):
def keyword_mandatory_and_keyword_only_arguments(self, arg: int, *vararg, some: bool):
return f'{arg}, {vararg}, {some}'

@keyword
Expand Down
11 changes: 3 additions & 8 deletions atest/tests_types.robot
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ Keyword Default Argument As Abject None Default Value

Keyword Default Argument As String None
${return} = DynamicTypesLibrary.Keyword None None
Should Match Regexp ${return} None: <(class|type) 'NoneType'>
Should Match Regexp ${return} None: <(class|type) '(unicode|str|NoneType)'>

Keyword Default As Booleans With Defaults
${return} DynamicTypesLibrary.Keyword Booleans
Expand All @@ -35,23 +35,18 @@ Keyword Annonations And Bool Defaults Using Default
Keyword Annonations And Bool Defaults Defining All Arguments
[Tags] py3
${return} = DynamicTypesAnnotationsLibrary.Keyword Default And Annotation 1 true
Should Match Regexp ${return} 1: <(class|type) 'int'>, True: <(class|type) 'bool'>
Should Match Regexp ${return} 1: <(class|type) 'int'>, true: <(class|type) 'str'>

Keyword Annonations And Bool Defaults Defining All Arguments And With Number
[Tags] py3
${return} = DynamicTypesAnnotationsLibrary.Keyword Default And Annotation ${1} true
Should Match Regexp ${return} 1: <(class|type) 'int'>, True: <(class|type) 'bool'>
Should Match Regexp ${return} 1: <(class|type) 'int'>, true: <(class|type) 'str'>

Keyword Annonations And Robot Types Disbales Argument Conversion
[Tags] py3
${return} = DynamicTypesAnnotationsLibrary.Keyword Robot Types Disabled And Annotations 111
Should Match Regexp ${return} 111: <(class|type) 'str'>

Keyword Annonations And Robot Types Defined
[Tags] py3
${return} = DynamicTypesAnnotationsLibrary.Keyword Robot Types And Bool Defaults tidii 111
Should Match Regexp ${return} tidii: <(class|type) 'str'>, 111: <(class|type) 'str'>

Keyword Annonations And Keyword Only Arguments
[Tags] py3
${return} = DynamicTypesAnnotationsLibrary.Keyword Only Arguments 1 ${1} some=222
Expand Down
5 changes: 4 additions & 1 deletion src/robotlibcore.py
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,10 @@ def get_keyword_types(self, keyword_name):
return types
if not types:
types = self.__get_typing_hints(method)
types = self.__join_defaults_with_types(method, types)
if RF31:
types = self.__join_defaults_with_types(method, types)
else:
types.pop('return', None)
return types

def __get_keyword(self, keyword_name):
Expand Down
80 changes: 60 additions & 20 deletions utest/test_get_keyword_types.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import pytest


from robotlibcore import PY2
from robotlibcore import PY2, RF31

if not PY2:
from typing import List, Union, Dict
Expand Down Expand Up @@ -31,11 +31,18 @@ def test_types_disabled(lib):
assert types is None


def test_keyword_types_and_bool_default(lib):
@pytest.mark.skipif(not RF31, reason='Only for RF3.1')
def test_keyword_types_and_bool_default_rf31(lib):
types = lib.get_keyword_types('keyword_robot_types_and_bool_default')
assert types == {'arg1': str, 'arg2': bool}


@pytest.mark.skipif(RF31, reason='Only for RF3.2+')
def test_keyword_types_and_bool_default_rf32(lib):
types = lib.get_keyword_types('keyword_robot_types_and_bool_default')
assert types == {'arg1': str}


def test_one_keyword_type_defined(lib):
types = lib.get_keyword_types('keyword_with_one_type')
assert types == {'arg1': str}
Expand All @@ -51,12 +58,26 @@ def test_not_keyword(lib):
lib.get_keyword_types('not_keyword')


def test_keyword_booleans(lib):
@pytest.mark.skipif(not RF31, reason='Only for RF3.2+')
def test_keyword_booleans_rf31(lib):
types = lib.get_keyword_types('keyword_booleans')
assert types == {'arg1': bool, 'arg2': bool}


def test_keyword_none(lib):
@pytest.mark.skipif(RF31, reason='Only for RF3.2+')
def test_keyword_booleans_rf32(lib):
types = lib.get_keyword_types('keyword_booleans')
assert types == {}


@pytest.mark.skipif(RF31, reason='Only for RF3.2+')
def test_keyword_none_rf32(lib):
types = lib.get_keyword_types('keyword_none')
assert types == {}


@pytest.mark.skipif(not RF31, reason='Only for RF3.2+')
def test_keyword_none_rf31(lib):
types = lib.get_keyword_types('keyword_none')
assert types == {'arg': type(None)}

Expand All @@ -79,11 +100,6 @@ def test_multiple_types(lib_types):
assert types == {'arg': Union[List, None]}


def test_keyword_with_default_type(lib):
types = lib.get_keyword_types('keyword_default_types')
assert types == {'arg': type(None)}


@pytest.mark.skipif(PY2, reason='Only applicable on Python 3')
def test_keyword_new_type(lib_types):
types = lib_types.get_keyword_types('keyword_new_type')
Expand Down Expand Up @@ -123,7 +139,7 @@ def test_keyword_with_annotation_external_class(lib_types):
@pytest.mark.skipif(PY2, reason='Only applicable on Python 3')
def test_keyword_with_annotation_and_default(lib_types):
types = lib_types.get_keyword_types('keyword_default_and_annotation')
assert types == {'arg1': int, 'arg2': bool}
assert types == {'arg1': int, 'arg2': Union[bool, str]}


@pytest.mark.skipif(PY2, reason='Only applicable on Python 3')
Expand All @@ -140,13 +156,13 @@ def test_keyword_with_robot_types_disbaled_and_annotations(lib_types):

@pytest.mark.skipif(PY2, reason='Only applicable on Python 3')
def test_keyword_with_robot_types_and_bool_annotations(lib_types):
types = lib_types.get_keyword_types('keyword_robot_types_and_bool_defaults')
assert types == {'arg1': str, 'arg2': bool}

types = lib_types.get_keyword_types('keyword_robot_types_and_bool_hint')
assert types == {'arg1': str}

def test_init_args(lib):
types = lib.get_keyword_types('__init__')
assert types == {'arg': bool}
@pytest.mark.skipif(PY2, reason='Only applicable on Python 3')
def test_init_args(lib_types):
types = lib_types.get_keyword_types('__init__')
assert types == {'arg': str}


def test_dummy_magic_method(lib):
Expand Down Expand Up @@ -177,26 +193,50 @@ def test_keyword_only_arguments(lib_types):
assert types == {}


@pytest.mark.skipif(RF31, reason='Only for RF3.2+')
@pytest.mark.skipif(PY2, reason='Only applicable on Python 3')
def test_keyword_only_arguments_many(lib_types):
types = lib_types.get_keyword_types('keyword_only_arguments_many')
assert types == {'other': type(None)}
assert types == {}


@pytest.mark.skipif(not RF31, reason='Only for RF3.1')
@pytest.mark.skipif(PY2, reason='Only applicable on Python 3')
def test_keyword_only_arguments_many(lib_types):
types = lib_types.get_keyword_types('keyword_only_arguments_many')
assert types == {'other': type(None)}


@pytest.mark.skipif(PY2, reason='Only applicable on Python 3')
def test_keyword_mandatory_and_keyword_only_arguments(lib_types):
types = lib_types.get_keyword_types('keyword_mandatory_and_keyword_only_arguments')
assert types == {'arg': int, 'some': bool}


@pytest.mark.skipif(RF31, reason='Only for RF3.2+')
@pytest.mark.skipif(PY2, reason='Only applicable on Python 3')
def test_keyword_only_arguments_many(lib_types):
def test_keyword_only_arguments_many_positional_and_default_rf32(lib_types):
types = lib_types.get_keyword_types('keyword_only_arguments_many_positional_and_default')
assert types == {'four': bool, 'five': type(None), 'six': bool}
assert types == {'four': Union[int, str], 'six': Union[bool, str]}


@pytest.mark.skipif(not RF31, reason='Only for RF3.1')
@pytest.mark.skipif(PY2, reason='Only applicable on Python 3')
def test_keyword_only_arguments_many_positional_and_default_rf31(lib_types):
types = lib_types.get_keyword_types('keyword_only_arguments_many_positional_and_default')
assert types == {'four': Union[int, str], 'five': type(None), 'six': Union[bool, str]}


@pytest.mark.skipif(RF31, reason='Only for RF3.2+')
@pytest.mark.skipif(PY2, reason='Only applicable on Python 3')
def test_keyword_all_args_rf32(lib_types):
types = lib_types.get_keyword_types('keyword_all_args')
assert types == {}


@pytest.mark.skipif(not RF31, reason='Only for RF3.1')
@pytest.mark.skipif(PY2, reason='Only applicable on Python 3')
def test_keyword_all_args(lib_types):
def test_keyword_all_args_rf31(lib_types):
types = lib_types.get_keyword_types('keyword_all_args')
assert types == {'value': bool}

Expand Down