Example #1
0
def get_schema_object(
        name: Union[str, qlast.BaseObjectRef],
        module: Optional[str] = None,
        *,
        item_type: Optional[Type[s_obj.Object]] = None,
        condition: Optional[Callable[[s_obj.Object], bool]] = None,
        label: Optional[str] = None,
        ctx: context.ContextLevel,
        srcctx: Optional[parsing.ParserContext] = None) -> s_obj.Object:

    if isinstance(name, qlast.ObjectRef):
        if srcctx is None:
            srcctx = name.context
        module = name.module
        name = name.name
    elif isinstance(name, qlast.AnyType):
        return s_pseudo.PseudoType.get(ctx.env.schema, 'anytype')
    elif isinstance(name, qlast.AnyTuple):
        return s_pseudo.PseudoType.get(ctx.env.schema, 'anytuple')
    elif isinstance(name, qlast.BaseObjectRef):
        raise AssertionError(f"Unhandled BaseObjectRef subclass: {name!r}")

    if module:
        name = sn.Name(name=name, module=module)

    elif isinstance(name, str):
        view = _get_type_variant(name, ctx)
        if view is not None:
            return view

    try:
        stype = ctx.env.get_track_schema_object(
            name=name,
            modaliases=ctx.modaliases,
            type=item_type,
            condition=condition,
            label=label,
        )

    except errors.QueryError as e:
        s_utils.enrich_schema_lookup_error(e,
                                           name,
                                           modaliases=ctx.modaliases,
                                           schema=ctx.env.schema,
                                           item_type=item_type,
                                           condition=condition,
                                           context=srcctx)
        raise

    view = _get_type_variant(stype.get_name(ctx.env.schema), ctx)
    if view is not None:
        return view
    elif stype == ctx.defining_view:
        # stype is the view in process of being defined and as such is
        # not yet a valid schema object
        raise errors.SchemaDefinitionError(
            f'illegal self-reference in definition of {name!r}',
            context=srcctx)
    else:
        return stype
Example #2
0
def get_schema_object(
        name: Union[str, qlast.BaseObjectRef],
        module: Optional[str] = None,
        *,
        item_types: Tuple[s_obj.ObjectMeta, ...] = (),
        condition: Optional[Callable[[s_obj.Object], bool]] = None,
        label: Optional[str] = None,
        ctx: context.ContextLevel,
        srcctx: Optional[parsing.ParserContext] = None) -> s_obj.Object:

    if isinstance(name, qlast.ObjectRef):
        if srcctx is None:
            srcctx = name.context
        module = name.module
        name = name.name
    elif isinstance(name, qlast.AnyType):
        return s_pseudo.Any.instance()
    elif isinstance(name, qlast.AnyTuple):
        return s_pseudo.AnyTuple.instance()
    elif isinstance(name, qlast.BaseObjectRef):
        raise AssertionError(f"Unhandled BaseObjectRef subclass: {name!r}")

    if module:
        name = sn.Name(name=name, module=module)

    elif isinstance(name, str):
        view = ctx.aliased_views.get(name)
        if view is not None:
            ctx.must_use_views.pop(view, None)
            return view

    try:
        stype = ctx.env.get_track_schema_object(
            name=name,
            modaliases=ctx.modaliases,
            type=item_types,
            condition=condition,
            label=label,
        )

    except errors.QueryError as e:
        s_utils.enrich_schema_lookup_error(e,
                                           name,
                                           modaliases=ctx.modaliases,
                                           schema=ctx.env.schema,
                                           item_types=item_types,
                                           condition=condition,
                                           context=srcctx)
        raise

    view = ctx.aliased_views.get(stype.get_name(ctx.env.schema))
    if view is not None:
        ctx.must_use_views.pop(view, None)
        return view
    else:
        return stype
