Adds transients (service, topic, etc) named in add_names if they are not exposed in resolved_dict
        and removes transients named in remove_names if they are exposed in resolved_dict

        This method can be used to force exposing/withholding any transient, bypassing other mechanisms.
        No extra check is made here regarding regex or system status to try to guess if it should be added/removed.
        This is left ot the caller.

        :param add_names: the names of the transients to add
        :param remove_names: the names of the transients to remove
        :param class_build_args: the args to pass to the resolved transient constructor
        :param class_build_kwargs: the kwargs to pass to the resolved transient constructor
        :return: the list of transients exposed

def update_transients(self, add_names, remove_names, *class_build_args, **class_build_kwargs):
        """
        Adds transients (service, topic, etc) named in add_names if they are not exposed in resolved_dict
        and removes transients named in remove_names if they are exposed in resolved_dict

        This method can be used to force exposing/withholding any transient, bypassing other mechanisms.
        No extra check is made here regarding regex or system status to try to guess if it should be added/removed.
        This is left ot the caller.

        :param add_names: the names of the transients to add
        :param remove_names: the names of the transients to remove
        :param class_build_args: the args to pass to the resolved transient constructor
        :param class_build_kwargs: the kwargs to pass to the resolved transient constructor
        :return: the list of transients exposed
        """
        # Important : no effect if names is empty list. only return empty. functional style.

        added = []
        removed = []
        for tst_name in [tst for tst in add_names if tst not in self.transients.keys()]:
            try:
                ttype = self.transient_type_resolver(tst_name)  # should return None if error - TODO : handle (and reraise) exception !!
                if ttype is not None:  # transient can be resolved
                    self.transients[tst_name] = self.TransientMaker(tst_name, ttype, *class_build_args, **class_build_kwargs)
                    added += [tst_name]
                    logging.info("[{name}] Interfacing with {desc} {transient}".format(name=__name__, desc=self.transients_desc, transient=tst_name))
                else:
                    logging.warning("[{name}] Type of {desc} {transient} unknown. Giving up trying to interface.".format(name=__name__, desc=self.transients_desc,
                                                                              transient=tst_name))
            except Exception as e:
                logging.warn("[{name}] Cannot interface with {desc} {transient} : {exc}".format(name=__name__, desc=self.transients_desc, transient=tst_name, exc=e))
                exc_info = sys.exc_info()
                six.reraise(exc_info[0], exc_info[1], exc_info[2])

        for tst_name in [tst for tst in remove_names if tst in self.transients.keys()]:
            if tst_name in self.transients:  # we make sure the transient is still exposed
                # because we might have modified resolved_dict after building the list to loop on
                logging.info("[{name}] Removing {desc} {transient}".format(name=__name__, desc=self.transients_desc, transient=tst_name))
                self.TransientCleaner(self.transients[tst_name])  # calling the cleanup function in case we need to do something
                self.transients.pop(tst_name, None)
                removed += [tst_name]

        return DiffTuple(added, removed)