Skip to content

Commit d9ff170

Browse files
committed
Fix DictJsonSchemaProvider and CollectionJsonSchemaProvider crash when sub-types are missing (#2037)
1 parent 9ad6123 commit d9ff170

3 files changed

Lines changed: 70 additions & 20 deletions

File tree

‎news/2037.bugfix‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fix crash in JSON schema providers for Dict and List fields when sub-types are missing by making adapter lookups safe.

‎src/plone/restapi/tests/test_types.py‎

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -797,3 +797,37 @@ def test_jsonfield(self):
797797
},
798798
adapter.get_schema(),
799799
)
800+
801+
def test_dict_without_types(self):
802+
field = schema.Dict(title="My field", description="My great field")
803+
adapter = getMultiAdapter(
804+
(field, self.portal, self.request), IJsonSchemaProvider
805+
)
806+
# This currently crashes with ComponentLookupError
807+
self.assertEqual(
808+
{
809+
"type": "dict",
810+
"title": "My field",
811+
"description": "My great field",
812+
},
813+
adapter.get_schema(),
814+
)
815+
816+
def test_list_without_value_type(self):
817+
field = schema.List(title="My field", description="My great field")
818+
adapter = getMultiAdapter(
819+
(field, self.portal, self.request), IJsonSchemaProvider
820+
)
821+
# This currently crashes with ComponentLookupError
822+
self.assertEqual(
823+
{
824+
"type": "array",
825+
"title": "My field",
826+
"description": "My great field",
827+
"factory": "List",
828+
"uniqueItems": False,
829+
"additionalItems": True,
830+
"items": {},
831+
},
832+
adapter.get_schema(),
833+
)

‎src/plone/restapi/types/adapters.py‎

Lines changed: 35 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
from plone.schema import IJSONField
1414
from z3c.formwidget.query.interfaces import IQuerySource
1515
from zope.component import adapter
16-
from zope.component import getMultiAdapter
16+
from zope.component import queryMultiAdapter
1717
from zope.i18n import translate
1818
from zope.interface import implementer
1919
from zope.interface import Interface
@@ -270,11 +270,16 @@ def get_factory(self):
270270

271271
def get_items(self):
272272
"""Get items properties."""
273-
value_type_adapter = getMultiAdapter(
274-
(self.field.value_type, self.context, self.request), IJsonSchemaProvider
275-
)
276-
277-
return value_type_adapter.get_schema()
273+
if self.field.value_type:
274+
value_type_adapter = queryMultiAdapter(
275+
(self.field.value_type, self.context, self.request), IJsonSchemaProvider
276+
)
277+
if value_type_adapter:
278+
try:
279+
return value_type_adapter.get_schema()
280+
except NotImplementedError:
281+
pass
282+
return {}
278283

279284
def additional(self):
280285
info = {}
@@ -434,20 +439,30 @@ def get_type(self):
434439

435440
def additional(self):
436441
info = {}
437-
key_type = getMultiAdapter(
438-
(self.field.key_type, self.context, self.request), IJsonSchemaProvider
439-
)
440-
info["key_type"] = {
441-
"schema": key_type.get_schema(),
442-
"additional": key_type.additional(),
443-
}
444-
value_type = getMultiAdapter(
445-
(self.field.value_type, self.context, self.request), IJsonSchemaProvider
446-
)
447-
info["value_type"] = {
448-
"schema": value_type.get_schema(),
449-
"additional": value_type.additional(),
450-
}
442+
if self.field.key_type:
443+
key_type = queryMultiAdapter(
444+
(self.field.key_type, self.context, self.request), IJsonSchemaProvider
445+
)
446+
if key_type:
447+
try:
448+
info["key_type"] = {
449+
"schema": key_type.get_schema(),
450+
"additional": key_type.additional(),
451+
}
452+
except NotImplementedError:
453+
pass
454+
if self.field.value_type:
455+
value_type = queryMultiAdapter(
456+
(self.field.value_type, self.context, self.request), IJsonSchemaProvider
457+
)
458+
if value_type:
459+
try:
460+
info["value_type"] = {
461+
"schema": value_type.get_schema(),
462+
"additional": value_type.additional(),
463+
}
464+
except NotImplementedError:
465+
pass
451466
return info
452467

453468

0 commit comments

Comments
 (0)