Example #1
0
    def copy_needed(self, traits: 'ResolvedTraitSet',
                    res_guide: 'CdmAttributeResolutionGuidanceDefinition',
                    actions: List['AttributeResolutionApplier']) -> bool:
        if not actions:
            return False

        # For every attribute in the set, detect if a merge of traits will alter the traits. If so, need to copy the
        # attribute set to avoid overwrite.
        for res_att in self.set:
            for trait_action in actions:
                ctx = ApplierContext()
                ctx.res_opt = traits.res_opt
                ctx.res_att_source = res_att
                ctx.res_guide = res_guide

                if trait_action.will_attribute_modify(ctx):
                    return True

        return False
Example #2
0
    def apply(
            self, traits: 'ResolvedTraitSet',
            res_guide: 'CdmAttributeResolutionGuidanceDefinition',
            actions: List['AttributeResolutionApplier']
    ) -> 'ResolvedAttributeSet':

        if not traits and not actions:
            # Nothing can change.
            return self

        # For every attribute in the set run any attribute appliers.
        applied_att_set = ResolvedAttributeSet()
        for res_att in self.set:
            sub_set = cast('ResolvedAttributeSet', res_att.target)
            # TODO: check if should be "sub_set.set is not None"
            if isinstance(sub_set, ResolvedAttributeSet) and sub_set.set:
                # The set contains another set. Process those.
                res_att.target = sub_set.apply(traits, res_guide, actions)
            else:
                rts_merge = res_att.resolved_traits.merge_set(traits)
                res_att.resolved_traits = rts_merge

                if actions:
                    for trait_action in actions:
                        ctx = ApplierContext()
                        ctx.res_opt = traits.res_opt
                        ctx.res_att_source = res_att
                        ctx.res_guide = res_guide

                        if trait_action.will_attribute_modify(ctx):
                            trait_action.do_attribute_modify(ctx)

            applied_att_set.merge(res_att)

        applied_att_set.rattr_to_attctxset = self.rattr_to_attctxset
        applied_att_set.attctx_to_rattr = self.attctx_to_rattr
        return applied_att_set
Example #3
0
        def make_resolved_attribute(res_att_source: 'ResolvedAttribute', action: 'AttributeResolutionApplier',
                                    query_add: 'ApplierQuery', do_add: 'ApplierAction', state: str) -> 'ApplierContext':
            app_ctx = ApplierContext()
            app_ctx.state = state
            app_ctx.res_opt = arc.res_opt
            app_ctx.att_ctx = att_ctx_container
            app_ctx.res_att_source = res_att_source
            app_ctx.res_guide = arc.res_guide

            if res_att_source and isinstance(res_att_source.target, ResolvedAttributeSet) and cast('ResolvedAttributeSet', res_att_source.target)._set:
                return app_ctx  # Makes no sense for a group.

            # Will something add?
            if query_add(app_ctx):
                # May want to make a new attribute group.
                # make the 'new' attribute look like any source attribute for the duration of this call to make a context. there could be state needed
                app_ctx.res_att_new = res_att_source
                if self.ras.attribute_context and action._will_create_context and action._will_create_context(app_ctx):
                    action._do_create_context(app_ctx)

                # Make a new resolved attribute as a place to hold results.
                app_ctx.res_att_new = ResolvedAttribute(app_ctx.res_opt, None, None, app_ctx.att_ctx)

                # Copy state from source.
                if res_att_source and res_att_source.applier_state:
                    app_ctx.res_att_new.applier_state = res_att_source.applier_state._copy()
                else:
                    app_ctx.res_att_new.applier_state = ApplierState()

                # If applying traits, then add the sets traits as a staring point.
                if apply_modifiers:
                    app_ctx.res_att_new.resolved_traits = arc.traits_to_apply.deep_copy()

                # Make it
                do_add(app_ctx)

                # Combine resolution guidance for this set with anything new from the new attribute.
                app_ctx.res_guide_new = app_ctx.res_guide._combine_resolution_guidance(app_ctx.res_guide_new)

                app_ctx.res_att_new.arc = AttributeResolutionContext(arc.res_opt, app_ctx.res_guide_new, app_ctx.res_att_new.resolved_traits)

                if apply_modifiers:
                    # Add the sets traits back in to this newly added one.
                    app_ctx.res_att_new.resolved_traits = app_ctx.res_att_new.resolved_traits.merge_set(arc.traits_to_apply)

                    # Be sure to use the new arc, the new attribute may have added actions. For now, only modify and
                    # remove will get acted on because recursion. Do all of the modify traits.
                    if app_ctx.res_att_new.arc.applier_caps.can_attribute_modify:
                        # Modify acts on the source and we should be done with it.
                        app_ctx.res_att_source = app_ctx.res_att_new

                        for mod_act in app_ctx.res_att_new.arc.actions_modify:
                            if mod_act._will_attribute_modify(app_ctx):
                                mod_act._do_attribute_modify(app_ctx)
                app_ctx.res_att_new.complete_context(app_ctx.res_opt)

            return app_ctx
