forked from robotframework/robotframework
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdynamicmethods.py
More file actions
152 lines (113 loc) · 4.69 KB
/
dynamicmethods.py
File metadata and controls
152 lines (113 loc) · 4.69 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
# Copyright 2008-2015 Nokia Networks
# Copyright 2016- Robot Framework Foundation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from robot.errors import DataError
from robot.utils import (get_error_message, is_java_method, is_bytes,
is_unicode, py2to3)
from .arguments import JavaArgumentParser, PythonArgumentParser
def no_dynamic_method(*args):
pass
@py2to3
class _DynamicMethod(object):
_underscore_name = NotImplemented
def __init__(self, lib):
self.method = self._get_method(lib)
def _get_method(self, lib):
for name in self._underscore_name, self._camelCaseName:
method = getattr(lib, name, None)
if callable(method):
return method
return no_dynamic_method
@property
def _camelCaseName(self):
tokens = self._underscore_name.split('_')
return ''.join([tokens[0]] + [t.capitalize() for t in tokens[1:]])
@property
def name(self):
return self.method.__name__
def __call__(self, *args):
try:
return self._handle_return_value(self.method(*args))
except:
raise DataError("Calling dynamic method '%s' failed: %s"
% (self.method.__name__, get_error_message()))
def _handle_return_value(self, value):
raise NotImplementedError
def _to_string(self, value):
if is_unicode(value):
return value
if is_bytes(value):
return value.decode('UTF-8')
raise DataError('Return value must be string.')
def _to_list_of_strings(self, value):
try:
return [self._to_string(v) for v in value]
except (TypeError, DataError):
raise DataError('Return value must be list of strings.')
def __nonzero__(self):
return self.method is not no_dynamic_method
class GetKeywordNames(_DynamicMethod):
_underscore_name = 'get_keyword_names'
def _handle_return_value(self, value):
names = self._to_list_of_strings(value or [])
return list(self._remove_duplicates(names))
def _remove_duplicates(self, names):
seen = set()
for name in names:
if name not in seen:
seen.add(name)
yield name
class RunKeyword(_DynamicMethod):
_underscore_name = 'run_keyword'
@property
def supports_kwargs(self):
if is_java_method(self.method):
return self._supports_java_kwargs(self.method)
return self._supports_python_kwargs(self.method)
def _supports_python_kwargs(self, method):
spec = PythonArgumentParser().parse(method)
return len(spec.positional) == 3
def _supports_java_kwargs(self, method):
func = self.method.im_func if hasattr(method, 'im_func') else method
signatures = func.argslist[:func.nargs]
spec = JavaArgumentParser().parse(signatures)
return (self._java_single_signature_kwargs(spec) or
self._java_multi_signature_kwargs(spec))
def _java_single_signature_kwargs(self, spec):
return len(spec.positional) == 1 and spec.varargs and spec.kwargs
def _java_multi_signature_kwargs(self, spec):
return len(spec.positional) == 3 and not (spec.varargs or spec.kwargs)
class GetKeywordDocumentation(_DynamicMethod):
_underscore_name = 'get_keyword_documentation'
def _handle_return_value(self, value):
return self._to_string(value or '')
class GetKeywordArguments(_DynamicMethod):
_underscore_name = 'get_keyword_arguments'
def __init__(self, lib):
_DynamicMethod.__init__(self, lib)
self._supports_kwargs = RunKeyword(lib).supports_kwargs
def _handle_return_value(self, value):
if value is None:
if self._supports_kwargs:
return ['*varargs', '**kwargs']
return ['*varargs']
return self._to_list_of_strings(value)
class GetKeywordTypes(_DynamicMethod):
_underscore_name = 'get_keyword_types'
def _handle_return_value(self, value):
return value
class GetKeywordTags(_DynamicMethod):
_underscore_name = 'get_keyword_tags'
def _handle_return_value(self, value):
return self._to_list_of_strings(value or [])