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
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
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
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