summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJulien Danjou <julien@danjou.info>2013-09-18 13:45:06 +0200
committerJulien Danjou <julien@danjou.info>2013-10-02 17:59:59 +0200
commit259fea952998f9b07d64448318ae6186b4372549 (patch)
treef7a53312dcf1181014794605b886fb2fb688e733
parent6bb3227165fe199de58a66b3699aee595b1076af (diff)
downloadwsme-259fea952998f9b07d64448318ae6186b4372549.tar.gz
types: fix error return when None is in Enum
Whe None is set as a valid value in an Enum, the error string that is meant to be returned is built with a join() call on valid values. However, that doesn't work as None isn't not a string. Calling map(str, values) fixes this problem. Also, if the value is invalid, the error code returned is 500 as if it was the server fault. 400 should be returned instead, so rather than raising a ValueError we raise an InvalidInput error. Change-Id: I92695594676da2a247cef4e1e8fe277aa0972dea
-rw-r--r--tox-tmpl.ini10
-rw-r--r--tox.ini44
-rw-r--r--wsme/tests/test_api.py33
-rw-r--r--wsme/tests/test_types.py23
-rw-r--r--wsme/types.py10
5 files changed, 104 insertions, 16 deletions
diff --git a/tox-tmpl.ini b/tox-tmpl.ini
index 355f022..533dbd5 100644
--- a/tox-tmpl.ini
+++ b/tox-tmpl.ini
@@ -27,6 +27,16 @@ commands=
{envbindir}/coverage xml -o coverage-{envname}.xml wsme/*.py wsme/rest/*.py wsmeext/*.py
{envbindir}/coverage report --show-missing wsme/*.py wsme/rest/*.py wsmeext/*.py
+[axis:python:py26]
+deps =
+ {[common]testtools}
+ webtest
+ transaction
+ suds
+ pecan
+ unittest2
+basepython=python2.6
+
[axis:python:py27]
basepython=python2.7
diff --git a/tox.ini b/tox.ini
index 0235f83..37dced0 100644
--- a/tox.ini
+++ b/tox.ini
@@ -161,12 +161,14 @@ commands =
{envbindir}/coverage run {envbindir}/nosetests --nologcapture --with-xunit --xunit-file nosetests-{envname}.xml wsme/tests wsmeext/tests tests/pecantest --verbose {posargs}
{envbindir}/coverage xml -o coverage-{envname}.xml wsme/*.py wsme/rest/*.py wsmeext/*.py
{envbindir}/coverage report --show-missing wsme/*.py wsme/rest/*.py wsmeext/*.py
+basepython = python2.6
deps =
{[common]testtools}
webtest
transaction
suds
pecan
+ unittest2
SQLAlchemy<=0.5.99
lxml
@@ -175,12 +177,14 @@ commands =
{envbindir}/coverage run {envbindir}/nosetests --nologcapture --with-xunit --xunit-file nosetests-{envname}.xml wsme/tests wsmeext/tests tests/pecantest --verbose {posargs}
{envbindir}/coverage xml -o coverage-{envname}.xml wsme/*.py wsme/rest/*.py wsmeext/*.py
{envbindir}/coverage report --show-missing wsme/*.py wsme/rest/*.py wsmeext/*.py
+basepython = python2.6
deps =
{[common]testtools}
webtest
transaction
suds
pecan
+ unittest2
SQLAlchemy<=0.5.99
lxml
@@ -189,12 +193,14 @@ commands =
{envbindir}/coverage run {envbindir}/nosetests --nologcapture --with-xunit --xunit-file nosetests-{envname}.xml wsme/tests wsmeext/tests tests/pecantest --verbose {posargs}
{envbindir}/coverage xml -o coverage-{envname}.xml wsme/*.py wsme/rest/*.py wsmeext/*.py
{envbindir}/coverage report --show-missing wsme/*.py wsme/rest/*.py wsmeext/*.py
+basepython = python2.6
deps =
{[common]testtools}
webtest
transaction
suds
pecan
+ unittest2
SQLAlchemy<=0.5.99
lxml
simplejson
@@ -204,12 +210,14 @@ commands =
{envbindir}/coverage run {envbindir}/nosetests --nologcapture --with-xunit --xunit-file nosetests-{envname}.xml wsme/tests wsmeext/tests tests/pecantest --verbose {posargs}
{envbindir}/coverage xml -o coverage-{envname}.xml wsme/*.py wsme/rest/*.py wsmeext/*.py
{envbindir}/coverage report --show-missing wsme/*.py wsme/rest/*.py wsmeext/*.py
+basepython = python2.6
deps =
{[common]testtools}
webtest
transaction
suds
pecan
+ unittest2
SQLAlchemy<=0.5.99
lxml
simplejson
@@ -219,12 +227,14 @@ commands =
{envbindir}/coverage run {envbindir}/nosetests --nologcapture --with-xunit --xunit-file nosetests-{envname}.xml wsme/tests wsmeext/tests tests/pecantest --verbose {posargs}
{envbindir}/coverage xml -o coverage-{envname}.xml wsme/*.py wsme/rest/*.py wsmeext/*.py
{envbindir}/coverage report --show-missing wsme/*.py wsme/rest/*.py wsmeext/*.py
+basepython = python2.6
deps =
{[common]testtools}
webtest
transaction
suds
pecan
+ unittest2
SQLAlchemy<=0.5.99
[testenv:py26-sa5-nolxml]
@@ -232,12 +242,14 @@ commands =
{envbindir}/coverage run {envbindir}/nosetests --nologcapture --with-xunit --xunit-file nosetests-{envname}.xml wsme/tests wsmeext/tests tests/pecantest --verbose {posargs}
{envbindir}/coverage xml -o coverage-{envname}.xml wsme/*.py wsme/rest/*.py wsmeext/*.py
{envbindir}/coverage report --show-missing wsme/*.py wsme/rest/*.py wsmeext/*.py
+basepython = python2.6
deps =
{[common]testtools}
webtest
transaction
suds
pecan
+ unittest2
SQLAlchemy<=0.5.99
[testenv:py26-sa5-nolxml-simplejson]
@@ -245,12 +257,14 @@ commands =
{envbindir}/coverage run {envbindir}/nosetests --nologcapture --with-xunit --xunit-file nosetests-{envname}.xml wsme/tests wsmeext/tests tests/pecantest --verbose {posargs}
{envbindir}/coverage xml -o coverage-{envname}.xml wsme/*.py wsme/rest/*.py wsmeext/*.py
{envbindir}/coverage report --show-missing wsme/*.py wsme/rest/*.py wsmeext/*.py
+basepython = python2.6
deps =
{[common]testtools}
webtest
transaction
suds
pecan
+ unittest2
SQLAlchemy<=0.5.99
simplejson
@@ -259,12 +273,14 @@ commands =
{envbindir}/coverage run {envbindir}/nosetests --nologcapture --with-xunit --xunit-file nosetests-{envname}.xml wsme/tests wsmeext/tests tests/pecantest --verbose {posargs}
{envbindir}/coverage xml -o coverage-{envname}.xml wsme/*.py wsme/rest/*.py wsmeext/*.py
{envbindir}/coverage report --show-missing wsme/*.py wsme/rest/*.py wsmeext/*.py
+basepython = python2.6
deps =
{[common]testtools}
webtest
transaction
suds
pecan
+ unittest2
SQLAlchemy<=0.6.99
lxml
@@ -273,12 +289,14 @@ commands =
{envbindir}/coverage run {envbindir}/nosetests --nologcapture --with-xunit --xunit-file nosetests-{envname}.xml wsme/tests wsmeext/tests tests/pecantest --verbose {posargs}
{envbindir}/coverage xml -o coverage-{envname}.xml wsme/*.py wsme/rest/*.py wsmeext/*.py
{envbindir}/coverage report --show-missing wsme/*.py wsme/rest/*.py wsmeext/*.py
+basepython = python2.6
deps =
{[common]testtools}
webtest
transaction
suds
pecan
+ unittest2
SQLAlchemy<=0.6.99
lxml
@@ -287,12 +305,14 @@ commands =
{envbindir}/coverage run {envbindir}/nosetests --nologcapture --with-xunit --xunit-file nosetests-{envname}.xml wsme/tests wsmeext/tests tests/pecantest --verbose {posargs}
{envbindir}/coverage xml -o coverage-{envname}.xml wsme/*.py wsme/rest/*.py wsmeext/*.py
{envbindir}/coverage report --show-missing wsme/*.py wsme/rest/*.py wsmeext/*.py
+basepython = python2.6
deps =
{[common]testtools}
webtest
transaction
suds
pecan
+ unittest2
SQLAlchemy<=0.6.99
lxml
simplejson
@@ -302,12 +322,14 @@ commands =
{envbindir}/coverage run {envbindir}/nosetests --nologcapture --with-xunit --xunit-file nosetests-{envname}.xml wsme/tests wsmeext/tests tests/pecantest --verbose {posargs}
{envbindir}/coverage xml -o coverage-{envname}.xml wsme/*.py wsme/rest/*.py wsmeext/*.py
{envbindir}/coverage report --show-missing wsme/*.py wsme/rest/*.py wsmeext/*.py
+basepython = python2.6
deps =
{[common]testtools}
webtest
transaction
suds
pecan
+ unittest2
SQLAlchemy<=0.6.99
lxml
simplejson
@@ -317,12 +339,14 @@ commands =
{envbindir}/coverage run {envbindir}/nosetests --nologcapture --with-xunit --xunit-file nosetests-{envname}.xml wsme/tests wsmeext/tests tests/pecantest --verbose {posargs}
{envbindir}/coverage xml -o coverage-{envname}.xml wsme/*.py wsme/rest/*.py wsmeext/*.py
{envbindir}/coverage report --show-missing wsme/*.py wsme/rest/*.py wsmeext/*.py
+basepython = python2.6
deps =
{[common]testtools}
webtest
transaction
suds
pecan
+ unittest2
SQLAlchemy<=0.6.99
[testenv:py26-sa6-nolxml]
@@ -330,12 +354,14 @@ commands =
{envbindir}/coverage run {envbindir}/nosetests --nologcapture --with-xunit --xunit-file nosetests-{envname}.xml wsme/tests wsmeext/tests tests/pecantest --verbose {posargs}
{envbindir}/coverage xml -o coverage-{envname}.xml wsme/*.py wsme/rest/*.py wsmeext/*.py
{envbindir}/coverage report --show-missing wsme/*.py wsme/rest/*.py wsmeext/*.py
+basepython = python2.6
deps =
{[common]testtools}
webtest
transaction
suds
pecan
+ unittest2
SQLAlchemy<=0.6.99
[testenv:py26-sa6-nolxml-simplejson]
@@ -343,12 +369,14 @@ commands =
{envbindir}/coverage run {envbindir}/nosetests --nologcapture --with-xunit --xunit-file nosetests-{envname}.xml wsme/tests wsmeext/tests tests/pecantest --verbose {posargs}
{envbindir}/coverage xml -o coverage-{envname}.xml wsme/*.py wsme/rest/*.py wsmeext/*.py
{envbindir}/coverage report --show-missing wsme/*.py wsme/rest/*.py wsmeext/*.py
+basepython = python2.6
deps =
{[common]testtools}
webtest
transaction
suds
pecan
+ unittest2
SQLAlchemy<=0.6.99
simplejson
@@ -357,12 +385,14 @@ commands =
{envbindir}/coverage run {envbindir}/nosetests --nologcapture --with-xunit --xunit-file nosetests-{envname}.xml wsme/tests wsmeext/tests tests/pecantest --verbose {posargs}
{envbindir}/coverage xml -o coverage-{envname}.xml wsme/*.py wsme/rest/*.py wsmeext/*.py
{envbindir}/coverage report --show-missing wsme/*.py wsme/rest/*.py wsmeext/*.py
+basepython = python2.6
deps =
{[common]testtools}
webtest
transaction
suds
pecan
+ unittest2
SQLAlchemy<=0.7.99
lxml
@@ -371,12 +401,14 @@ commands =
{envbindir}/coverage run {envbindir}/nosetests --nologcapture --with-xunit --xunit-file nosetests-{envname}.xml wsme/tests wsmeext/tests tests/pecantest --verbose {posargs}
{envbindir}/coverage xml -o coverage-{envname}.xml wsme/*.py wsme/rest/*.py wsmeext/*.py
{envbindir}/coverage report --show-missing wsme/*.py wsme/rest/*.py wsmeext/*.py
+basepython = python2.6
deps =
{[common]testtools}
webtest
transaction
suds
pecan
+ unittest2
SQLAlchemy<=0.7.99
lxml
@@ -385,12 +417,14 @@ commands =
{envbindir}/coverage run {envbindir}/nosetests --nologcapture --with-xunit --xunit-file nosetests-{envname}.xml wsme/tests wsmeext/tests tests/pecantest --verbose {posargs}
{envbindir}/coverage xml -o coverage-{envname}.xml wsme/*.py wsme/rest/*.py wsmeext/*.py
{envbindir}/coverage report --show-missing wsme/*.py wsme/rest/*.py wsmeext/*.py
+basepython = python2.6
deps =
{[common]testtools}
webtest
transaction
suds
pecan
+ unittest2
SQLAlchemy<=0.7.99
lxml
simplejson
@@ -400,12 +434,14 @@ commands =
{envbindir}/coverage run {envbindir}/nosetests --nologcapture --with-xunit --xunit-file nosetests-{envname}.xml wsme/tests wsmeext/tests tests/pecantest --verbose {posargs}
{envbindir}/coverage xml -o coverage-{envname}.xml wsme/*.py wsme/rest/*.py wsmeext/*.py
{envbindir}/coverage report --show-missing wsme/*.py wsme/rest/*.py wsmeext/*.py
+basepython = python2.6
deps =
{[common]testtools}
webtest
transaction
suds
pecan
+ unittest2
SQLAlchemy<=0.7.99
lxml
simplejson
@@ -415,12 +451,14 @@ commands =
{envbindir}/coverage run {envbindir}/nosetests --nologcapture --with-xunit --xunit-file nosetests-{envname}.xml wsme/tests wsmeext/tests tests/pecantest --verbose {posargs}
{envbindir}/coverage xml -o coverage-{envname}.xml wsme/*.py wsme/rest/*.py wsmeext/*.py
{envbindir}/coverage report --show-missing wsme/*.py wsme/rest/*.py wsmeext/*.py
+basepython = python2.6
deps =
{[common]testtools}
webtest
transaction
suds
pecan
+ unittest2
SQLAlchemy<=0.7.99
[testenv:py26-nolxml]
@@ -428,12 +466,14 @@ commands =
{envbindir}/coverage run {envbindir}/nosetests --nologcapture --with-xunit --xunit-file nosetests-{envname}.xml wsme/tests wsmeext/tests tests/pecantest --verbose {posargs}
{envbindir}/coverage xml -o coverage-{envname}.xml wsme/*.py wsme/rest/*.py wsmeext/*.py
{envbindir}/coverage report --show-missing wsme/*.py wsme/rest/*.py wsmeext/*.py
+basepython = python2.6
deps =
{[common]testtools}
webtest
transaction
suds
pecan
+ unittest2
SQLAlchemy<=0.7.99
[testenv:py26-sa7-nolxml-simplejson]
@@ -441,12 +481,14 @@ commands =
{envbindir}/coverage run {envbindir}/nosetests --nologcapture --with-xunit --xunit-file nosetests-{envname}.xml wsme/tests wsmeext/tests tests/pecantest --verbose {posargs}
{envbindir}/coverage xml -o coverage-{envname}.xml wsme/*.py wsme/rest/*.py wsmeext/*.py
{envbindir}/coverage report --show-missing wsme/*.py wsme/rest/*.py wsmeext/*.py
+basepython = python2.6
deps =
{[common]testtools}
webtest
transaction
suds
pecan
+ unittest2
SQLAlchemy<=0.7.99
simplejson
@@ -455,12 +497,14 @@ commands =
{envbindir}/coverage run {envbindir}/nosetests --nologcapture --with-xunit --xunit-file nosetests-{envname}.xml wsme/tests wsmeext/tests tests/pecantest --verbose {posargs}
{envbindir}/coverage xml -o coverage-{envname}.xml wsme/*.py wsme/rest/*.py wsmeext/*.py
{envbindir}/coverage report --show-missing wsme/*.py wsme/rest/*.py wsmeext/*.py
+basepython = python2.6
deps =
{[common]testtools}
webtest
transaction
suds
pecan
+ unittest2
SQLAlchemy<=0.7.99
simplejson
diff --git a/wsme/tests/test_api.py b/wsme/tests/test_api.py
index e27cf69..f08b74b 100644
--- a/wsme/tests/test_api.py
+++ b/wsme/tests/test_api.py
@@ -2,13 +2,16 @@
from six import b
-import unittest
+try:
+ import unittest2 as unittest
+except ImportError:
+ import unittest
import webtest
from wsme import WSRoot, expose, validate
from wsme.rest import scan_api
from wsme.api import FunctionArgument, FunctionDefinition
-from wsme.types import iscomplex
+from wsme import types
import wsme.types
from wsme.tests.test_protocols import DummyProtocol
@@ -57,7 +60,31 @@ class TestController(unittest.TestCase):
assert not args[2].mandatory
assert args[2].default == 0
- assert iscomplex(ComplexType)
+ assert types.iscomplex(ComplexType)
+
+ def test_validate_enum_with_none(self):
+ class Version(object):
+ number = types.Enum(str, 'v1', 'v2', None)
+
+ class MyWS(WSRoot):
+ @expose(str)
+ @validate(Version)
+ def setcplx(self, version):
+ pass
+
+ r = MyWS(['restjson'])
+ app = webtest.TestApp(r.wsgiapp())
+ res = app.post_json('/setcplx', params={'version': {'number': 'arf'}},
+ expect_errors=True,
+ headers={'Accept': 'application/json'})
+ self.assertTrue(
+ res.json_body['faultstring'].startswith(
+ "Invalid input for field/attribute number. Value: 'arf'. \
+Invalid value (should be one of:"))
+ self.assertIn('v1', res.json_body['faultstring'])
+ self.assertIn('v2', res.json_body['faultstring'])
+ self.assertIn('None', res.json_body['faultstring'])
+ self.assertEqual(res.status_int, 400)
def test_scan_api(self):
class NS(object):
diff --git a/wsme/tests/test_types.py b/wsme/tests/test_types.py
index c878513..167114b 100644
--- a/wsme/tests/test_types.py
+++ b/wsme/tests/test_types.py
@@ -1,6 +1,10 @@
-import unittest
+try:
+ import unittest2 as unittest
+except ImportError:
+ import unittest
import six
+from wsme import exc
from wsme import types
@@ -176,12 +180,13 @@ class TestTypes(unittest.TestCase):
obj.a = 'v1'
assert obj.a == 'v1', repr(obj.a)
- try:
- obj.a = 'v3'
- assert False, 'ValueError was not raised'
- except ValueError as e:
- assert str(e) == \
- "a: Value 'v3' is invalid (should be one of: v1, v2)", e
+ self.assertRaisesRegexp(exc.InvalidInput,
+ "Invalid input for field/attribute a. \
+Value: 'v3'. Invalid value \(should be one of: v., v.\)",
+ setattr,
+ obj,
+ 'a',
+ 'v3')
def test_attribute_validation(self):
class AType(object):
@@ -197,8 +202,8 @@ class TestTypes(unittest.TestCase):
obj.aint = 5
assert obj.aint == 5
- self.assertRaises(ValueError, setattr, obj, 'alist', 12)
- self.assertRaises(ValueError, setattr, obj, 'alist', [2, 'a'])
+ self.assertRaises(exc.InvalidInput, setattr, obj, 'alist', 12)
+ self.assertRaises(exc.InvalidInput, setattr, obj, 'alist', [2, 'a'])
def test_text_attribute_conversion(self):
class SType(object):
diff --git a/wsme/types.py b/wsme/types.py
index 789cbd0..18b032f 100644
--- a/wsme/types.py
+++ b/wsme/types.py
@@ -7,6 +7,8 @@ import six
import sys
import weakref
+from wsme import exc
+
log = logging.getLogger(__name__)
#: The 'str' (python 2) or 'bytes' (python 3) type.
@@ -154,13 +156,13 @@ class Enum(UserType):
self.values = set(values)
name = kw.pop('name', None)
if name is None:
- name = "Enum(%s)" % ', '.join((str(v) for v in values))
+ name = "Enum(%s)" % ', '.join((six.text_type(v) for v in values))
self.name = name
def validate(self, value):
if value not in self.values:
- raise ValueError("Value '%s' is invalid (should be one of: %s)" % (
- value, ', '.join(sorted(self.values))))
+ raise ValueError("Invalid value (should be one of: %s)" %
+ ', '.join(map(six.text_type, self.values)))
return value
def tobasetype(self, value):
@@ -341,7 +343,7 @@ class wsattr(object):
try:
value = validate_value(self.datatype, value)
except ValueError as e:
- raise ValueError("%s: %s" % (self.name, e))
+ raise exc.InvalidInput(self.name, value, six.text_type(e))
dataholder = self._get_dataholder(instance)
if value is Unset:
if hasattr(dataholder, self.key):