Example #3
0
def get_schema_object(
        name: typing.Union[str, qlast.BaseObjectRef],
        module: typing.Optional[str] = None,
        *,
        item_types: typing.Optional[typing.Sequence[s_obj.ObjectMeta]],
        condition: typing.Optional[typing.Callable[[s_types.Type],
                                                   bool]] = None,
        label: typing.Optional[str] = None,
        ctx: context.ContextLevel,
        srcctx: typing.Optional[parsing.ParserContext] = None) -> s_obj.Object:

    if isinstance(name, qlast.ObjectRef):
        if srcctx is None:
            srcctx = name.context
        module = name.module
        name = name.name
    elif isinstance(name, qlast.AnyType):
        return s_pseudo.Any.instance
    elif isinstance(name, qlast.AnyTuple):
        return s_pseudo.AnyTuple.instance

    if module:
        name = sn.Name(name=name, module=module)

    elif isinstance(name, str):
        view = ctx.aliased_views.get(name)
        if view is not None:
            return view

    try:
        stype = ctx.env.get_track_schema_object(
            name=name,
            modaliases=ctx.modaliases,
            type=item_types,
            condition=condition,
            label=label,
        )

    except errors.QueryError as e:
        s_utils.enrich_schema_lookup_error(e,
                                           name,
                                           modaliases=ctx.modaliases,
                                           schema=ctx.env.schema,
                                           item_types=item_types,
                                           condition=condition,
                                           context=srcctx)
        raise

    view = ctx.aliased_views.get(stype.get_name(ctx.env.schema))
    if view is not None:
        return view
    else:
        return stype
Example #4
0
    def _get_ref_obj(self, ref, item_type):
        clsname = self._get_ref_name(ref)
        try:
            obj = self._schema.get(
                clsname, type=item_type, module_aliases=self._mod_aliases)
        except errors.InvalidReferenceError as e:
            s_utils.enrich_schema_lookup_error(
                e, clsname, modaliases=self._mod_aliases,
                schema=self._schema, item_types=(item_type,))
            e.set_source_context(ref.context)
            raise e

        return obj
Example #5
0
def resolve_ptr(near_endpoint: s_sources.Source,
                pointer_name: str,
                *,
                direction: s_pointers.PointerDirection = (
                    s_pointers.PointerDirection.Outbound),
                source_context: typing.Optional[parsing.ParserContext] = None,
                ctx: context.ContextLevel) -> s_pointers.Pointer:

    if not isinstance(near_endpoint, s_sources.Source):
        # Reference to a property on non-object
        msg = 'invalid property reference on a primitive type expression'
        raise errors.InvalidReferenceError(msg, context=source_context)

    ctx.env.schema, ptr = near_endpoint.resolve_pointer(ctx.env.schema,
                                                        pointer_name,
                                                        direction=direction)

    if ptr is None:
        if isinstance(near_endpoint, s_links.Link):
            msg = (f'{near_endpoint.get_displayname(ctx.env.schema)} '
                   f'has no property {pointer_name!r}')

        elif direction == s_pointers.PointerDirection.Outbound:
            msg = (f'{near_endpoint.get_displayname(ctx.env.schema)} '
                   f'has no link or property {pointer_name!r}')

        else:
            nep_name = near_endpoint.get_displayname(ctx.env.schema)
            path = f'{nep_name}.{direction}{pointer_name}'
            msg = f'{path!r} does not resolve to any known path'

        err = errors.InvalidReferenceError(msg, context=source_context)

        if direction == s_pointers.PointerDirection.Outbound:
            near_enpoint_pointers = near_endpoint.get_pointers(ctx.env.schema)
            s_utils.enrich_schema_lookup_error(
                err,
                pointer_name,
                modaliases=ctx.modaliases,
                item_types=(s_pointers.Pointer, ),
                collection=near_enpoint_pointers.objects(ctx.env.schema),
                schema=ctx.env.schema)

        raise err

    return ptr
Example #6
0
    def _get_ref_type(self, ref):
        clsname = self._get_ref_name(ref.maintype)
        if ref.subtypes:
            subtypes = [self._get_ref_type(s) for s in ref.subtypes]
            ccls = s_types.Collection.get_class(clsname)
            typ = ccls.from_subtypes(self._schema, subtypes)
        else:
            try:
                typ = self._schema.get(
                    clsname, module_aliases=self._mod_aliases)
            except errors.InvalidReferenceError as e:
                s_utils.enrich_schema_lookup_error(
                    e, clsname, modaliases=self._mod_aliases,
                    schema=self._schema, item_types=(s_types.Type,))
                e.set_source_context(ref.context)
                raise e

        return typ
