Пример #1
0
    def _filter_parameters(
        self, parameters: Iterable[AgentParameterDto]
    ) -> List[AgentParameterDto]:
        """
        Remove parameters that should not be available to the user.
        """
        # We don't allow the user to change these options which are only
        # intended to be used interactively on command line.
        remove_parameters = frozenset(("help", "version"))
        filtered_1 = []
        for param in parameters:
            if param.name in remove_parameters:
                continue
            if param.name == "action":
                # However we still need the user to be able to set 'action' due
                # to backward compatibility reasons. So we just mark it as not
                # required. We also move it to advanced params to indicate users
                # should not set it in most cases.
                filtered_1.append(
                    dc_replace(
                        param,
                        required=False,
                        advanced=True,
                        pcs_deprecated_warning=(
                            "Specifying 'action' is deprecated and not "
                            "necessary with current Pacemaker versions. "
                            "Use {0} instead."
                        ).format(format_list(STONITH_ACTION_REPLACED_BY)),
                    )
                )
            else:
                filtered_1.append(param)

        # 'port' parameter is required by a fence agent, but it is filled
        # automatically by pacemaker based on 'pcmk_host_map' or
        # 'pcmk_host_list' parameter (defined in fenced metadata). Pacemaker
        # marks 'port' parameter as not required for us.
        # It, however, doesn't mark any parameters deprecating 'port' as not
        # required se we must do so ourselves.
        port_related_params = set(["port"])
        new_deprecated = set(["port"])
        while new_deprecated:
            current_deprecated = new_deprecated
            new_deprecated = set()
            for param in filtered_1:
                if param.obsoletes in current_deprecated:
                    if param.name not in port_related_params:
                        new_deprecated.add(param.name)
                        port_related_params.add(param.name)
        filtered_2 = []
        for param in filtered_1:
            if param.name in port_related_params:
                filtered_2.append(dc_replace(param, required=False))
            else:
                filtered_2.append(param)

        return filtered_2
Пример #2
0
    async def build_inferrer(self, a, fn, argvals):
        if isinstance(fn, TypedPrimitive):
            return _const(fn.prim, a)

        inf = self.specializer.engine.get_inferrer_for(fn)
        argvals = argvals and inf.normalize_args(argvals)
        argvals, outval = await self._find_unique_argvals(a, inf, argvals)

        if isinstance(inf, TrackedInferrer):
            fn = dc_replace(fn, tracking_id=None)
            inf = self.specializer.engine.get_inferrer_for(fn)

        if isinstance(fn, PrimitiveFunction):
            a = AbstractFunction(TypedPrimitive(fn.prim, argvals, outval))
            return _const(fn.prim, a)

        assert isinstance(inf, BaseGraphInferrer)

        assert _visible(self.graph, fn.context.graph)

        if hasattr(inf, 'graph_cache'):
            await concretize_cache(inf.graph_cache)

        ctx = inf.make_context(self.specializer.engine, argvals)
        v = await self.specializer._specialize(ctx.graph, ctx, None)

        assert isinstance(v, Graph)
        newa = AbstractFunction(GraphFunction(v, ctx))
        rval = _const(v, newa)
        newa.tracking_id = rval
        return rval
Пример #3
0
    def _prepare(self):
        assert self.pattern
        pattern = to_pattern(self.pattern)
        self._rules = defaultdict(lambda: defaultdict(list))

        self._key_captures = pattern.key_captures()

        for method in dir(self):
            fn = getattr(self, method)
            role = getattr(fn, "_ptera_role", None)
            if role is None:
                continue

            if role.target.capture is None:
                role.target = dc_replace(role.target,
                                         capture=self.default_target)

            _, names = get_names(fn)
            names = {*names, *[k for k, param in self._key_captures]}
            patt = pattern.rewrite(names, focus=role.target.capture)
            patt = patt.specialize({role.target.capture: role.target})

            if role.role == "valuer":
                self._rules[patt]["value"].append(self._value_wrap(fn))

            elif role.role == "initializer":
                self._rules[patt]["value"].append(self._init_wrap(fn))

            elif role.role == "updater":
                self._rules[patt]["listeners"].append(self._update_wrap(fn))

            else:
                raise AssertionError(f"Unknown role: {role.role}")
Пример #4
0
 def get_actions(self) -> List[AgentActionDto]:
     """
     Get list of agent's actions (operations)
     """
     action_list = []
     for action in self._get_raw_actions():
         if action.depth is not None:
             if action.depth == "0":
                 action_list.append(dc_replace(action, depth=None))
             else:
                 action_list.append(
                     dc_replace(action, OCF_CHECK_LEVEL=action.depth)
                 )
         else:
             action_list.append(action)
     return action_list
