1 """
2 Meta information validation.
3
4 The idea is that you define certain assertions about the meta information
5 of a given object type. Defined assertions are
6
7 - MetaExists -- a key is present
8 - MetaIsAtomic -- a key is present and a "leaf", i.e., has a single value
9 - MetaAtomicExistsOnSelf -- a key is present even without meta inheritance,
10 and has a single value
11
12 Validators are usually built using model descriptions. These are enumerations
13 of meta keys, separated by commata, with an optional code in parenteses.
14 Whitespace is ignored. Codes allowed in parens are:
15
16 - empty (default): plain existence
17 - !: atomic existance on self
18 - 1: atomic existance
19
20 An example for a valid model description:
21 "publisher.name,creator.email(), identifier (!), dateUpdated(1)"
22
23 These model descriptions can come in metaModel attributes of structures.
24 If they are, you can use the validateStructure function below to validate
25 an entire structure tree.
26 """
27
28
29
30
31
32
33
34 from gavo import utils
35 from gavo.base import meta
51
70
78
91
98
116
117
118 _assertionCodes = {
119 (): MetaExists,
120 ('!',): MetaAtomicExistsOnSelf,
121 ('1',): MetaIsAtomic,
122 }
127 from pyparsing import (Literal, Optional, StringEnd, Suppress,
128 Word, ZeroOrMore, alphas)
129
130 with utils.pyparsingWhitechars(" \t"):
131 metaKey = Word(alphas+".")
132 modChar = Literal('!') | '1'
133 modifier = Suppress('(') + Optional(modChar) + Suppress(')')
134 assertion = metaKey("key")+Optional(modifier)("mod")
135 model = assertion + ZeroOrMore(
136 Suppress(',') + assertion ) + StringEnd()
137
138 def _buildAssertion(s, p, toks):
139 key = str(toks["key"])
140 mod = tuple(toks.get("mod", ()))
141 return _assertionCodes[mod](key)
142
143 assertion.addParseAction(_buildAssertion)
144 model.addParseAction(lambda s,p,toks: MetaValidator(toks))
145 return model
146
149 """returns a MetaValidator for a model description.
150
151 model descriptions are covered in the module docstring.
152 """
153 return utils.pyparseString(_getModelGrammar(), modelDescr)[0]
154
165
168 """does a meta validation for a base.Structure.
169
170 This works by traversing the children of the structure, looking for
171 nodes with a metaModel attribute. For all these, a validation is
172 carried out. The first node failing the validation determines the
173 return value.
174
175 The function raises a MetaValidationError if aStruct is invalid.
176 """
177 _validateStructNode(aStruct)
178 for s in aStruct.iterChildren():
179 _validateStructNode(s)
180