8 new revisions:
Revision: a8df3f62edee
Branch: default
Author: Pekka Klärck
Date: Fri Nov 29 10:52:59 2013 UTC
Log: remoteserver test runner: use robot under src, not installed
robot, wh...
http://code.google.com/p/robotframework/source/detail?r=a8df3f62edee
Revision: 64d6f94bffac
Branch: default
Author: Pekka Klärck
Date: Fri Nov 29 10:59:10 2013 UTC
Log: Remote: Cleanup
http://code.google.com/p/robotframework/source/detail?r=64d6f94bffac
Revision: 4952d866ea5c
Branch: default
Author: Pekka Klärck
Date: Fri Nov 29 11:04:24 2013 UTC
Log: whitespace
http://code.google.com/p/robotframework/source/detail?r=4952d866ea5c
Revision: b789f4fff467
Branch: default
Author: Pekka Klärck
Date: Fri Nov 29 11:33:47 2013 UTC
Log: Support **kwargs in remote interface...
http://code.google.com/p/robotframework/source/detail?r=b789f4fff467
Revision: 285ada2433ea
Branch: default
Author: Pekka Klärck
Date: Fri Nov 29 12:29:11 2013 UTC
Log: utils: renamed iterable -> is_list_like, added is_str_like and
is_dict...
http://code.google.com/p/robotframework/source/detail?r=285ada2433ea
Revision: 28d2d99f6d0b
Branch: default
Author: Pekka Klärck
Date: Fri Nov 29 12:52:16 2013 UTC
Log: renamed utest file to match tested file name
http://code.google.com/p/robotframework/source/detail?r=28d2d99f6d0b
Revision: b5cec12fa691
Branch: default
Author: Pekka Klärck
Date: Fri Nov 29 13:01:53 2013 UTC
Log: test data cleanup
http://code.google.com/p/robotframework/source/detail?r=b5cec12fa691
Revision: 8b6bf3ff4728
Branch: default
Author: Pekka Klärck
Date: Fri Nov 29 13:33:49 2013 UTC
Log: Remote: support generic iterables and mappings...
http://code.google.com/p/robotframework/source/detail?r=8b6bf3ff4728
==============================================================================
Revision: a8df3f62edee
Branch: default
Author: Pekka Klärck
Date: Fri Nov 29 10:52:59 2013 UTC
Log: remoteserver test runner: use robot under src, not installed
robot, when running tests
http://code.google.com/p/robotframework/source/detail?r=a8df3f62edee
Modified:
/tools/remoteserver/test/run.py
=======================================
--- /tools/remoteserver/test/run.py Thu May 26 20:30:28 2011 UTC
+++ /tools/remoteserver/test/run.py Fri Nov 29 10:52:59 2013 UTC
@@ -4,7 +4,7 @@
Usage 1: run.py language[:runner] [[options] datasources]
Valid languages are 'python', 'jython' or 'ruby', and runner can
-either by 'pybot' (default) or 'jybot'. By default, all tests under
+either by 'python' (default) or 'jython'. By default, all tests under
'test/data' directory are run, but this can be changed by providing
options, which can be any Robot Framework command line options.
@@ -16,13 +16,14 @@
import xmlrpclib
import time
import os
+from os.path import abspath, dirname, exists, join, normpath
import subprocess
import shutil
import socket
-REMOTEDIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
-OUTPUTDIR = os.path.join(REMOTEDIR, 'test', 'logs')
-if os.path.exists(OUTPUTDIR):
+REMOTEDIR = dirname(dirname(abspath(__file__)))
+OUTPUTDIR = join(REMOTEDIR, 'test', 'logs')
+if exists(OUTPUTDIR):
shutil.rmtree(OUTPUTDIR)
os.mkdir(OUTPUTDIR)
@@ -38,9 +39,9 @@
def _start_library(self, lang):
opts = self._environment_setup(lang)
ext = {'python': 'py', 'jython': 'py', 'ruby': 'rb'}[lang]
- lib = os.path.join(REMOTEDIR, 'test', 'libs', 'examplelib.%s' %
ext)
- stdout = os.path.join(OUTPUTDIR, 'stdout.txt')
- stderr = os.path.join(OUTPUTDIR, 'stderr.txt')
+ lib = join(REMOTEDIR, 'test', 'libs', 'examplelib.%s' % ext)
+ stdout = join(OUTPUTDIR, 'stdout.txt')
+ stderr = join(OUTPUTDIR, 'stderr.txt')
cmd = '%s%s%s 1> %s 2> %s' % (lang, opts, lib, stdout, stderr)
print 'Starting %s remote library with command:\n%s' % (lang, cmd)
subprocess.Popen(cmd, shell=True)
@@ -88,21 +89,22 @@
if ':' in mode:
lang, runner = mode.split(':')
else:
- lang, runner = mode, 'pybot'
+ lang, runner = mode, 'python'
lib = Library(lang)
include = lang if lang != 'jython' else 'python'
- output = os.path.join(OUTPUTDIR, 'output.xml')
- args = [runner, '--log', 'NONE', '--report', 'NONE', '--output',
output,
+ output = join(OUTPUTDIR, 'output.xml')
+ args = [runner,
normpath(join(REMOTEDIR, '..', '..', 'src', 'robot', 'run.py')),
+ '--output', output, '--log', 'NONE', '--report', 'NONE',
'--name', mode, '--include',
include, '--noncritical', 'non-critical']
if len(sys.argv) == 2:
- args.append(os.path.join(REMOTEDIR, 'test', 'atest'))
+ args.append(join(REMOTEDIR, 'test', 'atest'))
else:
args.extend(sys.argv[2:])
print 'Running tests with command:\n%s' % ' '.join(args)
subprocess.call(args)
lib.stop()
print
- checker =
os.path.join(REMOTEDIR, '..', 'statuschecker', 'statuschecker.py')
+ checker = join(REMOTEDIR, '..', 'statuschecker', 'statuschecker.py')
subprocess.call(['python', checker, output])
rc = subprocess.call(['rebot', '--noncritical', 'non-critical',
'--outputdir', OUTPUTDIR, output])
==============================================================================
Revision: 64d6f94bffac
Branch: default
Author: Pekka Klärck
Date: Fri Nov 29 10:59:10 2013 UTC
Log: Remote: Cleanup
http://code.google.com/p/robotframework/source/detail?r=64d6f94bffac
Modified:
/src/robot/libraries/Remote.py
=======================================
--- /src/robot/libraries/Remote.py Thu Jun 6 14:00:44 2013 UTC
+++ /src/robot/libraries/Remote.py Fri Nov 29 10:59:10 2013 UTC
@@ -19,13 +19,14 @@
try:
from xml.parsers.expat import ExpatError
except ImportError: # No expat in IronPython 2.7
- class ExpatError(Exception): pass
+ class ExpatError(Exception):
+ pass
-from robot import utils
from robot.errors import RemoteError
+from robot.utils import unic
-class Remote:
+class Remote(object):
ROBOT_LIBRARY_SCOPE = 'TEST SUITE'
def __init__(self, uri='http://localhost:8270'):
@@ -56,7 +57,7 @@
return ''
def run_keyword(self, name, args):
- args = [self._handle_argument(arg) for arg in args]
+ args = self._handle_argument(args)
result = RemoteResult(self._client.run_keyword(name, args))
sys.stdout.write(result.output)
if result.status != 'PASS':
@@ -76,10 +77,10 @@
def _str(self, item):
if item is None:
return ''
- return utils.unic(item)
+ return unic(item)
-class RemoteResult:
+class RemoteResult(object):
def __init__(self, result):
try:
@@ -92,7 +93,7 @@
raise RuntimeError('Invalid remote result dictionary: %s' %
result)
-class XmlRpcRemoteClient:
+class XmlRpcRemoteClient(object):
def __init__(self, uri):
self._server = xmlrpclib.ServerProxy(uri, encoding='UTF-8')
==============================================================================
Revision: 4952d866ea5c
Branch: default
Author: Pekka Klärck
Date: Fri Nov 29 11:04:24 2013 UTC
Log: whitespace
http://code.google.com/p/robotframework/source/detail?r=4952d866ea5c
Modified:
/tools/remoteserver/test/libs/examplelib.py
=======================================
--- /tools/remoteserver/test/libs/examplelib.py Fri Apr 17 13:08:38 2009 UTC
+++ /tools/remoteserver/test/libs/examplelib.py Fri Nov 29 11:04:24 2013 UTC
@@ -18,7 +18,7 @@
See `Failing`, `Logging`, and `Returning` for other basic keywords.
"""
pass
-
+
def failing(self, message):
"""This keyword fails with provided `message`"""
raise AssertionError(message)
@@ -52,7 +52,7 @@
def log_unicode(self):
print self._unicode
-
+
def logging_and_failing(self):
print '*INFO* This keyword will fail!'
print '*WARN* Run for your lives!!'
@@ -216,16 +216,16 @@
def return_negative_integer(self):
return -1
-
+
def return_float(self):
return 3.14
-
+
def return_negative_float(self):
return -0.5
def return_zero(self):
return 0
-
+
def return_boolean_true(self):
return True
==============================================================================
Revision: b789f4fff467
Branch: default
Author: Pekka Klärck
Date: Fri Nov 29 11:33:47 2013 UTC
Log: Support **kwargs in remote interface
Update issue 1596
Status: Started
Implemented changes to Remote and robotremoteserver. Documentation missing.
http://code.google.com/p/robotframework/source/detail?r=b789f4fff467
Added:
/tools/remoteserver/test/atest/kwargs.txt
Modified:
/src/robot/libraries/Remote.py
/tools/remoteserver/robotremoteserver.py
/tools/remoteserver/test/libs/examplelib.py
=======================================
--- /dev/null
+++ /tools/remoteserver/test/atest/kwargs.txt Fri Nov 29 11:33:47 2013 UTC
@@ -0,0 +1,60 @@
+*** Settings ***
+Default Tags python
+Library Remote localhost:${PORT}
+
+*** Variables ***
+${PORT} 8270
+
+*** Test Cases ***
+No kwargs
+ ${result} = Kwargs
+ Should Be Equal ${result} ${EMPTY}
+
+One kwarg
+ ${result} = Kwargs foo=bar
+ Should Be Equal ${result} foo:bar
+
+Multiple kwargs
+ ${result} = Kwargs a=1 c=3 d=4 b=2
+ Should Be Equal ${result} a:1, b:2, c:3, d:4
+
+Args and kwargs
+ ${result} = Args and kwargs arg
+ Should Be Equal ${result} arg, default2
+ ${result} = Args and kwargs arg foo=bar
+ Should Be Equal ${result} arg, default2, foo:bar
+ ${result} = Args and kwargs a arg2=b c=3 d=4
+ Should Be Equal ${result} a, b, c:3, d:4
+ ${result} = Args and kwargs arg2=b c=3 d=4
+ Should Be Equal ${result} default1, b, c:3, d:4
+
+Varargs and kwargs
+ ${result} = Varargs and kwargs
+ Should Be Equal ${result} ${EMPTY}
+ ${result} = Varargs and kwargs foo=bar
+ Should Be Equal ${result} foo:bar
+ ${result} = Varargs and kwargs arg foo=bar
+ Should Be Equal ${result} arg, foo:bar
+ ${result} = Varargs and kwargs a b c d=4 e=5 f=6
+ Should Be Equal ${result} a, b, c, d:4, e:5, f:6
+
+Args, varargs and kwargs
+ ${result} = Args varargs and kwargs arg
+ Should Be Equal ${result} arg, default2
+ ${result} = Args varargs and kwargs arg foo=bar
+ Should Be Equal ${result} arg, default2, foo:bar
+ ${result} = Args varargs and kwargs arg2=foo foo=bar
+ Should Be Equal ${result} default1, foo, foo:bar
+ ${result} = Args varargs and kwargs a arg2=b c=3
+ Should Be Equal ${result} a, b, c:3
+ ${result} = Args varargs and kwargs a b c d e=5
f=6
+ Should Be Equal ${result} a, b, c, d, e:5, f:6
+
+Non-ASCII kwargs
+ ${result} = Kwargs a=hyvää b=päivää c=\u2603
+ Should Be Equal ${result} a:hyvää, b:päivää, c:\u2603
+
+Non-string kwargs
+ ${list} = Create List 1 ${2}
+ ${result} = Non string kwargs a=${1} b=${NONE} c=${list}
+ Should Be Equal ${result} a:1 (int), b: (str), c:['1', 2] (list)
=======================================
--- /src/robot/libraries/Remote.py Fri Nov 29 10:59:10 2013 UTC
+++ /src/robot/libraries/Remote.py Fri Nov 29 11:33:47 2013 UTC
@@ -56,9 +56,10 @@
except TypeError:
return ''
- def run_keyword(self, name, args):
+ def run_keyword(self, name, args, kwargs):
args = self._handle_argument(args)
- result = RemoteResult(self._client.run_keyword(name, args))
+ kwargs = self._handle_argument(kwargs)
+ result = RemoteResult(self._client.run_keyword(name, args, kwargs))
sys.stdout.write(result.output)
if result.status != 'PASS':
raise RemoteError(result.error, result.traceback)
@@ -118,9 +119,10 @@
except xmlrpclib.Error:
raise TypeError
- def run_keyword(self, name, args):
+ def run_keyword(self, name, args, kwargs):
+ run_keyword_args = [name, args, kwargs] if kwargs else [name, args]
try:
- return self._server.run_keyword(name, args)
+ return self._server.run_keyword(*run_keyword_args)
except xmlrpclib.Error, err:
raise RuntimeError(err.faultString)
except socket.error, (errno, err):
=======================================
--- /tools/remoteserver/robotremoteserver.py Thu Jun 6 14:00:44 2013 UTC
+++ /tools/remoteserver/robotremoteserver.py Fri Nov 29 11:33:47 2013 UTC
@@ -76,12 +76,12 @@
and inspect.isroutine(getattr(self._library, attr))]
return names + ['stop_remote_server']
- def run_keyword(self, name, args):
+ def run_keyword(self, name, args, kwargs=None):
result = {'status': 'PASS', 'return': '', 'output': '',
'error': '', 'traceback': ''}
self._intercept_stdout()
try:
- return_value = self._get_keyword(name)(*args)
+ return_value = self._get_keyword(name)(*args, **(kwargs or {}))
except:
result['status'] = 'FAIL'
result['error'], result['traceback'] =
self._get_error_details()
@@ -97,7 +97,7 @@
return self._arguments_from_kw(kw)
def _arguments_from_kw(self, kw):
- args, varargs, _, defaults = inspect.getargspec(kw)
+ args, varargs, kwargs, defaults = inspect.getargspec(kw)
if inspect.ismethod(kw):
args = args[1:] # drop 'self'
if defaults:
@@ -105,6 +105,8 @@
args += ['%s=%s' % (n, d) for n, d in zip(names, defaults)]
if varargs:
args.append('*%s' % varargs)
+ if kwargs:
+ args.append('**%s' % kwargs)
return args
def get_keyword_documentation(self, name):
=======================================
--- /tools/remoteserver/test/libs/examplelib.py Fri Nov 29 11:04:24 2013 UTC
+++ /tools/remoteserver/test/libs/examplelib.py Fri Nov 29 11:33:47 2013 UTC
@@ -122,6 +122,28 @@
def required_defaults_and_varargs(self, req, default='world',
*varargs):
return ' '.join((req, default) + varargs)
+ def kwargs(self, **kwargs):
+ return self._format_args(**kwargs)
+
+ def args_and_kwargs(self, arg1='default1', arg2='default2', **kwargs):
+ return self._format_args(arg1, arg2, **kwargs)
+
+ def varargs_and_kwargs(self, *varargs, **kwargs):
+ return self._format_args(*varargs, **kwargs)
+
+ def args_varargs_and_kwargs(self, arg1='default1', arg2='default2',
+ *varargs, **kwargs):
+ return self._format_args(arg1, arg2, *varargs, **kwargs)
+
+ def non_string_kwargs(self, **kwargs):
+ kwargs = dict((k, '%s (%s)' % (v, type(v).__name__))
+ for k, v in kwargs.items())
+ return self._format_args(**kwargs)
+
+ def _format_args(self, *args, **kws):
+ args += tuple(':'.join(item) for item in sorted(kws.items()))
+ return ', '.join(args)
+
# Argument types
def string_as_argument(self, arg):
==============================================================================
Revision: 285ada2433ea
Branch: default
Author: Pekka Klärck
Date: Fri Nov 29 12:29:11 2013 UTC
Log: utils: renamed iterable -> is_list_like, added is_str_like and
is_dict_like
http://code.google.com/p/robotframework/source/detail?r=285ada2433ea
Added:
/src/robot/utils/islike.py
/utest/utils/test_like.py
Modified:
/src/robot/utils/__init__.py
/src/robot/utils/misc.py
/src/robot/variables/variables.py
=======================================
--- /dev/null
+++ /src/robot/utils/islike.py Fri Nov 29 12:29:11 2013 UTC
@@ -0,0 +1,39 @@
+# Copyright 2008-2013 Nokia Siemens Networks Oyj
+#
+# 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.
+
+try:
+ from collections import Mapping
+except ImportError: # New in 2.6
+ Mapping = dict
+from UserDict import UserDict
+from UserString import UserString
+
+
+def is_str_like(item):
+ return isinstance(item, (basestring, UserString))
+
+
+def is_list_like(item):
+ if is_str_like(item) or is_dict_like(item):
+ return False
+ try:
+ iter(item)
+ except TypeError:
+ return False
+ else:
+ return True
+
+
+def is_dict_like(item):
+ return isinstance(item, (Mapping, UserDict))
=======================================
--- /dev/null
+++ /utest/utils/test_like.py Fri Nov 29 12:29:11 2013 UTC
@@ -0,0 +1,82 @@
+import unittest
+
+try:
+ from collections import Mapping
+except ImportError:
+ Mapping = dict
+from array import array
+from UserDict import UserDict
+from UserList import UserList
+from UserString import UserString, MutableString
+
+from robot.utils import is_dict_like, is_list_like, is_str_like
+from robot.utils.asserts import assert_equals
+
+
+class MyMapping(Mapping):
+
+ def __getitem__(self, item):
+ return 0
+
+ def __len__(self):
+ return 0
+
+ def __iter__(self):
+ return iter([])
+
+
+def generator():
+ yield 'generated'
+
+
+class TestListlike(unittest.TestCase):
+
+ def test_strings_are_not_list_like(self):
+ for thing in ['str', u'unicode', UserString('user')]:
+ assert_equals(is_list_like(thing), False, thing)
+
+ def test_dict_likes_are_not_list_like(self):
+ for thing in [dict(), UserDict(), MyMapping()]:
+ assert_equals(is_list_like(thing), False, thing)
+
+ def test_other_iterables_are_list_like(self):
+ for thing in [[], (), set(), xrange(1), generator(), array('i'),
UserList()]:
+ assert_equals(is_list_like(thing), True, thing)
+
+ def test_others_are_not_list_like(self):
+ for thing in [1, None, True, object(), object]:
+ assert_equals(is_list_like(thing), False, thing)
+
+ def test_generators_are_not_consumed(self):
+ g = generator()
+ assert_equals(is_list_like(g), True)
+ assert_equals(is_list_like(g), True)
+ assert_equals(list(g), ['generated'])
+ assert_equals(list(g), [])
+ assert_equals(is_list_like(g), True)
+
+
+class TestDictlike(unittest.TestCase):
+
+ def test_dict_likes(self):
+ for thing in [dict(), UserDict(), MyMapping()]:
+ assert_equals(is_dict_like(thing), True, thing)
+
+ def test_others(self):
+ for thing in ['', u'', 1, None, True, object(), object, [], (),
set()]:
+ assert_equals(is_dict_like(thing), False, thing)
+
+
+class TestStringlike(unittest.TestCase):
+
+ def test_string_likes(self):
+ for thing in ['', 'a', u'\xe4', UserString('us'),
MutableString('ms')]:
+ assert_equals(is_str_like(thing), True, thing)
+
+ def test_others(self):
+ for thing in [1, None, True, object(), object, [], (), {}]:
+ assert_equals(is_str_like(thing), False, thing)
+
+
+if __name__ == "__main__":
+ unittest.main()
=======================================
--- /src/robot/utils/__init__.py Thu Nov 28 13:25:17 2013 UTC
+++ /src/robot/utils/__init__.py Fri Nov 29 12:29:11 2013 UTC
@@ -45,8 +45,9 @@
from .markuputils import html_format, html_escape, xml_escape,
attribute_escape
from .markupwriters import HtmlWriter, XmlWriter, NullMarkupWriter
from .importer import Importer
+from .islike import is_dict_like, is_list_like, is_str_like
from .match import eq, Matcher, MultiMatcher
-from .misc import (isatty, getdoc, iterable, plural_or_not, printable_name,
+from .misc import (isatty, getdoc, plural_or_not, printable_name,
seq2str, seq2str2)
from .normalizing import lower, normalize, NormalizedDict
from .robotenv import get_env_var, set_env_var, del_env_var, get_env_vars
=======================================
--- /src/robot/utils/misc.py Thu Nov 28 13:25:17 2013 UTC
+++ /src/robot/utils/misc.py Fri Nov 29 12:29:11 2013 UTC
@@ -105,17 +105,6 @@
return unic(doc)
-def iterable(item):
- if isinstance(item, basestring):
- return False
- try:
- iter(item)
- except TypeError:
- return False
- else:
- return True
-
-
# On IronPython sys.stdxxx.isatty() always returns True
if sys.platform != 'cli':
=======================================
--- /src/robot/variables/variables.py Thu Nov 28 13:25:17 2013 UTC
+++ /src/robot/variables/variables.py Fri Nov 29 12:29:11 2013 UTC
@@ -126,7 +126,7 @@
value = self._find_variable(name)
except KeyError:
value = self._get_extended_var(name)
- if not utils.iterable(value):
+ if not utils.is_list_like(value):
raise DataError("Using scalar variable '%s' as list
variable '@%s' "
"requires its value to be list or list-like."
% (name, name[1:]))
==============================================================================
Revision: 28d2d99f6d0b
Branch: default
Author: Pekka Klärck
Date: Fri Nov 29 12:52:16 2013 UTC
Log: renamed utest file to match tested file name
http://code.google.com/p/robotframework/source/detail?r=28d2d99f6d0b
Added:
/utest/utils/test_islike.py
Deleted:
/utest/utils/test_like.py
=======================================
--- /dev/null
+++ /utest/utils/test_islike.py Fri Nov 29 12:52:16 2013 UTC
@@ -0,0 +1,82 @@
+import unittest
+
+try:
+ from collections import Mapping
+except ImportError:
+ Mapping = dict
+from array import array
+from UserDict import UserDict
+from UserList import UserList
+from UserString import UserString, MutableString
+
+from robot.utils import is_dict_like, is_list_like, is_str_like
+from robot.utils.asserts import assert_equals
+
+
+class MyMapping(Mapping):
+
+ def __getitem__(self, item):
+ return 0
+
+ def __len__(self):
+ return 0
+
+ def __iter__(self):
+ return iter([])
+
+
+def generator():
+ yield 'generated'
+
+
+class TestListlike(unittest.TestCase):
+
+ def test_strings_are_not_list_like(self):
+ for thing in ['str', u'unicode', UserString('user')]:
+ assert_equals(is_list_like(thing), False, thing)
+
+ def test_dict_likes_are_not_list_like(self):
+ for thing in [dict(), UserDict(), MyMapping()]:
+ assert_equals(is_list_like(thing), False, thing)
+
+ def test_other_iterables_are_list_like(self):
+ for thing in [[], (), set(), xrange(1), generator(), array('i'),
UserList()]:
+ assert_equals(is_list_like(thing), True, thing)
+
+ def test_others_are_not_list_like(self):
+ for thing in [1, None, True, object(), object]:
+ assert_equals(is_list_like(thing), False, thing)
+
+ def test_generators_are_not_consumed(self):
+ g = generator()
+ assert_equals(is_list_like(g), True)
+ assert_equals(is_list_like(g), True)
+ assert_equals(list(g), ['generated'])
+ assert_equals(list(g), [])
+ assert_equals(is_list_like(g), True)
+
+
+class TestDictlike(unittest.TestCase):
+
+ def test_dict_likes(self):
+ for thing in [dict(), UserDict(), MyMapping()]:
+ assert_equals(is_dict_like(thing), True, thing)
+
+ def test_others(self):
+ for thing in ['', u'', 1, None, True, object(), object, [], (),
set()]:
+ assert_equals(is_dict_like(thing), False, thing)
+
+
+class TestStringlike(unittest.TestCase):
+
+ def test_string_likes(self):
+ for thing in ['', 'a', u'\xe4', UserString('us'),
MutableString('ms')]:
+ assert_equals(is_str_like(thing), True, thing)
+
+ def test_others(self):
+ for thing in [1, None, True, object(), object, [], (), {}]:
+ assert_equals(is_str_like(thing), False, thing)
+
+
+if __name__ == "__main__":
+ unittest.main()
=======================================
--- /utest/utils/test_like.py Fri Nov 29 12:29:11 2013 UTC
+++ /dev/null
@@ -1,82 +0,0 @@
-import unittest
-
-try:
- from collections import Mapping
-except ImportError:
- Mapping = dict
-from array import array
-from UserDict import UserDict
-from UserList import UserList
-from UserString import UserString, MutableString
-
-from robot.utils import is_dict_like, is_list_like, is_str_like
-from robot.utils.asserts import assert_equals
-
-
-class MyMapping(Mapping):
-
- def __getitem__(self, item):
- return 0
-
- def __len__(self):
- return 0
-
- def __iter__(self):
- return iter([])
-
-
-def generator():
- yield 'generated'
-
-
-class TestListlike(unittest.TestCase):
-
- def test_strings_are_not_list_like(self):
- for thing in ['str', u'unicode', UserString('user')]:
- assert_equals(is_list_like(thing), False, thing)
-
- def test_dict_likes_are_not_list_like(self):
- for thing in [dict(), UserDict(), MyMapping()]:
- assert_equals(is_list_like(thing), False, thing)
-
- def test_other_iterables_are_list_like(self):
- for thing in [[], (), set(), xrange(1), generator(), array('i'),
UserList()]:
- assert_equals(is_list_like(thing), True, thing)
-
- def test_others_are_not_list_like(self):
- for thing in [1, None, True, object(), object]:
- assert_equals(is_list_like(thing), False, thing)
-
- def test_generators_are_not_consumed(self):
- g = generator()
- assert_equals(is_list_like(g), True)
- assert_equals(is_list_like(g), True)
- assert_equals(list(g), ['generated'])
- assert_equals(list(g), [])
- assert_equals(is_list_like(g), True)
-
-
-class TestDictlike(unittest.TestCase):
-
- def test_dict_likes(self):
- for thing in [dict(), UserDict(), MyMapping()]:
- assert_equals(is_dict_like(thing), True, thing)
-
- def test_others(self):
- for thing in ['', u'', 1, None, True, object(), object, [], (),
set()]:
- assert_equals(is_dict_like(thing), False, thing)
-
-
-class TestStringlike(unittest.TestCase):
-
- def test_string_likes(self):
- for thing in ['', 'a', u'\xe4', UserString('us'),
MutableString('ms')]:
- assert_equals(is_str_like(thing), True, thing)
-
- def test_others(self):
- for thing in [1, None, True, object(), object, [], (), {}]:
- assert_equals(is_str_like(thing), False, thing)
-
-
-if __name__ == "__main__":
- unittest.main()
==============================================================================
Revision: b5cec12fa691
Branch: default
Author: Pekka Klärck
Date: Fri Nov 29 13:01:53 2013 UTC
Log: test data cleanup
http://code.google.com/p/robotframework/source/detail?r=b5cec12fa691
Modified:
/tools/remoteserver/test/atest/arguments.py
=======================================
--- /tools/remoteserver/test/atest/arguments.py Fri Apr 17 13:08:38 2009 UTC
+++ /tools/remoteserver/test/atest/arguments.py Fri Nov 29 13:01:53 2013 UTC
@@ -1,16 +1,18 @@
-# Can be used in the test data like ${MyObject()} or ${MyObject(1)}
class MyObject:
- def __init__(self, index=''):
+
+ def __init__(self, index=0):
self.index = index
+
def __str__(self):
- return '<MyObject%s>' % self.index
+ return '<MyObject%s>' % (self.index or '')
+
UNICODE = (u'Hyv\u00E4\u00E4 y\u00F6t\u00E4. '
u'\u0421\u043F\u0430\u0441\u0438\u0431\u043E!')
LIST_WITH_OBJECTS = [MyObject(1), MyObject(2)]
-NESTED_LIST = [ [True, False], [[1, None, MyObject(), {}]] ]
-NESTED_TUPLE = ( (True, False), [(1, None, MyObject(), {})] )
+NESTED_LIST = [[True, False], [[1, None, MyObject(), {}]]]
+NESTED_TUPLE = ((True, False), [(1, None, MyObject(), {})])
DICT_WITH_OBJECTS = {'As value': MyObject(1), MyObject(2): 'As key'}
-NESTED_DICT = { 1: {None: False},
- 2: {'A': {'n': None},
- 'B': {'o': MyObject(), 'e': {}}} }
+NESTED_DICT = {1: {None: False},
+ 2: {'A': {'n': None},
+ 'B': {'o': MyObject(), 'e': {}}}}
==============================================================================
Revision: 8b6bf3ff4728
Branch: default
Author: Pekka Klärck
Date: Fri Nov 29 13:33:49 2013 UTC
Log: Remote: support generic iterables and mappings
Update issue 1597
Status: Done
Fixed on both sides.
robotremoteserver.py doesn't handle UserDicts or UserStrings correctly, but
I seriously doubt anyone uses them in a test library. If they do, they can
easily convert them to normal strings before returning them.
http://code.google.com/p/robotframework/source/detail?r=8b6bf3ff4728
Added:
/tools/remoteserver/test/libs/mapping.py
Modified:
/src/robot/libraries/Remote.py
/tools/remoteserver/robotremoteserver.py
/tools/remoteserver/test/atest/argument_types.txt
/tools/remoteserver/test/atest/return_values.txt
/tools/remoteserver/test/libs/examplelib.py
=======================================
--- /dev/null
+++ /tools/remoteserver/test/libs/mapping.py Fri Nov 29 13:33:49 2013 UTC
@@ -0,0 +1,20 @@
+try:
+ from collections import Mapping
+
+ class MyMapping(Mapping):
+
+ def __init__(self, data=None, **extra):
+ self.data = data or {}
+ self.data.update(**extra)
+
+ def __getitem__(self, item):
+ return self.data[item]
+
+ def __len__(self):
+ return len(self.data)
+
+ def __iter__(self):
+ return iter(self.data)
+
+except ImportError:
+ MyMapping = dict
=======================================
--- /src/robot/libraries/Remote.py Fri Nov 29 11:33:47 2013 UTC
+++ /src/robot/libraries/Remote.py Fri Nov 29 13:33:49 2013 UTC
@@ -23,7 +23,7 @@
pass
from robot.errors import RemoteError
-from robot.utils import unic
+from robot.utils import is_list_like, is_dict_like, unic
class Remote(object):
@@ -68,9 +68,9 @@
def _handle_argument(self, arg):
if isinstance(arg, (basestring, int, long, float)):
return arg
- if isinstance(arg, (tuple, list)):
+ if is_list_like(arg):
return [self._handle_argument(item) for item in arg]
- if isinstance(arg, dict):
+ if is_dict_like(arg):
return dict((self._str(key), self._handle_argument(value))
for key, value in arg.items())
return self._str(arg)
=======================================
--- /tools/remoteserver/robotremoteserver.py Fri Nov 29 11:33:47 2013 UTC
+++ /tools/remoteserver/robotremoteserver.py Fri Nov 29 13:33:49 2013 UTC
@@ -21,6 +21,10 @@
import signal
except ImportError:
signal = None
+try:
+ from collections import Mapping
+except ImportError:
+ Mapping = dict
class RobotRemoteServer(SimpleXMLRPCServer):
@@ -30,6 +34,7 @@
SimpleXMLRPCServer.__init__(self, (host, int(port)),
logRequests=False)
self._library = library
self._allow_stop = allow_stop
+ self._shutdown = False
self._register_functions()
self._register_signal_handlers()
self._log('Robot Framework remote server starting at %s:%s'
@@ -53,7 +58,6 @@
signal.signal(signal.SIGINT, stop_with_signal)
def serve_forever(self):
- self._shutdown = False
while not self._shutdown:
self.handle_request()
@@ -150,12 +154,13 @@
def _handle_return_value(self, ret):
if isinstance(ret, (basestring, int, long, float)):
return ret
- if isinstance(ret, (tuple, list)):
- return [self._handle_return_value(item) for item in ret]
- if isinstance(ret, dict):
+ if isinstance(ret, Mapping):
return dict([(self._str(key), self._handle_return_value(value))
for key, value in ret.items()])
- return self._str(ret)
+ try:
+ return [self._handle_return_value(item) for item in ret]
+ except TypeError:
+ return self._str(ret)
def _str(self, item):
if item is None:
=======================================
--- /tools/remoteserver/test/atest/argument_types.txt Thu May 26 20:30:59
2011 UTC
+++ /tools/remoteserver/test/atest/argument_types.txt Fri Nov 29 13:33:49
2013 UTC
@@ -3,6 +3,7 @@
Library Remote localhost:${PORT} WITH NAME remote
Library Collections
Variables arguments.py
+Variables ../libs/mapping.py
*** Variables ***
${PORT} 8270
@@ -76,6 +77,9 @@
Nested Dictionary As Argument
Nested Dictionary As Argument ${NESTED_DICT}
+
+Mapping As Argument
+ Dictionary As Argument ${MyMapping(one=1, spam='eggs')}
Control Char As Argument
[Documentation] In this situation the received error is not that good
FAIL REGEXP: .*ExpatError.*
=======================================
--- /tools/remoteserver/test/atest/return_values.txt Thu May 26 20:30:59
2011 UTC
+++ /tools/remoteserver/test/atest/return_values.txt Fri Nov 29 13:33:49
2013 UTC
@@ -89,6 +89,10 @@
Return Nested Dictionary
[Tags] ruby
Return Value Should Be Return Nested Dictionary {'1': {'true':
False}, '2': {'A': {'n': ''}, 'B': {'o': '<MyObject>', 'e': {}}} }
+
+Return Mapping
+ [Tags] python
+ Return Value Should Be Return Mapping {'a': 1, '2': 'b', '':
{'none': ''}}
Return Control Char
[Documentation] FAIL REGEXP: Processing XML-RPC return value failed.
Most often this happens when the return value contains characters that are
not valid in XML. Original error was: ExpatError: .*
=======================================
--- /tools/remoteserver/test/libs/examplelib.py Fri Nov 29 11:33:47 2013 UTC
+++ /tools/remoteserver/test/libs/examplelib.py Fri Nov 29 13:33:49 2013 UTC
@@ -1,4 +1,4 @@
-import sys
+from mapping import MyMapping
class RemoteTestLibrary:
@@ -302,6 +302,9 @@
def return_nested_dictionary(self):
return { 1: {None: False},
2: {'A': {'n': None}, 'B': {'o': MyObject(), 'e': {}}} }
+
+ def return_mapping(self):
+ return MyMapping({'a': 1, 2: 'b', None: MyMapping(none=None)})
def return_control_char(self):
return '\x01'
--
---
You received this message because you are subscribed to the Google Groups "robotframework-commit" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to robotframework-commit+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.