Example #7
0
def get_schema_object(
        name: typing.Union[str, qlast.ObjectRef],
        module: typing.Optional[str] = None,
        *,
        item_types: typing.Optional[typing.List[s_obj.ObjectMeta]],
        ctx: context.ContextLevel,
        srcctx: typing.Optional[parsing.ParserContext] = None) -> s_obj.Object:

    if isinstance(name, qlast.ObjectRef):
        if srcctx is None:
            srcctx = name.context
        module = name.module
        name = name.name
    elif isinstance(name, qlast.AnyType):
        return s_pseudo.Any.instance
    elif isinstance(name, qlast.AnyTuple):
        return s_pseudo.AnyTuple.instance

    if module:
        name = sn.Name(name=name, module=module)

    if not module:
        result = ctx.aliased_views.get(name)
        if result is not None:
            return result

    try:
        stype = ctx.env.schema.get(name=name,
                                   module_aliases=ctx.modaliases,
                                   type=item_types)

    except errors.QueryError as e:
        s_utils.enrich_schema_lookup_error(e,
                                           name,
                                           modaliases=ctx.modaliases,
                                           schema=ctx.env.schema,
                                           item_types=item_types)
        raise

    result = ctx.aliased_views.get(stype.get_name(ctx.env.schema))
    if result is None:
        result = stype

    return result
Example #8
0
def _resolve_schema_ref(
    name: s_name.Name,
    type: Type[s_obj.Object_T],
    sourcectx: parsing.ParserContext,
    *,
    ctx: LayoutTraceContext,
) -> s_obj.Object_T:
    try:
        return ctx.schema.get(name, type=type, sourcectx=sourcectx)
    except errors.InvalidReferenceError as e:
        s_utils.enrich_schema_lookup_error(
            e,
            name,
            schema=ctx.schema,
            modaliases=ctx.modaliases,
            item_type=type,
            context=sourcectx,
        )
        raise
Example #9
0
def _resolve_schema_ref(
    name: s_name.Name,
    type: Type[qltracer.NamedObject],
    sourcectx: Optional[parsing.ParserContext],
    *,
    ctx: LayoutTraceContext,
) -> s_obj.SubclassableObject:
    real_type = TRACER_TO_REAL_TYPE_MAP[type]
    try:
        return ctx.schema.get(name, type=real_type, sourcectx=sourcectx)
    except errors.InvalidReferenceError as e:
        s_utils.enrich_schema_lookup_error(
            e,
            name,
            schema=ctx.schema,
            modaliases=ctx.modaliases,
            item_type=real_type,
            context=sourcectx,
        )
        raise
