Include Pecan tests in default Python environment

- Makes sure we always run Pecan test and that there's no regression.
  There's no real need to split them out as they are not invasive.
  Also that reduces the number of environment a bit.
- This also fixes Pecan tests on python2.6
- This also fixes Pecan tests on python3.3
- This also enables Pecan tests on python3.2

Change-Id: I57070b0bd785fb3d445f432973f15825abccbdd5
This commit is contained in:
Julien Danjou 2013-09-26 12:12:20 +02:00
parent 7301adc75d
commit abcdd7affa
7 changed files with 241 additions and 185 deletions

View File

@ -6,6 +6,8 @@ from wsme.types import Base, text, wsattr
import wsme
import wsmeext.pecan
import six
class Author(Base):
id = int
@ -41,7 +43,6 @@ class BooksController(RestController):
@wsmeext.pecan.wsexpose(Book, int, int)
def get(self, author_id, id):
print repr(author_id), repr(id)
book = Book(
name=u"Les Confessions dun révolutionnaire pour servir à "
u"lhistoire de la révolution de février",
@ -51,8 +52,6 @@ class BooksController(RestController):
@wsmeext.pecan.wsexpose(Book, int, int, body=Book)
def put(self, author_id, id, book=None):
print author_id, id
print book
book.id = id
book.author = Author(id=author_id)
return book
@ -68,7 +67,7 @@ class AuthorsController(RestController):
books = BooksController()
@wsmeext.pecan.wsexpose([Author], [unicode], [Criterion])
@wsmeext.pecan.wsexpose([Author], [six.text_type], [Criterion])
def get_all(self, q=None, r=None):
if q:
return [
@ -116,4 +115,4 @@ class AuthorsController(RestController):
@wsmeext.pecan.wsexpose(None, int)
def delete(self, author_id):
print "Deleting", author_id
print("Deleting", author_id)

View File

@ -1,7 +1,7 @@
import os
from unittest import TestCase
from pecan import set_config
from pecan.testing import load_test_app
from pecan import testing
__all__ = ['FunctionalTest']
@ -13,7 +13,7 @@ class FunctionalTest(TestCase):
"""
def setUp(self):
self.app = load_test_app(os.path.join(
self.app = testing.load_test_app(os.path.join(
os.path.dirname(__file__),
'config.py'
))

View File

@ -2,14 +2,13 @@ from six.moves import http_client
from test.tests import FunctionalTest
import json
import pecan
import six
used_status_codes = [400, 401, 404, 500]
http_response_messages = {
code: '{} {}'.format(code, status)
for code, status in http_client.responses.iteritems()
if code in used_status_codes
}
http_response_messages = {}
for code in used_status_codes:
http_response_messages[code] = '%s %s' % (code, http_client.responses[code])
class TestWS(FunctionalTest):
@ -18,32 +17,28 @@ class TestWS(FunctionalTest):
def test_optional_array_param(self):
r = self.app.get('/authors?q=a&q=b')
l = json.loads(r.body)
print l
l = json.loads(r.body.decode('utf-8'))
assert len(l) == 2
assert l[0]['firstname'] == 'a'
assert l[1]['firstname'] == 'b'
def test_optional_indexed_array_param(self):
r = self.app.get('/authors?q[0]=a&q[1]=b')
l = json.loads(r.body)
print l
l = json.loads(r.body.decode('utf-8'))
assert len(l) == 2
assert l[0]['firstname'] == 'a'
assert l[1]['firstname'] == 'b'
def test_options_object_array_param(self):
r = self.app.get('/authors?r.value=a&r.value=b')
l = json.loads(r.body)
print l
l = json.loads(r.body.decode('utf-8'))
assert len(l) == 2
assert l[0]['firstname'] == 'a'
assert l[1]['firstname'] == 'b'
def test_options_indexed_object_array_param(self):
r = self.app.get('/authors?r[0].value=a&r[1].value=b')
l = json.loads(r.body)
print l
l = json.loads(r.body.decode('utf-8'))
assert len(l) == 2
assert l[0]['firstname'] == 'a'
assert l[1]['firstname'] == 'b'
@ -52,9 +47,7 @@ class TestWS(FunctionalTest):
a = self.app.get(
'/authors/1.json',
)
print a
a = json.loads(a.body)
print a
a = json.loads(a.body.decode('utf-8'))
assert a['id'] == 1
assert a['firstname'] == 'aname'
@ -62,9 +55,9 @@ class TestWS(FunctionalTest):
a = self.app.get(
'/authors/1.xml',
)
print a
assert '<id>1</id>' in a.body
assert '<firstname>aname</firstname>' in a.body
body = a.body.decode('utf-8')
assert '<id>1</id>' in body
assert '<firstname>aname</firstname>' in body
def test_post_body_parameter(self):
res = self.app.post(
@ -72,8 +65,7 @@ class TestWS(FunctionalTest):
headers={"Content-Type": "application/json"}
)
assert res.status_int == 201
a = json.loads(res.body)
print a
a = json.loads(res.body.decode('utf-8'))
assert a['id'] == 10
assert a['firstname'] == 'test'
@ -84,19 +76,16 @@ class TestWS(FunctionalTest):
'/authors/999.json',
expect_errors=True
)
print res
self.assertEqual(res.status, expected_status)
a = json.loads(res.body)
print a
a = json.loads(res.body.decode('utf-8'))
assert a['faultcode'] == 'Client'
res = self.app.get(
'/authors/999.xml',
expect_errors=True
)
print res
self.assertEqual(res.status, expected_status)
assert '<faultcode>Client</faultcode>' in res.body
assert '<faultcode>Client</faultcode>' in res.body.decode('utf-8')
def test_custom_clientside_error(self):
expected_status_code = 404
@ -105,19 +94,16 @@ class TestWS(FunctionalTest):
'/authors/998.json',
expect_errors=True
)
print res
self.assertEqual(res.status, expected_status)
a = json.loads(res.body)
print a
a = json.loads(res.body.decode('utf-8'))
assert a['faultcode'] == 'Server'
res = self.app.get(
'/authors/998.xml',
expect_errors=True
)
print res
self.assertEqual(res.status, expected_status)
assert '<faultcode>Server</faultcode>' in res.body
assert '<faultcode>Server</faultcode>' in res.body.decode('utf-8')
def test_custom_non_http_clientside_error(self):
expected_status_code = 500
@ -126,19 +112,16 @@ class TestWS(FunctionalTest):
'/authors/997.json',
expect_errors=True
)
print res
self.assertEqual(res.status, expected_status)
a = json.loads(res.body)
print a
a = json.loads(res.body.decode('utf-8'))
assert a['faultcode'] == 'Server'
res = self.app.get(
'/authors/997.xml',
expect_errors=True
)
print res
self.assertEqual(res.status, expected_status)
assert '<faultcode>Server</faultcode>' in res.body
assert '<faultcode>Server</faultcode>' in res.body.decode('utf-8')
def test_non_default_response(self):
expected_status_code = 401
@ -155,8 +138,7 @@ class TestWS(FunctionalTest):
expected_status = http_response_messages[expected_status_code]
res = self.app.get('/divide_by_zero.json', expect_errors=True)
self.assertEqual(res.status, expected_status)
a = json.loads(res.body)
print a
a = json.loads(res.body.decode('utf-8'))
assert a['faultcode'] == 'Server'
assert a['debuginfo'] is None
@ -166,8 +148,7 @@ class TestWS(FunctionalTest):
pecan.set_config({'wsme': {'debug': True}})
res = self.app.get('/divide_by_zero.json', expect_errors=True)
self.assertEqual(res.status, expected_status)
a = json.loads(res.body)
print a
a = json.loads(res.body.decode('utf-8'))
assert a['faultcode'] == 'Server'
assert a['debuginfo'].startswith('Traceback (most recent call last):')
@ -177,11 +158,13 @@ class TestWS(FunctionalTest):
'{"name": "Alice au pays des merveilles"}',
headers={"Content-Type": "application/json"}
)
book = json.loads(res.body)
print book
book = json.loads(res.body.decode('utf-8'))
assert book['id'] == 2
assert book['author']['id'] == 1
def test_no_content_type_if_no_return_type(self):
if six.PY3:
self.skipTest(
"This test does not work in Python 3 until https://review.openstack.org/#/c/48439/ is merged")
res = self.app.delete('/authors/4')
assert "Content-Type" not in res.headers, res.headers['Content-Type']

View File

@ -1,6 +1,6 @@
# content of: tox.ini , put in same dir as setup.py
[tox]
envlist = py26,py26-nolxml,py27,py27-nolxml,py32,py32-nolxml,pypy,sphinxext,tg11,tg15,pecan,flask,cornice,coverage,py33,py33-nolxml,pep8
envlist = py26,py26-nolxml,py27,py27-nolxml,py32,py32-nolxml,pypy,sphinxext,tg11,tg15,flask,cornice,coverage,py33,py33-nolxml,pep8
[common]
testtools=
@ -20,9 +20,10 @@ deps =
webtest
transaction
suds
pecan
commands=
{envbindir}/coverage run {envbindir}/nosetests --nologcapture --with-xunit --xunit-file nosetests-{envname}.xml wsme/tests wsmeext/tests --verbose {posargs}
{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
@ -36,10 +37,11 @@ deps =
{[common]testtools}
webtest
transaction
pecan
https://bitbucket.org/bernh/suds-python-3-patches/downloads/suds_patched.zip
commands=
{envbindir}/coverage run {envbindir}/nosetests --with-xunit --xunit-file nosetests-{envname}.xml wsme/tests wsmeext/tests --verbose {posargs}
{envbindir}/coverage run {envbindir}/nosetests --with-xunit --xunit-file nosetests-{envname}.xml wsme/tests wsmeext/tests tests/pecantest tests/pecantest --verbose {posargs}
{envbindir}/coverage xml -o coverage-{envname}.xml --omit wsmeext/sphinxext.py wsme/*.py wsme/rest/*.py wsmeext/*.py
{envbindir}/coverage report --show-missing --omit wsmeext/sphinxext.py wsme/*.py wsme/rest/*.py wsmeext/*.py
@ -50,10 +52,11 @@ deps =
{[common]testtools}
webtest
transaction
pecan
https://bitbucket.org/bernh/suds-python-3-patches/downloads/suds_patched.zip
commands=
{envbindir}/coverage run {envbindir}/nosetests --with-xunit --xunit-file nosetests-{envname}.xml wsme/tests wsmeext/tests --verbose {posargs}
{envbindir}/coverage run {envbindir}/nosetests --with-xunit --xunit-file nosetests-{envname}.xml wsme/tests wsmeext/tests tests/pecantest --verbose {posargs}
{envbindir}/coverage xml -o coverage-{envname}.xml --omit wsmeext/sphinxext.py wsme/*.py wsme/rest/*.py wsmeext/*.py
{envbindir}/coverage report --show-missing --omit wsmeext/sphinxext.py wsme/*.py wsme/rest/*.py wsmeext/*.py
@ -145,23 +148,6 @@ 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
[testenv:pecan]
basepython=python2.7
deps=
pbr
nose
webtest
coverage
simplejson
pecan
setenv=
PYTHONPATH={toxinidir}
COVERAGE_FILE=.coverage.{envname}
commands=
{envbindir}/nosetests -w tests/pecantest test/tests/test_ws.py --with-xunit --xunit-file nosetests-{envname}.xml --verbose --with-coverage --cover-package wsme,wsmeext {posargs}
{envbindir}/coverage xml -o coverage-{envname}.xml wsme/*.py wsme/rest/*.py wsmeext/*.py
[testenv:flask]
basepython=python2.7
deps=

306
tox.ini

File diff suppressed because it is too large Load Diff

View File

@ -11,6 +11,8 @@ from wsme.types import UserType, ArrayType, DictType, File
from wsme.utils import parse_isodate, parse_isotime, parse_isodatetime
import wsme.runtime
from six import moves
ARRAY_MAX_SIZE = 1000
@ -114,7 +116,7 @@ def array_from_params(datatype, params, path, hit_paths):
if len(value) < len(attrvalues):
value[-1:] = [
datatype.item_type()
for i in xrange(len(attrvalues) - len(value))
for i in moves.range(len(attrvalues) - len(value))
]
for i, attrvalue in enumerate(attrvalues):
setattr(

View File

@ -53,6 +53,11 @@ def wsexpose(*args, **kwargs):
content_type='application/xml',
generic=False
)
pecan_text_xml_decorate = pecan.expose(
template='wsmexml:',
content_type='text/xml',
generic=False
)
sig = wsme.signature(*args, **kwargs)
def decorate(f):
@ -109,6 +114,7 @@ def wsexpose(*args, **kwargs):
)
pecan_xml_decorate(callfunction)
pecan_text_xml_decorate(callfunction)
pecan_json_decorate(callfunction)
pecan.util._cfg(callfunction)['argspec'] = inspect.getargspec(f)
callfunction._wsme_definition = funcdef