Skip to content

Commit c1576b3

Browse files
merged [master] with [devel]
2 parents db8b980 + 2829c43 commit c1576b3

File tree

20 files changed

+638
-60
lines changed

20 files changed

+638
-60
lines changed

.travis.yml

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ python:
55
- '2.7'
66
- '3.3'
77
- '3.4'
8+
- '3.5'
89
- pypy
910

1011
install:
@@ -14,10 +15,11 @@ install:
1415
- pip install robotframework-python3
1516
- pip install zetup[commands] --upgrade
1617
- pip install pytest --upgrade
17-
- pip install tox --upgrade
18+
- pip install tox tox-travis --upgrade
1819
- zetup install
1920

2021
script:
2122
- zetup test
22-
- py.test -v test
23+
- py.test -vv robottools
24+
- py.test -vv test
2325
- zetup tox

requirements.robotshell.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
ipython >= 4.0 #import IPython
1+
ipython >= 5.0 #import IPython

robotshell/base.py

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -46,15 +46,3 @@ def cell_magics(self):
4646
"""IPython's dict of registered cell magic functions.
4747
"""
4848
return self.shell.magics_manager.magics['cell']
49-
50-
@property
51-
def in_template(self):
52-
"""IPython's current input prompt template.
53-
"""
54-
return self.shell.prompt_manager.in_template
55-
56-
@in_template.setter
57-
def in_template(self, value):
58-
"""Change IPython's current input prompt template to `value`.
59-
"""
60-
self.shell.prompt_manager.in_template = value

robotshell/shell.py

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,16 @@
3434
import os
3535
from itertools import chain
3636

37+
# for creating custom IPython input prompts
38+
from pygments.token import Token
39+
3740
from robot.errors import DataError
3841

3942
from robottools import TestRobot, TestLibraryInspector
4043
from robottools.testrobot import Keyword
4144

45+
from IPython.terminal.prompts import Prompts
46+
4247
from .base import ShellBase
4348
from .library import TestLibrary
4449
from .result import TestResult
@@ -48,7 +53,7 @@
4853
from .extension import ExtensionMagic
4954

5055

51-
class RobotShell(ShellBase):
56+
class RobotShell(ShellBase, Prompts):
5257
# To support customization in derived Plugins
5358
robot_magic_name = 'Robot'
5459

@@ -57,6 +62,7 @@ class RobotShell(ShellBase):
5762

5863
def __init__(self, shell, default_robot_name='Default'):
5964
ShellBase.__init__(self, shell)
65+
shell.prompts = self
6066
self.label = None
6167

6268
for name, value in os.environ.items():
@@ -116,12 +122,21 @@ def Robot(self, name=None, extname=None):
116122
else:
117123
if extname:
118124
label += '.' + extname
119-
self.in_template = re.sub(
120-
r'^(\[%s\]\n)?' % self.label, '[%s]\n' % label, self.in_template)
121125
self.label = label
122126

123127
return self.robot
124128

129+
def in_prompt_tokens(self, cli=None):
130+
"""Creates custom IPython input prompt with
131+
``[Robot.<name>]`` label above.
132+
133+
* Overrides method from IPython's ``Prompts`` base class.
134+
"""
135+
tokens = super(RobotShell, self).in_prompt_tokens(cli=cli)
136+
if not self.label:
137+
return tokens
138+
return [(Token.Prompt, '[%s]\n' % self.label)] + tokens
139+
125140
def Import(self, libname, args=None, alias=None):
126141
library = self.robot.Import(libname, args, alias=alias)
127142
self.register_robot_keyword_magics(alias or libname, library)