Example #10
0
def resolve_ptr(
    near_endpoint: s_obj.Object,
    pointer_name: str,
    *,
    upcoming_intersections: Sequence[s_types.Type] = (),
    far_endpoints: Iterable[s_obj.Object] = (),
    direction: s_pointers.PointerDirection = (
        s_pointers.PointerDirection.Outbound),
    source_context: Optional[parsing.ParserContext] = None,
    track_ref: Optional[Union[qlast.Base, Literal[False]]],
    ctx: context.ContextLevel,
) -> s_pointers.Pointer:

    if not isinstance(near_endpoint, s_sources.Source):
        # Reference to a property on non-object
        msg = 'invalid property reference on a primitive type expression'
        raise errors.InvalidReferenceError(msg, context=source_context)

    ptr: Optional[s_pointers.Pointer] = None

    if direction is s_pointers.PointerDirection.Outbound:
        ptr = near_endpoint.maybe_get_ptr(
            ctx.env.schema,
            s_name.UnqualName(pointer_name),
        )

        if ptr is not None:
            ref = ptr.get_nearest_non_derived_parent(ctx.env.schema)
            if track_ref is not False:
                ctx.env.add_schema_ref(ref, track_ref)

    else:
        ptrs = near_endpoint.getrptrs(ctx.env.schema,
                                      pointer_name,
                                      sources=far_endpoints)
        if ptrs:
            if track_ref is not False:
                # If this reverse pointer access is followed by
                # intersections, we filter out any pointers that
                # couldn't be picked up by the intersections. This avoids
                # creating spurious dependencies when reverse
                # links are used in schemas.
                dep_ptrs = {
                    ptr
                    for ptr in ptrs
                    if (src := ptr.get_source(ctx.env.schema)) and all(
                        src.issubclass(ctx.env.schema, typ) or any(
                            dsrc.issubclass(ctx.env.schema, typ)
                            for dsrc in src.descendants(ctx.env.schema))
                        for typ in upcoming_intersections)
                }

                for p in dep_ptrs:
                    ctx.env.add_schema_ref(
                        p.get_nearest_non_derived_parent(ctx.env.schema),
                        track_ref)

            opaque = not far_endpoints
            ctx.env.schema, ptr = s_pointers.get_or_create_union_pointer(
                ctx.env.schema,
                ptrname=s_name.UnqualName(pointer_name),
                source=near_endpoint,
                direction=direction,
                components=ptrs,
                opaque=opaque,
                modname=ctx.derived_target_module,
            )

    if ptr is not None:
        return ptr

    if isinstance(near_endpoint, s_links.Link):
        vname = near_endpoint.get_verbosename(ctx.env.schema, with_parent=True)
        msg = f'{vname} has no property {pointer_name!r}'

    elif direction == s_pointers.PointerDirection.Outbound:
        msg = (f'{near_endpoint.get_verbosename(ctx.env.schema)} '
               f'has no link or property {pointer_name!r}')

    else:
        nep_name = near_endpoint.get_displayname(ctx.env.schema)
        path = f'{nep_name}.{direction}{pointer_name}'
        msg = f'{path!r} does not resolve to any known path'

    err = errors.InvalidReferenceError(msg, context=source_context)

    if direction is s_pointers.PointerDirection.Outbound:
        near_enpoint_pointers = near_endpoint.get_pointers(ctx.env.schema)
        s_utils.enrich_schema_lookup_error(
            err,
            s_name.UnqualName(pointer_name),
            modaliases=ctx.modaliases,
            item_type=s_pointers.Pointer,
            collection=near_enpoint_pointers.objects(ctx.env.schema),
            schema=ctx.env.schema,
        )

    raise err
Example #11
0
def resolve_ptr(
    near_endpoint: s_obj.Object,
    pointer_name: str,
    *,
    far_endpoints: Iterable[s_obj.Object] = (),
    direction: s_pointers.PointerDirection = (
        s_pointers.PointerDirection.Outbound
    ),
    source_context: Optional[parsing.ParserContext] = None,
    track_ref: Optional[Union[qlast.Base, Literal[False]]],
    ctx: context.ContextLevel,
) -> s_pointers.Pointer:

    if not isinstance(near_endpoint, s_sources.Source):
        # Reference to a property on non-object
        msg = 'invalid property reference on a primitive type expression'
        raise errors.InvalidReferenceError(msg, context=source_context)

    ptr: Optional[s_pointers.Pointer] = None

    if direction is s_pointers.PointerDirection.Outbound:
        ptr = near_endpoint.maybe_get_ptr(
            ctx.env.schema,
            s_name.UnqualName(pointer_name),
        )

        if ptr is not None:
            ref = ptr.get_nearest_non_derived_parent(ctx.env.schema)
            if track_ref is not False:
                ctx.env.add_schema_ref(ref, track_ref)

    else:
        ptrs = near_endpoint.getrptrs(ctx.env.schema, pointer_name,
                                      sources=far_endpoints)
        if ptrs:
            if track_ref is not False:
                for p in ptrs:
                    ctx.env.add_schema_ref(
                        p.get_nearest_non_derived_parent(ctx.env.schema),
                        track_ref)

            opaque = not far_endpoints
            ctx.env.schema, ptr = s_pointers.get_or_create_union_pointer(
                ctx.env.schema,
                ptrname=s_name.UnqualName(pointer_name),
                source=near_endpoint,
                direction=direction,
                components=ptrs,
                opaque=opaque,
                modname=ctx.derived_target_module,
            )

    if ptr is not None:
        return ptr

    if isinstance(near_endpoint, s_links.Link):
        vname = near_endpoint.get_verbosename(ctx.env.schema, with_parent=True)
        msg = f'{vname} has no property {pointer_name!r}'

    elif direction == s_pointers.PointerDirection.Outbound:
        msg = (f'{near_endpoint.get_verbosename(ctx.env.schema)} '
               f'has no link or property {pointer_name!r}')

    else:
        nep_name = near_endpoint.get_displayname(ctx.env.schema)
        path = f'{nep_name}.{direction}{pointer_name}'
        msg = f'{path!r} does not resolve to any known path'

    err = errors.InvalidReferenceError(msg, context=source_context)

    if direction is s_pointers.PointerDirection.Outbound:
        near_enpoint_pointers = near_endpoint.get_pointers(ctx.env.schema)
        s_utils.enrich_schema_lookup_error(
            err,
            s_name.UnqualName(pointer_name),
            modaliases=ctx.modaliases,
            item_type=s_pointers.Pointer,
            collection=near_enpoint_pointers.objects(ctx.env.schema),
            schema=ctx.env.schema,
        )

    raise err
