def _parse_subject_constraints(self, subject, subjdecl): # Perform initial collection of constraints defined in subject context. # At this point all referenced constraints should be fully initialized. for constrdecl in subjdecl.constraints: attrs = {a.name.name: a.value for a in constrdecl.fields} assert 'subject' not in attrs # TODO: Add proper validation constr_name = self._get_ref_name(constrdecl.name) if constrdecl.args: args = [ qlcodegen.generate_source(arg, pretty=False) for arg in constrdecl.args ] else: args = [] modaliases = {None: subject.get_name(self._schema).module} self._schema, c, _ = \ s_constr.Constraint.create_concrete_constraint( self._schema, subject, name=constr_name, is_abstract=constrdecl.delegated, sourcectx=constrdecl.context, subjectexpr=constrdecl.subject, args=args, modaliases=modaliases, ) self._schema = subject.add_constraint(self._schema, c)
def _parse_field_setters(self, scls, field_decls: typing.List[s_ast.Field]): fields = type(scls).get_fields() updates = {} for field_decl in field_decls: fieldname = field_decl.name.name attrfield = fields.get(fieldname) if attrfield is None or not attrfield.allow_ddl_set: raise errors.SchemaError(f'unexpected field {fieldname}', context=field_decl.context) if issubclass(attrfield.type, s_expr.ExpressionText): updates[fieldname] = qlcodegen.generate_source( field_decl.value) else: updates[fieldname] = qlcompiler.evaluate_ast_to_python_val( field_decl.value, self._schema, modaliases=self._mod_aliases) if updates: self._schema = scls.update(self._schema, updates)
def edb_base_name(self): base = self.edb_base.get_name(self.edb_schema) return codegen.generate_source( qlast.ObjectRef( module=base.module, name=base.name, ))
def _init_constraints(self, constraints): for constraint, decl in constraints.items(): attrs = {a.name.name: a.value for a in decl.attributes} assert 'subject' not in attrs # TODO: Add proper validation assert 'subjectexpr' not in attrs # TODO: Add proper validation expr = attrs.pop('expr', None) if expr is not None: constraint.expr = s_expr.ExpressionText( qlcodegen.generate_source(expr)) subjexpr = decl.subject if subjexpr is not None: constraint.subjectexpr = s_expr.ExpressionText( qlcodegen.generate_source(subjexpr)) paramnames, paramdefaults, paramtypes, paramkinds, variadic = \ s_func.parameters_from_ast(decl, self._mod_aliases, self._schema) for pname, pdefault, ptype in zip(paramnames, paramdefaults, paramtypes): if pname is not None: raise s_err.SchemaDefinitionError( 'constraints do not support named parameters', context=decl.context) if pdefault is not None: raise s_err.SchemaDefinitionError( 'constraints do not support parameters ' 'with defaults', context=decl.context) if ptype is None: raise s_err.SchemaDefinitionError('untyped parameter', context=decl.context) constraint.paramtypes = paramtypes constraint.varparam = variadic
def _init_constraints(self, constraints): for constraint, decl in constraints.items(): attrs = {a.name.name: a.value for a in decl.fields} assert 'subject' not in attrs # TODO: Add proper validation assert 'subjectexpr' not in attrs # TODO: Add proper validation expr = attrs.pop('expr', None) if expr is not None: self._schema = constraint.set_field_value( self._schema, 'expr', s_expr.ExpressionText(qlcodegen.generate_source(expr))) subjexpr = decl.subject if subjexpr is not None: self._schema = constraint.set_field_value( self._schema, 'subjectexpr', s_expr.ExpressionText(qlcodegen.generate_source(subjexpr))) self._schema, params = s_func.FuncParameterList.from_ast( self._schema, decl, self._mod_aliases, func_fqname=constraint.get_name(self._schema)) for param in params.objects(self._schema): if param.get_kind(self._schema) is ft.ParameterKind.NAMED_ONLY: raise errors.InvalidConstraintDefinitionError( 'named only parameters are not allowed ' 'in this context', context=decl.context) if param.get_default(self._schema) is not None: raise errors.InvalidConstraintDefinitionError( 'constraints do not support parameters ' 'with defaults', context=decl.context) self._schema = constraint.set_field_value(self._schema, 'params', params)
def rewrite_refs(expr, callback): """Rewrite class references in EdgeQL expression.""" tree = qlparser.parse_fragment(expr) def _cb(node): if isinstance(node, qlast.ObjectRef): name = sn.Name(name=node.name, module=node.module) upd = callback(name) if name != upd: node.name = upd.name node.module = upd.module ast.find_children(tree, _cb) return qlcodegen.generate_source(tree, pretty=False)
def from_ast(cls, schema, modaliases, num: int, astnode) -> 'ParameterDesc': paramd = None if astnode.default is not None: paramd = codegen.generate_source(astnode.default) paramt = utils.resolve_typeref( utils.ast_to_typeref(astnode.type, modaliases=modaliases, schema=schema), schema) if astnode.kind is ft.ParameterKind.VARIADIC: paramt = s_types.Array.from_subtypes(schema, (paramt, )) return cls(num=num, name=astnode.name, type=paramt, typemod=astnode.typemod, kind=astnode.kind, default=paramd)
def parameters_from_ast(astnode, modaliases, schema): paramdefaults = [] paramnames = [] paramtypes = [] paramkinds = [] variadic = None for argi, arg in enumerate(astnode.args): paramnames.append(arg.name) paramkinds.append(arg.qualifier) default = None if arg.default is not None: default = codegen.generate_source(arg.default) paramdefaults.append(default) paramtypes.append(utils.ast_to_typeref( arg.type, modaliases=modaliases, schema=schema)) if arg.qualifier == qlast.SetQualifier.VARIADIC: variadic = argi return paramnames, paramdefaults, paramtypes, paramkinds, variadic
def _cmd_tree_from_ast(cls, astnode, context, schema): cmd = super()._cmd_tree_from_ast(astnode, context, schema) modaliases = context.modaliases paramnames, paramdefaults, paramtypes, paramkinds, variadic = \ parameters_from_ast(astnode, modaliases, schema) if variadic is not None: cmd.add( sd.AlterObjectProperty(property='varparam', new_value=variadic)) cmd.add( sd.AlterObjectProperty(property='paramnames', new_value=paramnames)) cmd.add( sd.AlterObjectProperty(property='paramtypes', new_value=paramtypes)) cmd.add( sd.AlterObjectProperty(property='paramkinds', new_value=paramkinds)) cmd.add( sd.AlterObjectProperty(property='paramdefaults', new_value=paramdefaults)) cmd.add( sd.AlterObjectProperty(property='returntype', new_value=utils.ast_to_typeref( astnode.returning, modaliases=modaliases, schema=schema))) cmd.add( sd.AlterObjectProperty(property='aggregate', new_value=astnode.aggregate)) cmd.add( sd.AlterObjectProperty(property='set_returning', new_value=astnode.set_returning)) if astnode.initial_value is not None: iv = codegen.generate_source(astnode.initial_value) cmd.add( sd.AlterObjectProperty(property='initial_value', new_value=iv)) if astnode.code is not None: cmd.add( sd.AlterObjectProperty(property='language', new_value=astnode.code.language)) if astnode.code.from_name is not None: cmd.add( sd.AlterObjectProperty(property='from_function', new_value=astnode.code.from_name)) else: cmd.add( sd.AlterObjectProperty(property='code', new_value=astnode.code.code)) return cmd
def _parse_subject_constraints(self, subject, subjdecl): # Perform initial collection of constraints defined in subject context. # At this point all referenced constraints should be fully initialized. constr = {} for constrdecl in subjdecl.constraints: attrs = {a.name.name: a.value for a in constrdecl.attributes} assert 'subject' not in attrs # TODO: Add proper validation constr_name = self._get_ref_name(constrdecl.name) constr_base = self._schema.get(constr_name, type=s_constr.Constraint, module_aliases=self._mod_aliases) constraint = constr_base.derive(self._schema, subject) constraint.is_abstract = constrdecl.delegated constraint.acquire_ancestor_inheritance(self._schema) constraint.sourcectx = constrdecl.context if constrdecl.args: args = [ edgeql_codegen.generate_source(arg, pretty=False) for arg in constrdecl.args ] else: args = [] subjectexpr = constrdecl.subject if subjectexpr is not None: constraint.set_attribute( 'subjectexpr', s_constr.Constraint.normalize_constraint_expr( self._schema, {}, subjectexpr, subject=subject, constraint=constraint), source_context=constrdecl.subject.context, ) s_constr.Constraint.process_specialized_constraint( self._schema, constraint, args) # There can be only one specialized constraint per constraint # class per subject. At this point all placeholders have been # folded, so it is possible to merge the constraints consistently # by merging their final exprs. # try: prev = constr[constraint.bases[0].name] except KeyError: constr[constraint.bases[0].name] = constraint else: constraint.merge(prev, schema=self._schema) constraint.merge_localexprs(prev, schema=self._schema) constr[constraint.bases[0].name] = constraint for c in constr.values(): # Note that we don't do finalization for the constraint # here, since it's possible that it will be further used # in a merge of it's subject. # self._schema.add(c) subject.add_constraint(c)
def _parse_ptr_default(self, expr, source, ptr): """Set the default value for a pointer.""" if not isinstance(expr, edgeql.ast.SelectQuery): expr = edgeql.ast.Constant(value=self._get_literal_value(expr)) ptr.default = s_expr.ExpressionText(qlcodegen.generate_source(expr))