Esempio n. 1
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
Esempio n. 2
0
def tuple_indirection_set(path_tip: irast.Set, *, source: s_sources.Source,
                          ptr_name: str, source_context: parsing.ParserContext,
                          ctx: context.ContextLevel) -> irast.Set:

    el_name = ptr_name
    el_norm_name = source.normalize_index(ctx.env.schema, el_name)
    el_type = source.get_subtype(ctx.env.schema, el_name)

    path_id = pathctx.get_tuple_indirection_path_id(path_tip.path_id,
                                                    el_norm_name,
                                                    el_type,
                                                    ctx=ctx)
    expr = irast.TupleIndirection(expr=path_tip,
                                  name=el_norm_name,
                                  path_id=path_id,
                                  context=source_context)

    return expression_set(expr, ctx=ctx)
Esempio n. 3
0
def _fixup_cardinalities(
    subj_source: s_sources.Source,
    tpl_source: s_sources.Source,
    *,
    ctx: context.ContextLevel,
) -> None:
    """Copy pointer cardinalities from *tpl_source* to *subj_source*."""

    subj_ptrs = subj_source.get_pointers(ctx.env.schema).items(ctx.env.schema)
    tpl_ptrs = dict(
        tpl_source.get_pointers(ctx.env.schema).items(ctx.env.schema))

    for pn, ptrcls in subj_ptrs:
        card = ptrcls.get_cardinality(ctx.env.schema)
        tpl_ptrcls = tpl_ptrs.get(pn)
        if tpl_ptrcls is None:
            raise AssertionError(
                f'expected to find {pn!r} in template source object'
            )

        if not card.is_known():
            tpl_card = tpl_ptrcls.get_cardinality(ctx.env.schema)
            if not tpl_card.is_known():
                raise AssertionError(
                    f'{pn!r} cardinality in template source is unknown'
                )

            ctx.env.schema = ptrcls.set_field_value(
                ctx.env.schema,
                'cardinality',
                tpl_card,
            )

        subj_target = ptrcls.get_target(ctx.env.schema)
        if (
            isinstance(subj_target, s_sources.Source)
            and subj_target.is_view(ctx.env.schema)
        ):
            tpl_target = tpl_ptrcls.get_target(ctx.env.schema)
            assert isinstance(tpl_target, s_sources.Source)
            _fixup_cardinalities(subj_target, tpl_target, ctx=ctx)
Esempio n. 4
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