如何仅确保匹配特定模式的patternProperties

时间:2016-08-04 15:46:48

标签: python

我正在使用python模块验证来验证dicts / yaml配置。

鉴于以下架构,我想匹配匹配“^ [0-9x] {3} $”的任何键数,并使用其他模式验证该值。

SCHEMA = {
    "type": "object",
    "patternProperties": {
        "^[0-9x]{3}$": {
            "type": "string",
            "pattern": "^somepattern$"
        }
    }
}

这项工作到目前为止,但我现在想要的是:

SCHEMA = {
    "type": "object",
    "additionalProperties": False,
    "patternProperties": {
        "^[0-9x]{3}$": {
            "type": "string",
            "pattern": "^somePattern$"
        }
    }
}

这不会像我预期的那样工作,似乎如果存在additionalProperties,则不会评估patternProperties导致错误,即不允许在属性中未指定任何键。

那么我怎么能确保配置中的每个键都遵循那个确切的模式(“^ [0-9x] {3} $”)?

示例配置:

{
    '5xx': 'someValidValue',
    'x9x': 'someValidValue'
}

- >应该测试真实

{
    '5xx': 'someValidValue',
    'foobar': 'someValidValue', #this one should fail
    'baz': 'someValidValue',    #this one, too
    'x9x1': 'someValidValue',   #this one, too
    'x9x': 'someValidValue'
}

- >应该测试错误

我尝试“定义自己的类型”,就像文档所说,通过在类型块中给出一个模式:

...
"type": { "pattern": "^[0-9x]{3}$" }
...

但是它实际上测试了该模式的值,所以要么我做错了,要么文档错误(或两者都有)。

注意:我有(并希望)使用validictory,因为它是我正在使用的某些第三方库的设置模块。

编辑:好的,在smarx的回答之后,我想知道这里出了什么问题,经过几次我认为搞砸了一些事情我终于找不到我的计划有什么问题了。但我想我发现了问题:

这是一个更像生产的例子,比如我正在构建的模式生成器给我(减少到必要的):

import validictory

data = {
    'tests': {
        'default': {
            'timeout_status': 'amber',
            'sensor': 'http',
            'modules': {
                'statuscode': {'200': 'red'}
            }
        },
        'tgoogle': {
            'sensor': 'http',
            'modules': {
                'statuscode': {
                    '200': 'green',
                    'foo': 'bar',
                },
            },
            'timeout_status': 'amber'
        }
    }, 
    # ... more besides key tests
}

SCHEMA = {
    'type': 'object',
    'properties': {
        'tests': {
            'additionalProperties': {
                'type': 'object',
                'properties': {
                    'timeout_status': {
                        'enum': ['amber', 'yellow', 'green', 'red'],
                        'type': 'string'
                    }, 
                    'sensor': {
                        'pattern': '^\S+$',
                        'type': 'string'
                    }, 
                    'modules': {
                        'additionalProperties': False,
                        'type': 'object',
                        'properties': {
                            'statuscode': {
                                'additionalProperties': False,
                                'required': False,
                                'type': 'object',
                                'patternProperties': {
                                    '^[0-9x]{3}': {
                                        'enum': ['amber', 'yellow', 'green', 'red'],
                                        'type': 'string',
                                    }
                                }
                            }
                            # ... more available test modules
                        }
                    }
                }
            },
            'type': 'object'
        },
        # ... more besides key tests
    }
}

validictory.validate(data, SCHEMA) #<- this fails as expected at foo
#validictory.validate(data, SCHEMA, fail_fast=False) #<- this throws the exception from below

- &GT;这按预期工作

我认为这里出了两件大事:

  1. 我有一个太旧的验证lib安装,我认为这是原始missbehavior的原因 - &gt;永远不要使用debian软件包,即使是debian8,他们来自石器时代 - .-更好地使用pip
  2. 升级到1.0.2后,我收到以下错误:

    Traceback (most recent call last):
      File "./test.py", line 71, in <module>
        validictory.validate(should_work, SCHEMA, fail_fast=False) # no exception
      File "/usr/local/lib/python2.7/dist-packages/validictory/__init__.py", line 43, in validate
        return v.validate(data, schema)
      File "/usr/local/lib/python2.7/dist-packages/validictory/validator.py", line 590, in validate
        self.__validate("data", {"data": data}, schema, '<obj>')
      File "/usr/local/lib/python2.7/dist-packages/validictory/validator.py", line 632, in __validate
        validator(data, fieldname, schema, path, newschema.get(schemaprop))
      File "/usr/local/lib/python2.7/dist-packages/validictory/validator.py", line 285, in validate_properties
        path + '.' + property)
      File "/usr/local/lib/python2.7/dist-packages/validictory/validator.py", line 632, in __validate
        validator(data, fieldname, schema, path, newschema.get(schemaprop))
      File "/usr/local/lib/python2.7/dist-packages/validictory/validator.py", line 398, in validate_additionalProperties
        self.__validate(eachProperty, value, additionalProperties, path)
      File "/usr/local/lib/python2.7/dist-packages/validictory/validator.py", line 632, in __validate
        validator(data, fieldname, schema, path, newschema.get(schemaprop))
      File "/usr/local/lib/python2.7/dist-packages/validictory/validator.py", line 285, in validate_properties
        path + '.' + property)
      File "/usr/local/lib/python2.7/dist-packages/validictory/validator.py", line 632, in __validate
        validator(data, fieldname, schema, path, newschema.get(schemaprop))
      File "/usr/local/lib/python2.7/dist-packages/validictory/validator.py", line 285, in validate_properties
        path + '.' + property)
      File "/usr/local/lib/python2.7/dist-packages/validictory/validator.py", line 632, in __validate
        validator(data, fieldname, schema, path, newschema.get(schemaprop))
      File "/usr/local/lib/python2.7/dist-packages/validictory/validator.py", line 398, in validate_additionalProperties
        self.__validate(eachProperty, value, additionalProperties, path)
      File "/usr/local/lib/python2.7/dist-packages/validictory/validator.py", line 599, in __validate
        (fieldname, type(schema).__name__))
    validictory.validator.SchemaError: Type for field 'foo' must be 'dict', got: 'bool'
    

    实际上我称之为有效:

    validictory.validate(data, SCHEMA, fail_fast=False)
    

    删除fail_fast = False后,一切都按预期工作,所以:

    1. 也许fail_fast = False有错误? (我实际上在使用之前已成功测试了它,但使用了更简单的模式)
    2. - &GT;如果有人看到我的架构出现任何问题,可能会破坏验证码,我很乐意知道。

      - &GT;如果没有,我希望我能用这些提示节省一些时间

1 个答案:

答案 0 :(得分:0)

我无法重现您的问题。这段代码对我来说是预期的(Python 3.5.1,validictory 1.0.2),除非我误解了你的问题?

import validictory

should_work = {
    '5xx': 'someValidValue',
    'x9x': 'someValidValue'
}

should_not_work = {
    '5xx': 'someValidValue',
    'foobar': 'someValidValue', #this one should fail
    'baz': 'someValidValue',    #this one, too
    'x9x1': 'someValidValue',   #this one, too
    'x9x': 'someValidValue'
}

SCHEMA = {
    "type": "object",
    "additionalProperties": False,
    "patternProperties": {
        "^[0-9x]{3}$": {
            "type": "string",
            "pattern": "^someValidValue$"
        },
    },
}

validictory.validate(should_work, SCHEMA) # no exception

validictory.validate(should_not_work, SCHEMA)
# validictory.validator.FieldValidationError ... contains additional property 'baz' not defined by 'properties' or 'patternProperties' and additionalProperties  is False