Пример #5
0
    def solve_rates(
        self, outflow: Frac, **solver_kwargs
    ) -> t.Tuple[t.List[BeltAssignment], int, t.List[Item.Flow]]:
        """
        Solves the number of units to fill a full belt
        """

        # NOTE we divide by 2 since the line solution is for half the flow
        # see: symmetric layout assumed (TODO) by belt_solver
        out_rate = outflow / 2

        # base output per sec per unit
        rps = Frac(self.speed) * self.base_rps

        # NOTE this is the needed manufactories per side
        need_mfs = Frac(out_rate / rps) / self.prod

        assert self.recipe is not None

        need_flows = [
            dc_replace(base_flow, num=base_flow.num * need_mfs * rps)
            for base_flow in self.recipe.inputs
        ]

        belt_assignment = solve_belts(need_flows)

        return belt_assignment, need_mfs, need_flows
Пример #6
0
    def analyze_function(self, a, fn, argvals):
        """Analyze a function for the collect phase.

        Arguments:
            a: The abstract value for the function.
            fn: The Function object, equivalent a.get_unique().
            argvals: The abstract arguments given to the function.

        Returns:
            ct: A Constant to use for this call.
            ctx: The context for this call, or None
            norm_ctx: The normalized context for this call, or None

        """
        inf = self.engine.get_inferrer_for(fn)
        argvals = argvals and inf.normalize_args_sync(argvals)
        argvals, outval = self._find_unique_argvals(a, inf, argvals)

        if isinstance(inf, TrackedInferrer):
            fn = dc_replace(fn, tracking_id=None)
            inf = self.engine.get_inferrer_for(fn)

        if isinstance(fn, PrimitiveFunction):
            a = AbstractFunction(TypedPrimitive(fn.prim, argvals, outval))
            return _const(fn.prim, a), None

        assert isinstance(inf, GraphInferrer)
        concretize_cache(inf.graph_cache)

        ctx = inf.make_context(self.engine, argvals)
        norm_ctx = _normalize_context(ctx)
        if norm_ctx not in self.specializations:
            self.specializations[norm_ctx] = ctx
        new_ct = _const(_Placeholder(norm_ctx), None)
        return new_ct, norm_ctx
Пример #7
0
    def _get_parameters(self) -> List[AgentParameterDto]:
        """
        Get list of agent's parameters
        """
        params_element = self._get_metadata().find("parameters")
        if params_element is None:
            return []

        preprocessed_param_list = []
        deprecated_by_dict: Dict[str, Set[str]] = {}
        for param_el in params_element.iter("parameter"):
            param = self._get_parameter(param_el)
            if param is None:
                continue
            preprocessed_param_list.append(param)
            if param.obsoletes:
                obsoletes = param.obsoletes
                if not obsoletes in deprecated_by_dict:
                    deprecated_by_dict[obsoletes] = set()
                deprecated_by_dict[obsoletes].add(param.name)

        param_list = []
        for param in preprocessed_param_list:
            if param.name in deprecated_by_dict:
                param_list.append(
                    dc_replace(
                        param,
                        deprecated_by=sorted(deprecated_by_dict[param.name]),
                    )
                )
            else:
                param_list.append(param)

        return param_list
Пример #8
0
 def _get_metadata(self) -> ResourceAgentMetadata:
     pcs_metadata = ocf_unified_to_pcs(self._raw_metadata)
     if self._additional_parameters:
         pcs_metadata = dc_replace(
             pcs_metadata,
             parameters=(pcs_metadata.parameters +
                         list(self._additional_parameters)),
         )
     return pcs_metadata
Пример #9
0
 def with_modules(self, modules: t.List[Item.Module]) -> BaseManuf:
     if len(modules) > self.module_slots:
         raise ValueError(
             f"Too many modules for a {self.name} manufactory!")
     if (self.recipe and any(m.prod != Frac(0) for m in modules)
             and not self.recipe.proddable):
         raise ValueError(
             "Assigning productivity modules to non-proddable recipe!")
     return dc_replace(self, modules=modules)
Пример #10
0
 def get_inferrer_for(__call__, self, fn):
     """Return the Inferrer for the given function."""
     tracking = getattr(fn, "tracking_id", None)
     if tracking is None:
         return __call__(self, fn)
     if fn not in self.constructors:
         fn_generic = dc_replace(fn, tracking_id=None)
         inf = __call__(self, fn_generic)
         self.constructors[fn] = TrackedInferrer(inf)
     return self.constructors[fn]
