def _apply_rebase_ast(self, context, node, op): from . import inheriting parent_ctx = context.get(sd.CommandContextToken) parent_op = parent_ctx.op rebase = next( iter(parent_op.get_subcommands(type=inheriting.RebaseNamedObject))) dropped = rebase.removed_bases added = rebase.added_bases if dropped: node.commands.append( qlast.AlterDropInherit(bases=[ qlast.ObjectRef(module=b.classname.module, name=b.classname.name) for b in dropped ])) for bases, pos in added: if isinstance(pos, tuple): pos_node = qlast.Position(position=pos[0], ref=qlast.ObjectRef( module=pos[1].classname.module, name=pos[1].classname.name)) else: pos_node = qlast.Position(position=pos) node.commands.append( qlast.AlterAddInherit(bases=[ qlast.ObjectRef(module=b.classname.module, name=b.classname.name) for b in bases ], position=pos_node))
def _float_to_path(self, token, context): from edgedb.lang.schema import pointers as s_pointers # make sure that the float is of the type 0.1 parts = token.val.split('.') if not (len(parts) == 2 and parts[0].isdigit() and parts[1].isdigit()): raise EdgeQLSyntaxError(f"Unexpected {token.val!r}", context=token.context) # context for the AST is established manually here return [ qlast.Ptr( ptr=qlast.ObjectRef( name=parts[0], context=token.context, ), direction=s_pointers.PointerDirection.Outbound, context=context, ), qlast.Ptr( ptr=qlast.ObjectRef( name=parts[1], context=token.context, ), direction=s_pointers.PointerDirection.Outbound, context=token.context, ) ]
def _apply_field_ast(self, context, node, op): if op.property == 'spectargets': if op.new_value: node.commands.append(qlast.AlterTarget( targets=[ qlast.ObjectRef(name=t.classname.name, module=t.classname.module) for t in op.new_value ] )) elif op.property == 'target': if op.new_value: node.commands.append(qlast.AlterTarget( targets=[ qlast.ObjectRef( name=op.new_value.classname.name, module=op.new_value.classname.module) ] )) elif op.property == 'source': pass elif op.property == 'search': if op.new_value: v = qlast.Constant(value=str(op.new_value.weight)) self._set_attribute_ast(context, node, 'search_weight', v) else: self._drop_attribute_ast(context, node, 'search_weight') else: super()._apply_field_ast(context, node, op)
def visit_Set(self, node): if node.expr is not None: result = self.visit(node.expr) else: links = [] while node.rptr and (not node.show_as_anchor or self.context.inline_anchors): rptr = node.rptr ptrcls = rptr.ptrcls pname = ptrcls.shortname if isinstance(rptr.target.scls, s_objtypes.ObjectType): target = rptr.target.scls.shortname target = qlast.ObjectRef(name=target.name, module=target.module) else: target = None link = qlast.Ptr(ptr=qlast.ObjectRef(name=pname.name, ), direction=rptr.direction, target=target) if isinstance(ptrcls.source, s_links.Link): link.type = 'property' links.append(link) node = node.rptr.source result = qlast.Path() if node.show_as_anchor and not self.context.inline_anchors: if issubclass(node.show_as_anchor, qlast.Expr): step = node.show_as_anchor() else: step = qlast.ObjectRef(name=node.show_as_anchor) else: step = qlast.ObjectRef(name=node.scls.shortname.name, module=node.scls.shortname.module) result.steps.append(step) result.steps.extend(reversed(links)) if node.shape: result = qlast.Shape(expr=result, elements=[]) for el in node.shape: rptr = el.rptr ptrcls = rptr.ptrcls pn = ptrcls.shortname pn = qlast.ShapeElement(expr=qlast.Path(steps=[ qlast.Ptr(ptr=qlast.ObjectRef(name=pn.name), direction=rptr.direction) ])) result.elements.append(pn) return result
def type_to_ql_typeref(t: s_obj.Object) -> qlast.TypeName: if not isinstance(t, s_types.Collection): result = qlast.TypeName( maintype=qlast.ObjectRef(module=t.name.module, name=t.name.name)) else: result = qlast.TypeName( maintype=qlast.ObjectRef(name=t.schema_name), subtypes=[type_to_ql_typeref(st) for st in t.get_subtypes()]) return result
def typeref_to_ast(t: so.Object) -> ql_ast.TypeName: if not isinstance(t, s_types.Collection): if isinstance(t, so.ObjectRef): name = t.classname else: name = t.name result = ql_ast.TypeName( maintype=ql_ast.ObjectRef(module=name.module, name=name.name)) else: result = ql_ast.TypeName( maintype=ql_ast.ObjectRef(name=t.schema_name), subtypes=[typeref_to_ast(st) for st in t.get_subtypes()]) return result
def edb_base_name(self): base = self.edb_base.name return codegen.generate_source( qlast.ObjectRef( module=base.module, name=base.name, ))
def get_path_prefix(self, end_trim=None): # flatten the path path = [step for psteps in self._context.path for step in psteps] # find the first shadowed root for i, step in enumerate(path): base = step.type if base.shadow: break # trim the rest of the path path = path[i + 1:end_trim] prefix = [qlast.ObjectRef(module=base.module, name=base.short_name)] prefix.extend( qlast.Ptr(ptr=qlast.ObjectRef(name=step.name)) for step in path) return prefix
def _apply_field_ast(self, context, node, op): objtype = context.get(LinkSourceCommandContext) if op.property == 'is_derived': pass elif op.property == 'spectargets': if op.new_value: node.targets = [ qlast.ObjectRef(name=t.classname.name, module=t.classname.module) for t in op.new_value ] elif op.property == 'default': self._encode_default(context, node, op) elif op.property == 'required': node.is_required = op.new_value elif op.property == 'source': pass elif op.property == 'search': if op.new_value: v = qlast.Constant(value=str(op.new_value.weight)) self._set_attribute_ast(context, node, 'search_weight', v) elif op.property == 'target' and objtype: if not node.targets: t = op.new_value node.targets = [utils.typeref_to_ast(t)] else: super()._apply_field_ast(context, node, op)
def reduce_NodeName_Shape(self, *kids): self.val = qlast.Shape(expr=qlast.Path(steps=[ qlast.ObjectRef(name=kids[0].val.name, module=kids[0].val.module, context=kids[0].context) ]), elements=kids[1].val)
def visit_TypeCast(self, node): if node.type.subtypes: typ = qlast.TypeName( maintype=qlast.ObjectRef(name=node.type.maintype), subtypes=[ qlast.ObjectRef(module=stn.module, name=stn.name) for stn in node.type.subtypes ]) else: mtn = node.type.maintype mt = qlast.ObjectRef(module=mtn.module, name=mtn.name) typ = qlast.TypeName(maintype=mt) result = qlast.TypeCast(expr=self.visit(node.expr), type=typ) return result
def reduce_VIEW_Identifier_TurnstileBlob(self, *kids): self.val = esast.ViewDeclaration( name=kids[1].val, attributes=[ esast.Attribute(name=qlast.ObjectRef(name='expr'), value=kids[2].val) ])
def _prepare_field(self, node): path = self._context.path[-1] include_base = self._context.include_base[-1] is_top = self._is_top_level_field(node) spath = self._context.path[-1] prevt, target = self._get_parent_and_current_type() # insert normal or specialized link steps = [] if include_base: base = spath[0].type steps.append( qlast.ObjectRef(module=base.module, name=base.short_name)) steps.append(qlast.Ptr(ptr=qlast.ObjectRef(name=node.name))) return is_top, path, prevt, target, steps
def visit_TypeRef(self, node): # Bare TypeRef only appears as rhs of IS [NOT] and is always # an object type reference. mtn = node.maintype result = qlast.Path( steps=[qlast.ObjectRef(module=mtn.module, name=mtn.name)]) return result
def _get_ast(self, context): value = self.new_value new_value_empty = \ (value is None or (isinstance(value, collections.Container) and not value)) old_value_empty = \ (self.old_value is None or (isinstance(self.old_value, collections.Container) and not self.old_value)) if new_value_empty and not old_value_empty: op = qlast.DropAttributeValue( name=qlast.ObjectRef(module='', name=self.property)) return op if new_value_empty and old_value_empty: return if isinstance(value, s_expr.ExpressionText): value = edgeql.parse(str(value)) elif utils.is_nontrivial_container(value): value = qlast.Tuple( elements=[qlast.Constant(value=el) for el in value]) elif isinstance(value, nlang.WordCombination): forms = value.as_dict() if len(forms) > 1: items = [] for k, v in forms.items(): items.append( (qlast.Constant(value=k), qlast.Constant(value=v))) value = qlast.Mapping(items=items) else: value = qlast.Constant(value=str(value)) else: value = qlast.Constant(value=value) as_expr = isinstance(value, qlast.ExpressionText) op = qlast.CreateAttributeValue(name=qlast.ObjectRef( module='', name=self.property), value=value, as_expr=as_expr) return op
def reduce_ARRAY_LANGBRACKET_NonArrayTypeName_OptDimensions_RANGBRACKET( self, *kids): subtype = kids[2].val dimensions = kids[3].val self.val = qlast.TypeName( maintype=qlast.ObjectRef(name='array'), subtypes=[subtype], dimensions=dimensions, )
def _set_attribute_ast(self, context, node, name, value): if isinstance(value, expr.ExpressionText): value = qlast.ExpressionText(expr=str(value)) as_expr = isinstance(value, qlast.ExpressionText) name_ref = qlast.ObjectRef(name=name, module='') node.commands.append( qlast.CreateAttributeValue(name=name_ref, value=value, as_expr=as_expr))
def _get_ast(self, context): metaclass = self.get_schema_metaclass() astnode = self._get_ast_node(context) if isinstance(self.classname, sn.Name): if hasattr(metaclass, 'get_shortname'): nname = metaclass.get_shortname(self.classname) else: nname = self.classname name = qlast.ObjectRef(module=nname.module, name=nname.name) else: name = qlast.ObjectRef(module='', name=self.classname) if astnode.get_field('name'): op = astnode(name=name) else: op = astnode() self._apply_fields_ast(context, op) return op
def reduce_CreateViewShortStmt(self, *kids): r"""%reduce \ CREATE VIEW NodeName TURNSTILE Expr \ """ self.val = qlast.CreateView(name=kids[2].val, commands=[ qlast.CreateAttributeValue( name=qlast.ObjectRef(name='expr'), value=kids[4].val, as_expr=True) ])
def _apply_field_ast(self, context, node, op): if op.property == 'target': if op.new_value: node.commands.append( qlast.AlterTarget(targets=[ qlast.ObjectRef(name=op.new_value.classname.name, module=op.new_value.classname.module) ])) elif op.property == 'source': pass else: super()._apply_field_ast(context, node, op)
def visit_Argument(self, node, *, get_path_prefix): op = ast.ops.EQ name_parts = node.name _, target = self._get_parent_and_current_type() name = get_path_prefix() name.append(qlast.Ptr(ptr=qlast.ObjectRef(name=name_parts))) name = qlast.Path(steps=name) value = self.visit(node.value) # potentially need to cast the 'name' side into a <str>, so as # to be compatible with the 'value' typename = target.get_field_type(name_parts).short_name if (typename != 'str' and gt.EDB_TO_GQL_SCALARS_MAP[typename] in {GraphQLString, GraphQLID}): name = qlast.TypeCast( expr=name, type=qlast.TypeName(maintype=qlast.ObjectRef(name='str')), ) return qlast.BinOp(left=name, op=op, right=value)
def _apply_field_ast(self, context, node, op): if op.property == 'name': pass elif op.property == 'bases': node.bases = [ qlast.ObjectRef(name=b.classname.name, module=b.classname.module) for b in op.new_value ] elif op.property == 'mro': pass elif op.property == 'is_abstract': node.is_abstract = op.new_value elif op.property == 'is_final': node.is_final = op.new_value else: super()._apply_field_ast(context, node, op)
def _apply_field_ast(self, context, node, op): if op.property == 'type': tp = op.new_value if isinstance(tp, s_types.Collection): maintype = tp.schema_name stt = tp.get_subtypes() for st in stt: eltype = qlast.ObjectRef(module=st.module, name=st.name) tnn = qlast.TypeName(maintype=maintype, subtypes=[eltype]) else: tnn = qlast.TypeName(maintype=tp) node.type = tnn else: super()._apply_field_ast(context, node, op)
def _get_ast(self, context): astnode = self._get_ast_node(context) metaclass = self.get_schema_metaclass() if hasattr(metaclass, 'get_shortname'): new_name = metaclass.get_shortname(self.new_name) else: new_name = self.new_name if new_name != self.new_name: # Derived name name_b32 = base64.b32encode(self.new_name.name.encode()).decode() new_nname = '__b32_' + name_b32.replace('=', '_') new_name = sn.Name(module=self.new_name.module, name=new_nname) else: new_name = self.new_name ref = qlast.ObjectRef(name=new_name.name, module=new_name.module) return astnode(new_name=ref)
def compile_result_clause( result: qlast.Base, *, view_scls: typing.Optional[s_types.Type]=None, view_rptr: typing.Optional[context.ViewRPtr]=None, view_name: typing.Optional[s_name.SchemaName]=None, result_alias: typing.Optional[str]=None, ctx: context.ContextLevel) -> irast.Set: with ctx.new() as sctx: sctx.clause = 'result' if sctx.stmt is ctx.toplevel_stmt: sctx.toplevel_clause = sctx.clause sctx.expr_exposed = True if isinstance(result, qlast.Shape): result_expr = result.expr shape = result.elements else: result_expr = result shape = None if result_alias: stmtctx.declare_view(result_expr, alias=result_alias, ctx=sctx) result_expr = qlast.Path( steps=[qlast.ObjectRef(name=result_alias)] ) expr = setgen.ensure_set( dispatch.compile(result_expr, ctx=sctx), ctx=sctx) result = compile_query_subject( expr, shape=shape, view_rptr=view_rptr, view_name=view_name, result_alias=result_alias, view_scls=view_scls, compile_views=ctx.stmt is ctx.toplevel_stmt, ctx=sctx) ctx.partial_path_prefix = result return result
def _visit_query(self, node): # populate input variables with defaults, where applicable if node.variables: self.visit(node.variables) # base Query needs to be configured specially base = self._context.gql_schema.get('Query', modules=self._context.modules) # special treatment of the selection_set, different from inner # recursion query = qlast.SelectQuery(result=qlast.Shape(expr=qlast.Path( steps=[qlast.ObjectRef(name='Query', module='graphql')]), elements=[]), ) self._context.fields.append({}) self._context.path.append([Step(None, base)]) query.result.elements = self.visit(node.selection_set) self._context.fields.pop() self._context.path.pop() return query
def get_path_prefix(): path = self._context.path[0] return [ qlast.ObjectRef(module=path[1].module, name=path[1].short_name) ]
def visit_Field(self, node): if self._is_duplicate_field(node): return is_top, path, prevt, target, steps = \ self._prepare_field(node) json_mode = False # determine if there needs to be extra subqueries if not prevt.dummy and target.dummy: json_mode = True # this is a special introspection type eql, shape, filterable = target.get_template() spec = qlast.ShapeElement( expr=qlast.Path(steps=[ qlast.Ptr(ptr=qlast.ObjectRef( name=node.alias or node.name)) ]), compexpr=eql, ) elif prevt.is_field_shadowed(node.name): if prevt.has_native_field(node.name) and not node.alias: spec = filterable = shape = qlast.ShapeElement( expr=qlast.Path(steps=steps), ) else: prefix = qlast.Path(steps=self.get_path_prefix(-1)) eql, shape, filterable = prevt.get_field_template( node.name, parent=prefix, has_shape=bool(node.selection_set)) spec = qlast.ShapeElement( expr=qlast.Path(steps=[ qlast.Ptr(ptr=qlast.ObjectRef( # this is already a sub-query name=node.alias or node.name)) ]), compexpr=eql) else: # if the parent is NOT a shadowed type, we need an explicit SELECT eql, shape, filterable = target.get_template() spec = qlast.ShapeElement( expr=qlast.Path(steps=[ qlast.Ptr(ptr=qlast.ObjectRef( # this is already a sub-query name=node.alias or node.name)) ]), compexpr=eql) if node.selection_set is not None: if json_mode: pass else: # a single recursion target, so we can process # selection set now self._context.fields.append({}) vals = self.visit(node.selection_set) self._context.fields.pop() if shape: shape.elements = vals if filterable: filterable.where = self._visit_path_where(node.arguments) path.pop() return spec
def reduce_DUNDERTYPE(self, *kids): self.val = qlast.ObjectRef(name=kids[0].val)
def reduce_DROP_MODULE_ModuleName(self, *kids): self.val = qlast.DropModule( name=qlast.ObjectRef(module=None, name='.'.join(kids[2].val)))