wsme/wsmeext/tests/test_extdirect.py
Chris Dent 1440eeb13b Fix (some) tests for modern flask and pep8
Somewhere along the way, WSME and flask/werkzeug have got out of sync
and tests have started failing. Since there aren't regular contributions
to WSME we don't catch these changes, so this may have happened months
or years ago.

I have adjusted tests to attempt to account for what I can, but one test
fails to work so I have marked it as an xfail. It works correctly with
werkzeug 1.13.x but not later. Since WSME is in something worse than
maintenance mode, I'm not inclined to fix this.

pep8/flake8 in python3 is more strict than python. The gate now
runs the pep8 jobs using python3 by default, so the local jobs
should as well. This changes the job and also fixes the new problems it
points out.

There are other failures, but they are present in master as well, so
leaving that for other changes.

Change-Id: I57ae0405e0d6ddba0bb1dac93020fb08a0fc7c89
2018-04-09 13:24:20 +01:00

244 lines
7.2 KiB
Python

import base64
import datetime
import decimal
try:
import simplejson as json
except ImportError:
import json # noqa
import wsme.tests.protocol
from wsme.utils import parse_isodatetime, parse_isodate, parse_isotime
from wsme.types import isarray, isdict, isusertype
import six
if six.PY3:
from urllib.parse import urlencode
else:
from urllib import urlencode # noqa
def encode_arg(value):
if isinstance(value, tuple):
value, datatype = value
else:
datatype = type(value)
if isinstance(datatype, list):
value = [encode_arg((item, datatype[0])) for item in value]
elif isinstance(datatype, dict):
key_type, value_type = list(datatype.items())[0]
value = dict((
(encode_arg((key, key_type)),
encode_arg((value, value_type)))
for key, value in value.items()
))
elif datatype in (datetime.date, datetime.time, datetime.datetime):
value = value.isoformat()
elif datatype == wsme.types.binary:
value = base64.encodestring(value).decode('ascii')
elif datatype == wsme.types.bytes:
value = value.decode('ascii')
elif datatype == decimal.Decimal:
value = str(value)
return value
def decode_result(value, datatype):
if value is None:
return None
if datatype == wsme.types.binary:
value = base64.decodestring(value.encode('ascii'))
return value
if isusertype(datatype):
datatype = datatype.basetype
if isinstance(datatype, list):
value = [decode_result(item, datatype[0]) for item in value]
elif isarray(datatype):
value = [decode_result(item, datatype.item_type) for item in value]
elif isinstance(datatype, dict):
key_type, value_type = list(datatype.items())[0]
value = dict((
(decode_result(key, key_type),
decode_result(value, value_type))
for key, value in value.items()
))
elif isdict(datatype):
key_type, value_type = datatype.key_type, datatype.value_type
value = dict((
(decode_result(key, key_type),
decode_result(value, value_type))
for key, value in value.items()
))
elif datatype == datetime.time:
value = parse_isotime(value)
elif datatype == datetime.date:
value = parse_isodate(value)
elif datatype == datetime.datetime:
value = parse_isodatetime(value)
elif hasattr(datatype, '_wsme_attributes'):
for attr in datatype._wsme_attributes:
if attr.key not in value:
continue
value[attr.key] = decode_result(value[attr.key], attr.datatype)
elif datatype == decimal.Decimal:
value = decimal.Decimal(value)
elif datatype == wsme.types.bytes:
value = value.encode('ascii')
elif datatype is not None and type(value) != datatype:
value = datatype(value)
return value
class TestExtDirectProtocol(wsme.tests.protocol.ProtocolTestCase):
protocol = 'extdirect'
protocol_options = {
'namespace': 'MyNS.api',
'nsfolder': 'app'
}
def call(self, fname, _rt=None, _no_result_decode=False, _accept=None,
**kw):
path = fname.split('/')
try:
func, funcdef, args = self.root._lookup_function(path)
arguments = funcdef.arguments
except Exception:
arguments = []
if len(path) == 1:
ns, action, fname = '', '', path[0]
elif len(path) == 2:
ns, action, fname = '', path[0], path[1]
else:
ns, action, fname = '.'.join(path[:-2]), path[-2], path[-1]
print(kw)
args = [
dict(
(arg.name, encode_arg(kw[arg.name]))
for arg in arguments if arg.name in kw
)
]
print("args =", args)
data = json.dumps({
'type': 'rpc',
'tid': 0,
'action': action,
'method': fname,
'data': args,
})
print(data)
headers = {'Content-Type': 'application/json'}
if _accept:
headers['Accept'] = _accept
res = self.app.post('/extdirect/router/%s' % ns, data, headers=headers,
expect_errors=True)
print(res.body)
if _no_result_decode:
return res
data = json.loads(res.text)
if data['type'] == 'rpc':
r = data['result']
return decode_result(r, _rt)
elif data['type'] == 'exception':
faultcode, faultstring = data['message'].split(': ', 1)
debuginfo = data.get('where')
raise wsme.tests.protocol.CallException(
faultcode, faultstring, debuginfo)
def test_api_alias(self):
assert self.root._get_protocol('extdirect').api_alias == '/app/api.js'
def test_get_api(self):
res = self.app.get('/app/api.js')
print(res.body)
assert res.body
def test_positional(self):
self.root._get_protocol('extdirect').default_params_notation = \
'positional'
data = json.dumps({
'type': 'rpc',
'tid': 0,
'action': 'misc',
'method': 'multiply',
'data': [2, 5],
})
headers = {'Content-Type': 'application/json'}
res = self.app.post('/extdirect/router', data, headers=headers)
print(res.body)
data = json.loads(res.text)
assert data['type'] == 'rpc'
r = data['result']
assert r == 10
def test_batchcall(self):
data = json.dumps([{
'type': 'rpc',
'tid': 1,
'action': 'argtypes',
'method': 'setdate',
'data': [{'value': '2011-04-06'}],
}, {
'type': 'rpc',
'tid': 2,
'action': 'returntypes',
'method': 'getbytes',
'data': []
}])
print(data)
headers = {'Content-Type': 'application/json'}
res = self.app.post('/extdirect/router', data, headers=headers)
print(res.body)
rdata = json.loads(res.text)
assert len(rdata) == 2
assert rdata[0]['tid'] == 1
assert rdata[0]['result'] == '2011-04-06'
assert rdata[1]['tid'] == 2
assert rdata[1]['result'] == 'astring'
def test_form_call(self):
params = {
'value[0].inner.aint': 54,
'value[1].inner.aint': 55,
'extType': 'rpc',
'extTID': 1,
'extAction': 'argtypes',
'extMethod': 'setnestedarray',
}
body = urlencode(params)
r = self.app.post(
'/extdirect/router',
body,
headers={'Content-Type': 'application/x-www-form-urlencoded'}
)
print(r)
assert json.loads(r.text) == {
"tid": "1",
"action": "argtypes",
"type": "rpc",
"method": "setnestedarray",
"result": [{
"inner": {
"aint": 54
}
}, {
"inner": {
"aint": 55
}
}]
}