diff --git a/leapp/actors/__init__.py b/leapp/actors/__init__.py index 055e88a41..db84e0841 100644 --- a/leapp/actors/__init__.py +++ b/leapp/actors/__init__.py @@ -324,6 +324,35 @@ def produce(self, *models): 'explicitely in the actor\'s "produces" tuple. The message will be ignored'.format( type(model))) + def consume_first_default(self, model): + """ + Retrieves the first message found as specified in the actors :py:attr:`consumes` attribute, and filter message + types by model. This additionally returns as fallback value an instance of model with the default + initialization + + :param model: Model to use as a filter for the messages to return + :type model: A derived class from :py:class:`leapp.models.Model` + :return: The first message of the specified model produced by other a fallback instance of model + :rtype: The message or a default initialized instance of the model type. + """ + return self.consume_first(model, default=model()) + + def consume_first(self, model, default=None): + """ + Retrieves the first message found as specified in the actors :py:attr:`consumes` attribute, and filter message + types by model. + + :param model: Model to use as a filter for the messages to return + :type model: A derived class from :py:class:`leapp.models.Model` + :param default: Fallback value in case there are no messages + :type default: Any + :return: The first message of the specified model produced by other actors or the value passed as `default` + :rtype: The message or the value passed as ``default`` + """ + # One cannot iterate over tuples, so we make a generator that iterates over the value returned by self.consume. + # This way we can workaround both cases. + return next((message for message in self.consume(model)), default) + def consume(self, *models): """ Retrieve messages specified in the actors :py:attr:`consumes` attribute, and filter message types by diff --git a/leapp/libraries/stdlib/api.py b/leapp/libraries/stdlib/api.py index 36a742d37..b6ecc313e 100644 --- a/leapp/libraries/stdlib/api.py +++ b/leapp/libraries/stdlib/api.py @@ -65,6 +65,35 @@ def produce(*model_instances): return current_actor().produce(*model_instances) +def consume_first_default(model): + """ + Retrieves the first message found as specified in the actors :py:attr:`consumes` attribute, and filter message + types by model. This additionally returns as fallback value an instance of model with the default + initialization + + :param model: Model to use as a filter for the messages to return + :type model: A derived class from :py:class:`leapp.models.Model` + :return: The first message of the specified model produced by other a fallback instance of model + :rtype: The message or a default initialized instance of the model type. + """ + return current_actor().consume_first_default(model) + + +def consume_first(model, default=None): + """ + Retrieves the first message found as specified in the actors :py:attr:`consumes` attribute, and filter message + types by model. + + :param model: Model to use as a filter for the messages to return + :type model: A derived class from :py:class:`leapp.models.Model` + :param default: Fallback value in case there are no messages + :type default: Any + :return: The first message of the specified model produced by other actors or the value passed as `default` + :rtype: The message or the value passed as ``default`` + """ + return current_actor().consume_first(model=model, default=default) + + def consume(*models): """ Retrieve messages specified in the actors :py:attr:`consumes` attribute, and filter message types by diff --git a/tests/data/actor-api-tests/models/apitest.py b/tests/data/actor-api-tests/models/apitest.py index 7fd29f1b1..25e36a3e7 100644 --- a/tests/data/actor-api-tests/models/apitest.py +++ b/tests/data/actor-api-tests/models/apitest.py @@ -5,7 +5,7 @@ class ApiTest(Model): topic = ApiTestTopic - data = fields.String() + data = fields.String(default='not-filled') class ApiTestProduce(ApiTest): diff --git a/tests/scripts/test_actor_api.py b/tests/scripts/test_actor_api.py index 1d7affeb2..939e5317d 100644 --- a/tests/scripts/test_actor_api.py +++ b/tests/scripts/test_actor_api.py @@ -72,13 +72,24 @@ def test_actor_messaging_paths(leapp_forked, repository, actor_name): messaging = _TestableMessaging() with _with_loaded_actor(repository, actor_name, messaging) as (_unused, actor): from leapp.models import ApiTestConsume, ApiTestProduce + assert len(list(actor.consume(ApiTestConsume))) == 0 + assert next(actor.consume(ApiTestConsume), None) is None + assert actor.consume_first(ApiTestConsume) is None + assert api.consume_first(ApiTestConsume) is None + assert api.consume_first_default(ApiTestConsume).data == 'not-filled' + assert actor.consume_first_default(ApiTestConsume).data == 'not-filled' + assert actor.consume_first(ApiTestConsume, default='default') == 'default' + assert api.consume_first(ApiTestConsume, default='default') == 'default' + messaging.feed(ApiTestConsume(data='prefilled'), actor) assert len(list(actor.consume(ApiTestConsume))) == 1 assert next(actor.consume(ApiTestConsume)).data == 'prefilled' + assert actor.consume_first(ApiTestConsume).data == 'prefilled' assert len(list(api.consume(ApiTestConsume))) == 1 assert next(api.consume(ApiTestConsume)).data == 'prefilled' + assert api.consume_first(ApiTestConsume).data == 'prefilled' actor_message = 'Actor {} sent message via Actor'.format(actor_name) api_message = 'Actor {} sent message via API'.format(actor_name)