robottools/conftest.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
from importlib import import_module
2+
from inspect import getmembers, ismethod
3+
4+
import robot
5+
6+
import pytest
7+
8+
9+
@pytest.fixture(params=['String', 'Collections'])
10+
def stdlibname(request):
11+
return request.param
12+
13+
14+
@pytest.fixture
15+
def stdlib(request, stdlibname):
16+
try: # Robot < 3.0
17+
libmod = import_module(stdlibname)
18+
except ImportError:
19+
libmod = import_module('robot.libraries.%s' % stdlibname)
20+
libcls = getattr(libmod, stdlibname)
21+
return libcls()
22+
23+
24+
@pytest.fixture
25+
def stdlib_kwfuncnames(request, stdlib):
26+
return [name for name, obj in getmembers(stdlib)
27+
if name[0] != '_' and ismethod(obj)]
28+
29+
30+
@pytest.fixture
31+
def BuiltIn_kwfuncnames(request):
32+
BuiltIn = stdlib(request, 'BuiltIn')
33+
return stdlib_kwfuncnames(request, BuiltIn)

robottools/library/inspector/__init__.py

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,15 +21,17 @@
2121
2222
.. moduleauthor:: Stefan Zimmermann <[email protected]>
2323
"""
24-
from six import with_metaclass
25-
2624
__all__ = [
2725
'ROBOT_LIBRARIES',
2826
'TestLibraryImportError', 'TestLibraryInspector',
2927
# From .multi:
3028
'MultiTestLibraryInspector',
3129
]
3230

31+
from six import with_metaclass
32+
from itertools import chain
33+
34+
import zetup
3335
from moretools import camelize
3436

3537
from path import Path
@@ -55,10 +57,11 @@
5557

5658

5759
class TestLibraryImportError(ImportError):
58-
pass
60+
pass
61+
5962

63+
class TestLibraryInspectorMeta(zetup.meta):
6064

61-
class TestLibraryInspectorMeta(type):
6265
def __getattr__(self, libname):
6366
try:
6467
return TestLibraryInspector(libname)
@@ -70,8 +73,9 @@ def __dir__(self):
7073

7174

7275
class TestLibraryInspector(
73-
with_metaclass(TestLibraryInspectorMeta, object)
76+
with_metaclass(TestLibraryInspectorMeta, zetup.object)
7477
):
78+
7579
def __init__(self, lib, *args):
7680
if isinstance(lib, TestLibraryInspector):
7781
self._library = lib._library
@@ -122,7 +126,14 @@ def __getattr__(self, name):
122126
raise AttributeError(str(e))
123127

124128
def __dir__(self):
125-
return list(map(camelize, self._library.handlers.keys()))
129+
if hasattr(self._library.handlers, 'keys'):
130+
# Robot < 3.0
131+
kwnames = self._library.handlers.keys()
132+
else:
133+
kwnames = (h.name for h in self._library.handlers)
134+
return list(chain(
135+
super(TestLibraryInspector, self).__dir__(),
136+
map(camelize, kwnames)))
126137

127138
def __str__(self):
128139
return self._library.name
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
from robottools import TestLibraryInspector
2+
3+
import pytest
4+
5+
6+
@pytest.fixture
7+
def inspector(request, stdlibname):
8+
return TestLibraryInspector(stdlibname)

robottools/library/inspector/keyword.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727

2828

2929
class KeywordInspector(object):
30+
3031
def __init__(self, handler):
3132
self._handler = handler
3233

@@ -38,6 +39,10 @@ def __doc__(self):
3839
def arguments(self):
3940
return KeywordArgumentsInspector(self._handler.arguments)
4041

42+
def __eq__(self, other):
43+
return isinstance(other, KeywordInspector) and \
44+
self._handler == other._handler
45+
4146
def __getattr__(self, name):
4247
return getattr(self._handler, name)
4348

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
from inspect import getmembers, ismethod
2+
from itertools import chain
3+
from six.moves import zip
4+
5+
from moretools import camelize, isidentifier
6+
7+
from robot.utils import normalize
8+
from robot.errors import DataError
9+
10+
import robottools.library.inspector
11+
from robottools import TestLibraryInspector, TestLibraryImportError
12+
13+
import pytest
14+
15+
16+
class TestInspector(object):
17+
"""Tests for :class:`robottools.TestLibraryInspector`.
18+
"""
19+
def test_class(self):
20+
assert TestLibraryInspector \
21+
is robottools.library.inspector.TestLibraryInspector
22+
assert type(TestLibraryInspector) \
23+
is robottools.library.inspector.TestLibraryInspectorMeta
24+
25+
def test__init__(self, stdlibname, stdlib):
26+
inspector = TestLibraryInspector(stdlibname)
27+
assert type(inspector._library.get_instance()) is type(stdlib)
28+
29+
def test_name(self, inspector, stdlibname):
30+
assert inspector.name == stdlibname
31+
32+
def test__iter__(self, inspector, stdlib, stdlib_kwfuncnames):
33+
kwnames = [camelize(n, joiner=' ') for n in stdlib_kwfuncnames]
34+
for keyword in iter(inspector):
35+
assert isinstance(
36+
keyword, robottools.library.inspector.KeywordInspector)
37+
kwnames.remove(keyword.name)
38+
assert not kwnames
39+
40+
def test__dir__(self, inspector, stdlib):
41+
# filter keyword methods from directly instantiated stdlib
42+
kwfuncnames = [name for name, obj in getmembers(stdlib)
43+
if name[0] != '_' and ismethod(obj)]
44+
# and check if __dir__ contains their camelized names
45+
assert set(dir(inspector)) \
46+
== set(chain(map(camelize, kwfuncnames),
47+
# as well as all other members
48+
super(TestLibraryInspector, inspector).__dir__()))
49+
50+
def test__getattr__(self, inspector, stdlib):
51+
# filter keyword methods from directly instantiated stdlib
52+
kwfuncnames = [name for name, obj in getmembers(stdlib)
53+
if name[0] != '_' and ismethod(obj)]
54+
# and check that __getattr__ works with with keyword method names
55+
# as well as with normalized and camelized keyword names
56+
for name, normalized, camelized in zip(
57+
kwfuncnames, map(normalize, kwfuncnames),
58+
map(camelize, kwfuncnames)
59+
):
60+
keyword, from_normalized, from_camelized = (
61+
getattr(inspector, n)
62+
for n in [name, normalized, camelized])
63+
assert keyword == from_normalized == from_camelized
64+
for keyword in [keyword, from_normalized, from_camelized]:
65+
assert isinstance(
66+
keyword, robottools.library.inspector.KeywordInspector)
67+
assert keyword.name == camelize(name, joiner=' ')
68+
69+
def test__getattr__error(self, inspector):
70+
with pytest.raises(AttributeError) as exc:
71+
getattr(inspector, 'Invalid')
72+
# and check that exception message contains
73+
# RFW's original exception message
74+
with pytest.raises(DataError) as robot_exc:
75+
if hasattr(inspector._library, 'get_handler'):
76+
# robot < 2.9
77+
inspector._library.get_handler('Invalid')
78+
else:
79+
inspector._library.handlers['Invalid']
80+
assert str(robot_exc.value) in str(exc.value)
81+
82+
def test__repr__(self, inspector, stdlibname):
83+
assert repr(inspector) == "[Library] %s" % stdlibname

robottools/remote/__init__.py

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -120,14 +120,12 @@ def _get_keyword(self, name):
120120
except KeyError:
121121
try:
122122
# find in extra RemoteRobot Keywords
123-
keyword = self.keywords[name]
123+
return self.keywords[name]
124124
except KeyError:
125125
return None
126-
else:
127-
# use Keyword's debug mode
128-
# to pass exceptions to RobotRemoteServer base
129-
return keyword.debug
130126
# make sure that self[name] is not a Library
127+
# and return TestRobot Keywords in debug mode
128+
# to get actual exceptions from Keyword functions
131129
return keyword.debug if isinstance(keyword, Keyword) else None
132130

133131
def _arguments_from_kw(self, keyword):

0 commit comments

Comments
 (0)