Example #4
0
    def remove_requested_atts(
            self, marker: Tuple[int, int]) -> 'ResolvedAttributeSet':
        # The marker tracks the track the deletes 'under' a certain index.
        (count_index, mark_index) = marker

        # For every attribute in the set, run any attribute removers on the traits they have.
        applied_att_set = None  # type: ResolvedAttributeSet
        for i_att, res_att in enumerate(self.set):
            # Possible for another set to be in this set.
            sub_set = cast('ResolvedAttributeSet', res_att.target)
            if isinstance(sub_set, ResolvedAttributeSet) and sub_set.set:
                # Go around again on this same function and get rid of things from this group.
                marker = (count_index, mark_index)
                new_sub_set = sub_set.remove_requested_atts(marker)
                (count_index, mark_index) = marker
                # Replace the set with the new one that came back.
                res_att.target = new_sub_set
                # If everything went away, then remove this group.
                if not new_sub_set or not new_sub_set.set:
                    res_att = None
                else:
                    # Don't count this as an attribute (later).
                    count_index -= 1
            else:
                # This is a good time to make the resolved names final.
                res_att.previous_resolved_name = res_att.resolved_name
                if res_att.arc and res_att.arc.applier_caps and res_att.arc.applier_caps.can_remove:
                    for apl in res_att.arc.actions_remove:
                        # This should look like the applier context when the att was created.
                        ctx = ApplierContext()
                        ctx.res_opt = res_att.arc.res_opt
                        ctx.res_att_source = res_att
                        ctx.res_guide = res_att.arc.res_guide

                        if apl.will_remove(ctx):
                            res_att = None
                            break

            if res_att:
                # Attribute remains. Are we building a new set?
                if applied_att_set:
                    self.copy_att_ctx_mappings_into(
                        applied_att_set.rattr_to_attctxset,
                        applied_att_set.attctx_to_rattr, res_att)
                    applied_att_set.merge(res_att)
                count_index += 1
            else:
                # Remove the attribute. If this is the first removed attribute, then make a copy of the set now. After
                # this point, the rest of the loop logic keeps the copy going as needed.
                if not applied_att_set:
                    applied_att_set = ResolvedAttributeSet()
                    for i_copy in range(i_att):
                        self.copy_att_ctx_mappings_into(
                            applied_att_set.rattr_to_attctxset,
                            applied_att_set.attctx_to_rattr, self.set[i_copy])
                        applied_att_set.merge(self.set[i_copy])

                # Track deletes under the mark (move the mark up)
                if count_index < mark_index:
                    mark_index -= 1

        marker = (count_index, mark_index)

        # Now we are that (or a copy).
        ras_result = self
        if applied_att_set and applied_att_set.size != ras_result.size:
            ras_result = applied_att_set
            ras_result.basetrait_to_attr = None
            ras_result.attribute_context = self.attribute_context

        return ras_result