def merge(self, mfr, root=None, override=False, ignore_collision=True, sep="/", force=None): """Merge another manufacturer with compatible target. This method registers all the factories from the given `Manufacturer`. The resulting key of the merged factories will have the following form: * "root<sep><factory_key>" For instance, using the default `sep="/"`, the merged factory key becomes: * "root/<factory_key>" This allows convenient grouping of factories by context, without the need to hard-code the path-like key at registration. If `root` is `None`, the original method name is used. Args: mfr: `Manufacturer` or a zero-argument function that returns an instance of it. root: A string that serves as the root of the factory keys from `mfr`. If None, the original factory key will be used directly. override: If True, overwrites the original factory in case of key collision. Defaults to False. See `ignore_collision` for collision handling when `override` is False. ignore_collision: Will only take effect when `override` is False. If True, the factory key collision is ignored, i.e. the original factory is preserved. Otherwise, an error would be raised when key collision occurs. Defaults to False. sep: Separator between root and method name in the resulting factory key. Defaults to "/". force: Deprecated. Use `override` instead. If specified, this overrides `override` for backwards compatibility. Raises: KeyConflictError: - Any of the resulting keys has been registered when `override` and `ignore_collision` are both False. TypeError: - `mfr` is not a `Manufacturer` nor a zero-argument function that returns an instance of it. - Target of `mfr` is not a subclass of this target. """ override = deprecation.handle_renamed_arg("override", override, "force", force) mfr = fn_util.maybe_call(mfr, Manufacturer) self._validate_merge(mfr, root, override, ignore_collision, sep) self._merge(root, mfr, override=override, ignore_collision=ignore_collision, sep=sep)
def merge_all(self, mfr_dict, **kwargs): """Merges multiple manufacturers. Args: mfr_dict: A dictionary mapping each root to either of the following: 1. A `Manufacturer` instance with compatible target 2. A zero-argument function that returns (1) above 3. An iterable of either of (1, 2) above 4. A zero-argument function that returns either of (1, 3) above **kwargs: Merge options: * override: If True, overwrites the original factory registration in case of key collision. Defaults to False. See `raise_on_collision` for collision handling if not `override`. * ignore_collision: If True, the factory key collision is ignored when `override` is False, and the original factory is preserved. Otherwise, an error would be raised. Defaults to False. * sep: Separator between root and method name in the resulting factory key. Defaults to "/". See `Manufacturer.merge` for details. * force: Deprecated. Use `override` instead. If specified, this overrides `override` for backwards compatibility. Raises: KeyConflictError: - Any of the resulting keys has been registered when `override` and `ignore_collision` are both False TypeError: - Any values of `mfr_dict` is not one of the described ones above. - Target of any `Manufacturer` that is not a subclass of this target. """ if "force" in kwargs: deprecation.warn( "Parameter `force` is deprecated. Use `override` instead.") kwargs["override"] = kwargs.pop("force") mfr_dict_validated = collections.defaultdict(list) for root, mfrs in mfr_dict.items(): if callable(mfrs): mfrs = mfrs() if not hasattr(mfrs, "__iter__"): mfrs = [mfrs] for mfr in mfrs: mfr = fn_util.maybe_call(mfr, Manufacturer) self._validate_merge(mfr, root, **kwargs) mfr_dict_validated[root].append(mfr) for root, mfrs in mfr_dict_validated.items(): [self._merge(root, mfr, **kwargs) for mfr in mfrs]
def register_all(self, mfrs, **kwargs): """Registers multiple `Manufacturer`s at once. Args: mfrs: An iterable of `Manufacturer`s, or zero-argument functions where each returns an instance of it. **kwargs: Register options * override: If True, when a `Manufacturer` with the same target class exists, detaches the original one and registers `mfr`. If False, an error is raised instead. Defaults to False. Raises: KeyConflictError: - `Manufacturer` class collision occurs and `override` is False. """ checked = [] for mfr in mfrs: mfr = fn_util.maybe_call(mfr, Manufacturer) checked.append(mfr) [self.register(mfr, **kwargs) for mfr in checked]
def _merge_mfr(self, mfr, **kwargs): mfr = fn_util.maybe_call(mfr, Manufacturer) _mfr = self.get_or_create(mfr.cls) _mfr.merge(mfr, **kwargs)
def _merge(self, broker, **kwargs): broker = fn_util.maybe_call(broker, Broker) for cls in broker.classes: mfr = broker.get(cls) self.merge_mfr(mfr, **kwargs)