cwacek / python-jsonschema-objects

Automatic Python binding generation from JSON Schemas
MIT License
364 stars 96 forks source link

Improper tuple validation #202

Closed ahulist closed 3 years ago

ahulist commented 3 years ago

Describe the bug tuple validation on array is not working as expected. ValidationError/TypeError pop up even though they should not.

Example Schema and code 1)

import python_jsonschema_objects as pjs

schema = {
    "title": "Base",
    "type": "object",
    "properties": {
        "name": {
            "additionalItems": False,
            "type": "array",
            "items": [
                {
                    "enum": [
                        "A",
                        "B"
                    ]
                },
                {
                    "type": "string"
                }
            ]
        },
    }
}

builder = pjs.ObjectBuilder(schema)
klasses = builder.build_classes()
a = klasses.Base()
a.name = ['A', 'X']

ValidationError                           Traceback (most recent call last)
<ipython-input-97-7965663f677d> in <module>
----> 1 a.name = ['A', 'X']

~/.conda/envs/py37/lib/python3.7/site-packages/python_jsonschema_objects/classbuilder.py in __setattr__(self, name, val)
    226             # it directly. XXX Heinous.
    227             prop = getattr(self.__class__, self.__prop_names__[name])
--> 228             prop.__set__(self, val)
    229         else:
    230             # This is an additional property of some kind

~/.conda/envs/py37/lib/python3.7/site-packages/python_jsonschema_objects/descriptors.py in __set__(self, obj, val)
     83                 errstr = "\n".join(errors)
     84                 raise validators.ValidationError(
---> 85                     "Object must be one of {0}: \n{1}".format(info["type"], errstr)
     86                 )
     87 

>>> ValidationError: Object must be one of [<class 'python_jsonschema_objects.classbuilder.base/name/<anonymous_0>'>, <class 'python_jsonschema_objects.classbuilder.base/name/<anonymous_1>'>]: 
>>> Failed to coerce to '<class 'python_jsonschema_objects.classbuilder.base/name/<anonymous_0>'>': ['A', 'X'] is not one of ['A', 'B']
>>> Failed to coerce to '<class 'python_jsonschema_objects.classbuilder.base/name/<anonymous_1>'>': ['A', 'X'] is not a string

2)

import python_jsonschema_objects as pjs

s = {
    "title": "Base",
    "type": "object",
    "properties": {
        "name": {
            "additionalItems": False,
            "type": "array",
            "items": [
                {
                    "enum": [
                        "A",
                        "B"
                    ]
                },
                {
                    "type": ["string", "null"]
                }
            ]
        },
    }
}

builder = pjs.ObjectBuilder(s)
klasses = builder.build_classes()
a = klasses.Base()

a.name = ['A', None]

TypeError                                 Traceback (most recent call last)
<ipython-input-95-4295b0f2ae77> in <module>
----> 1 a.name = ['A', None]

~/.conda/envs/py37/lib/python3.7/site-packages/python_jsonschema_objects/classbuilder.py in __setattr__(self, name, val)
    226             # it directly. XXX Heinous.
    227             prop = getattr(self.__class__, self.__prop_names__[name])
--> 228             prop.__set__(self, val)
    229         else:
    230             # This is an additional property of some kind

~/.conda/envs/py37/lib/python3.7/site-packages/python_jsonschema_objects/descriptors.py in __set__(self, obj, val)
     45 
     46             for typ in type_checks:
---> 47                 if isinstance(val, typ):
     48                     ok = True
     49                     break

>>> TypeError: isinstance() arg 2 must be a type or tuple of types

Expected behavior AFAIK in both cases positional validation should allow array to have two elements: 1) [either 'A' or 'B', any string] 2) [either 'A' or 'B', any string or None]

Right now they seem to work more like anyOf (especially #⁠1 where ['A', 'X'] is not one of ['A', 'B']) even though Specs state that:

When this attribute value is an array of schemas and the instance value is an array, each position in the instance array MUST conform to the schema in the corresponding position for this array. This called tuple typing.

github-actions[bot] commented 3 years ago

Stale issue message