Пример #11
0
 def with_recipe(self, recipe: Recipe) -> BaseManuf:
     print(recipe)
     if (self.modules and any(m.prod != Frac(0) for m in self.modules)
             and not recipe.proddable):
         raise ValueError(
             "Assigning non-proddable recipe to manuf. with prodmods!")
     if recipe.category not in self.recipe_cap:
         raise ValueError(f"Recipe ({recipe.category})incompatible with "
                          f"this manufactory ({self.recipe_cap}")
     return dc_replace(self, recipe=recipe)
Пример #12
0
 def get_inferrer_for(ovldcall, fn):
     """Return the Inferrer for the given function."""
     __call__ = ovldcall.resolve(fn)
     tracking = getattr(fn, "tracking_id", None)
     if tracking is None:
         return __call__(fn)
     if fn not in ovldcall.obj.constructors:
         fn_generic = dc_replace(fn, tracking_id=None)
         inf = __call__(fn_generic)
         ovldcall.obj.constructors[fn] = TrackedInferrer(inf)
     return ovldcall.obj.constructors[fn]
Пример #13
0
 def _get_parameter(
     self, parameter_element: _Element
 ) -> Optional[AgentParameterDto]:
     parameter = super()._get_parameter(parameter_element)
     if parameter is None:
         return None
     # Metadata are written in such a way that a longdesc text is a
     # continuation of a shortdesc text.
     return dc_replace(
         parameter,
         longdesc=f"{parameter.shortdesc}\n{parameter.longdesc}".strip(),
         advanced=parameter.shortdesc.startswith("Advanced use only"),
     )
Пример #14
0
def _complete_all_intervals(
    raw_operation_list: Iterable[AgentActionDto],
) -> List[AgentActionDto]:
    """
    Return a new list of operations with "interval" defined for all of them

    operation_list -- can include items with "interval" == None
    """
    operation_list = []
    for operation in raw_operation_list:
        if operation.interval is None:
            operation_list.append(
                dc_replace(
                    operation, interval=_get_default_interval(operation.name)
                )
            )
        else:
            operation_list.append(operation)
    return operation_list
Пример #15
0
 def clone(self, **changes):
     return dc_replace(self, **changes)
Пример #16
0
def no_tracking_id(self, x: GraphFunction):
    """Resolve all Pending and erase tracking_id information."""
    return dc_replace(x, tracking_id=None)
Пример #17
0
def _no_tracking_id(self, x: GraphFunction):
    return dc_replace(x, tracking_id=None)
Пример #18
0
    def normalize(
            assignments: ty.List[BeltAssignment]) -> ty.List[BeltAssignment]:
        """
        Normalize a belt assignment solution set.

        Minimizes hetereogeneous belts.
        """

        by_belt_type = defaultdict(list)  # type: ignore
        for asst in assignments:
            by_belt_type[asst.belt].append(asst)

        out = []
        # within each belt type...
        for bt_assts in by_belt_type.values():
            assts_copy = set(bt_assts)
            while True:
                continue_outer = False
                by_item = defaultdict(set)  # type: ignore
                # ... we map each item to the hetero assts that contain it ...
                for asst in assts_copy:
                    if asst.item_right == asst.item_left:
                        continue
                    by_item[asst.item_left].add(asst)
                    by_item[asst.item_right].add(asst)
                    # ... rechecking by_item every time we add a new asst ...
                    for asst_set in by_item.values():
                        # ... if ever an item has two hetero assets
                        # then they can be swapped to homogenize a belt...
                        if len(asst_set) == 2:
                            x = asst_set.pop()
                            y = asst_set.pop()

                            # so we check which assets to swap between the
                            # belts. Immutability is a guiderail here.
                            if (x.item_right
                                    == y.item_right) or (x.item_left
                                                         == y.item_left):
                                new_x = dc_replace(x, item_right=y.item_left)
                                new_y = dc_replace(y, item_left=x.item_right)
                            else:
                                new_x = dc_replace(x, item_right=y.item_right)
                                new_y = dc_replace(y, item_right=x.item_right)

                            # we invalidate the originals
                            assts_copy.discard(x)
                            assts_copy.discard(y)
                            # and add the reforged assignments
                            assts_copy.add(new_x)
                            assts_copy.add(new_y)
                            # we continue our search if we did anything
                            continue_outer = True
                            break  # for asst_set in by_item.values()
                    # we continue continuing our search if we did anything
                    if continue_outer:
                        break  # for asst in assts_copy
                # otherwise we are done!
                if not continue_outer:
                    break  # while True

            out.extend(list(assts_copy))
        return sorted(out)