sqlalchemy-jsonapi
sqlalchemy-jsonapi copied to clipboard
TypeError occurs when formatting detail when raising BadRequestError with garbage relationships in post_collection
Here is a test that should return a BadRequestError:
def test_add_resource_with_invalid_relationships(self):
"""Create resource with unknown OneToMany relationship key returns 400.
A BadRequestError is raised.
"""
payload = {
'data': {
'attributes': {
'first': 'Sally',
'last': 'Smith',
'username': 'SallySmith1',
'password': 'password',
},
'type': 'users',
'relationships': {
'posts': {
'data': [{
'type': 'posts',
'id': 1
},
{
'type': 'posts',
'id': 2
}]
},
'dogs': {
'data': [{
'id': 1,
'type': 'dogs'
}]
}
}
}
}
with self.assertRaises(errors.BadRequestError) as error:
models.serializer.post_collection(
self.session, payload, 'users')
self.assertEqual(error.exception.detail, 'dogs not relationship for users')
self.assertEqual(error.exception.status_code, 400)
However this test will never actually return this detail message because when this check happens:
data_keys = set(map((
lambda x: resource.__jsonapi_map_to_py__.get(x, None)),
data['data'].get('relationships', {}).keys()))
model_keys = set(resource.__mapper__.relationships.keys())
if not data_keys <= model_keys:
raise BadRequestError(
'{} not relationships for {}'.format(
', '.join(list(data_keys -
model_keys)), model.__jsonapi_type__))
When we take the difference between data_keys and model_keys we are getting {None} because
data_keys = {'posts',None'} and model_keys = {'posts','comments',logs'}.
When the BadRequestError is raised we get a TypeError: sequence 0: expected str instance, NoneType found.
This happens on both python3 and python2. I will look at more as to how to fix this.
This same TypeError: sequence 0: expected str instance, NoneType found also occurs in patch_resource when trying to raise a BadRequestError. Will put up issue.
Do you know what the expression not data_keys <= model_keys is trying to figure out?
Yes. Basically if you look at the test I posted above, we are trying to make sure we flag relationships that are not existent and raise a BadRequestError for those. So someone could send garbage input for the relationship keys, as I did in that test with dogs, and we would give a meaningful error message back so they understand the relationship between 'dogs' and 'users' does not exist. In other words, we are checking if data_keys is a subset of model_keys.