为密钥类型验证获取更好的Voluptuous Schema错误消息?

时间:2017-08-23 18:51:30

标签: python validation key schema voluptuous

我有一个看起来像这样的架构(例子):

Schema({
    Any(str, unicode): [{
        Required('first_name'): [Any(str, unicode)],
        Required('age'): Any('int32', 'double'),
        Required('something'): Any(int, long, float, str, unicode)
    }]
})

如果我传递一个int(让我们说42)作为键(Any(str, unicode)),我得到:

<class 'voluptuous.error.Invalid'> : extra keys not allowed @ data[42]. Got ["my_value"]

这并不能很好地代表我的错误,因为它甚至没有告诉我们问题实际上是密钥的类型。值类型的错误是完美的,如下所示:expected str for dictionary value @ data[0]["my_key"]. Got 42

是否有办法使用voluptuous' Schema获得更清晰的密钥类型验证消息,如此?

expected str for dictionary key type. Got 42

PS:或者可能是我的Schema不正确?我的目标是创建一个字典,其中键是字符串或unicode(这是一个示例),值是具有特定键值的字典列表。

更新

我尝试将密钥验证放在另一个Schema中,以获取正确的错误消息,如下所示:

KEY_SCHEMA = Schema(Any(str, unicode))

def validate_key(my_key):
    KEY_SCHEMA (my_key) # Here the correct error/message is raised

Schema({
    validate_key: [{
        Required('first_name'): [Any(str, unicode)],
        Required('age'): Any('int32', 'double'),
        Required('something'): Any(int, long, float, str, unicode)
    }]
})

我从KEY_SCHEMA收到的错误消息是&#34;确定&#34;我可以执行try/except raise输出更好的错误消息,但它会被主Schema捕获,并且会再次返回与之前相同的错误。

1 个答案:

答案 0 :(得分:1)

我遇到了完全相同的问题。这不是关于你的模式,而是关于淫荡的方式。

因为您为字典键定义了Schema而不是静态值,所以它允许字典包含与该模式匹配的多个键。父模式的额外参数是False(默认值),这意味着任何额外的元素(任何与您的内部模式不匹配的键)将不被接受(这很好,否则您无法确保所有键根据您的内部架构进行验证)。这是问题,extra = False条件优先于内部模式的非验证。然后将整数键视为额外键,因为它在被视为无效之前与架构不匹配。验证具有相同模式的多个密钥不如在丰富的值验证中有效和明确。

话虽这么说,我最终得到了一个(肮脏的)解决方案。在打印为额外参数之前,我只想输出一条消息,说明关键模式在给定键上不匹配。我通过定义密钥验证的函数来做同样的事情。此函数会自动验证密钥,如果没有,则会输出错误消息。提高无效将触发额外的参数错误消息,所以我之前退出我的程序(它符合我的需要,但对其他任何人来说都不是这样)。

在你的情况下,它可能是这样的:

KEY_SCHEMA = Schema(Any(str, unicode))

def validate_key(my_key):
    if type(my_key) is not str and type(my_key) is not unicode:
        logger.error("{} is not a str or unicode. Aborting.") # if you use the logger library
        sys.exit(1) # need to import sys
    return KEY_SCHEMA (my_key)

Schema({
    validate_key: [{
        Required('first_name'): [Any(str, unicode)],
        Required('age'): Any('int32', 'double'),
        Required('something'): Any(int, long, float, str, unicode)
    }]
})