Example #12
0
def resolve_ptr(
        near_endpoint: s_sources.Source,
        pointer_name: str, *,
        direction: s_pointers.PointerDirection=(
            s_pointers.PointerDirection.Outbound
        ),
        source_context: typing.Optional[parsing.ParserContext]=None,
        ctx: context.ContextLevel) -> s_pointers.Pointer:

    if not isinstance(near_endpoint, s_sources.Source):
        # Reference to a property on non-object
        msg = 'invalid property reference on a primitive type expression'
        raise errors.InvalidReferenceError(msg, context=source_context)

    if direction is s_pointers.PointerDirection.Outbound:
        ptr = near_endpoint.getptr(ctx.env.schema, pointer_name)
    else:
        ptrs = near_endpoint.getrptrs(ctx.env.schema, pointer_name)
        if not ptrs:
            ptr = None
        else:
            if len(ptrs) == 1:
                ptr = next(iter(ptrs))
            else:
                ctx.env.schema_refs.update(
                    p.get_nearest_non_derived_parent(ctx.env.schema)
                    for p in ptrs
                )
                ctx.env.schema, ptr = s_pointers.get_or_create_union_pointer(
                    ctx.env.schema,
                    ptrname=pointer_name,
                    source=near_endpoint,
                    direction=direction,
                    components=ptrs,
                    modname=ctx.derived_target_module)

    if ptr is None:
        if isinstance(near_endpoint, s_links.Link):
            msg = (f'{near_endpoint.get_verbosename(ctx.env.schema)} '
                   f'has no property {pointer_name!r}')

        elif direction == s_pointers.PointerDirection.Outbound:
            msg = (f'{near_endpoint.get_verbosename(ctx.env.schema)} '
                   f'has no link or property {pointer_name!r}')

        else:
            nep_name = near_endpoint.get_displayname(ctx.env.schema)
            path = f'{nep_name}.{direction}{pointer_name}'
            msg = f'{path!r} does not resolve to any known path'

        err = errors.InvalidReferenceError(msg, context=source_context)

        if direction == s_pointers.PointerDirection.Outbound:
            near_enpoint_pointers = near_endpoint.get_pointers(
                ctx.env.schema)
            s_utils.enrich_schema_lookup_error(
                err, pointer_name, modaliases=ctx.modaliases,
                item_types=(s_pointers.Pointer,),
                collection=near_enpoint_pointers.objects(ctx.env.schema),
                schema=ctx.env.schema
            )

        raise err

    ref = ptr.get_nearest_non_derived_parent(ctx.env.schema)
    ctx.env.schema_refs.add(ref)

    return ptr