diff -r a8769b752299 -r 6c2d57d1b6de schema.py --- a/schema.py Mon Jun 16 10:08:32 2014 +0200 +++ b/schema.py Mon Apr 28 14:11:23 2014 +0200 @@ -1017,8 +1017,56 @@ def finalize(self): super(CubicWebSchema, self).finalize() + self.finalize_computed_attributes() self.finalize_computed_relations() + def finalize_computed_attributes(self): + """Check consistency of computed attributes types""" + analyzer = ETypeResolver(self) + for relation in self.relations(): + for rdef in relation.rdefs.itervalues(): + if rdef.final and rdef.formula is not None: + computed_etype = rdef.subject.type + computed_attr = rdef.rtype + rqlst = parse(rdef.formula) + if len(rqlst.children) != 1: + raise BadSchemaDefinition( + 'computed attribute %(attr)s on %(etype)s: ' + 'can not use UNION in formula %(form)r' % + dict(attr=computed_attr, + etype=computed_etype, + form=rdef.formula)) + select = rqlst.children[0] + analyzer.visit(select) + if len(select.selection) != 1: + raise BadSchemaDefinition( + 'computed attribute %(attr)s on %(etype)s: ' + 'can only select one term in formula %(form)r' % + dict(attr=computed_attr, + etype=computed_etype, + form=rdef.formula)) + term = select.selection[0] + types = set(term.get_type(sol) for sol in select.solutions) + if len(types) != 1: + raise BadSchemaDefinition( + 'computed attribute %(attr)s on %(etype)s: ' + 'multiple possible types (%(types)s) for formula %(form)s' % + dict(attr=computed_attr, + etype=computed_etype, + types=list(types), + form=rdef.formula)) + computed_type = types.pop() + expected_type = rdef.object.type + if computed_type != expected_type: + raise BadSchemaDefinition( + 'computed attribute %(attr)s on %(etype)s: ' + 'computed attribute type (%(comp_type)s) mismatch with ' + 'specified type (%(attr_type)s)' % + dict(attr=computed_attr, + etype=computed_etype, + comp_type=computed_type, + attr_type=expected_type)) + def finalize_computed_relations(self): """Build relation definitions for computed relations