From cea77ab377314110900b4b0bf5ec553f27ff54cc Mon Sep 17 00:00:00 2001 From: vijay59122 Date: Mon, 28 Oct 2024 09:57:47 +0530 Subject: [PATCH 01/10] --tags filter issue(#2849) fix --- locust/user/task.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/locust/user/task.py b/locust/user/task.py index 11089b9772..96f7b92c7c 100644 --- a/locust/user/task.py +++ b/locust/user/task.py @@ -472,13 +472,15 @@ class DefaultTaskSet(TaskSet): def get_next_task(self): if not self.user.tasks: + warning_message = "Use the @task decorator or set the 'tasks' attribute of the User (or mark it as abstract = True if you only intend to subclass it)" if getattr(self.user, "task", None): - extra_message = ", but you have set a 'task' attribute on your class - maybe you meant to set 'tasks'?" + extra_message = f", but you have set a 'task' attribute on your class - maybe you meant to set 'tasks'?" + raise Exception( + f"No tasks defined on {self.user.__class__.__name__}{extra_message}{warning_message}" + ) else: - extra_message = "." - raise Exception( - f"No tasks defined on {self.user.__class__.__name__}{extra_message} Use the @task decorator or set the 'tasks' attribute of the User (or mark it as abstract = True if you only intend to subclass it)" - ) + logger.warning(f"No tasks defined on {self.user.__class__.__name__}. {warning_message}") + raise StopUser return random.choice(self.user.tasks) def execute_task(self, task): From efe96c336e8259d244eea283d9298946a238c135 Mon Sep 17 00:00:00 2001 From: vijay59122 Date: Mon, 28 Oct 2024 10:06:13 +0530 Subject: [PATCH 02/10] removed f string format from extra_message variable --- locust/user/task.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/locust/user/task.py b/locust/user/task.py index 96f7b92c7c..1556e025c0 100644 --- a/locust/user/task.py +++ b/locust/user/task.py @@ -474,7 +474,7 @@ def get_next_task(self): if not self.user.tasks: warning_message = "Use the @task decorator or set the 'tasks' attribute of the User (or mark it as abstract = True if you only intend to subclass it)" if getattr(self.user, "task", None): - extra_message = f", but you have set a 'task' attribute on your class - maybe you meant to set 'tasks'?" + extra_message = ", but you have set a 'task' attribute on your class - maybe you meant to set 'tasks'?" raise Exception( f"No tasks defined on {self.user.__class__.__name__}{extra_message}{warning_message}" ) From bdcf4ca068d8bee3155f987c1635e95ebb993c4e Mon Sep 17 00:00:00 2001 From: vijay59122 Date: Mon, 28 Oct 2024 22:41:03 +0530 Subject: [PATCH 03/10] fixed unit test cases --- locust/test/test_locust_class.py | 3 ++- locust/user/task.py | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/locust/test/test_locust_class.py b/locust/test/test_locust_class.py index 6fc0c0b829..9cae339012 100644 --- a/locust/test/test_locust_class.py +++ b/locust/test/test_locust_class.py @@ -60,7 +60,8 @@ class MyUser(User): wait_time = constant(0.5) l = MyUser(self.environment) - self.assertRaisesRegex(Exception, "No tasks defined on MyUser.*", l.run) + # to make sure exception is not raised + l.run() MyUser.task = object() self.assertRaisesRegex(Exception, ".*but you have set a 'task' attribute.*", l.run) diff --git a/locust/user/task.py b/locust/user/task.py index 1556e025c0..3dd1df8a65 100644 --- a/locust/user/task.py +++ b/locust/user/task.py @@ -480,7 +480,7 @@ def get_next_task(self): ) else: logger.warning(f"No tasks defined on {self.user.__class__.__name__}. {warning_message}") - raise StopUser + raise StopUser() return random.choice(self.user.tasks) def execute_task(self, task): From cab6ccf1a5bdc60e0bb544c9da294cd3d785368f Mon Sep 17 00:00:00 2001 From: vijay59122 Date: Mon, 28 Oct 2024 22:46:58 +0530 Subject: [PATCH 04/10] ruff format fix --- locust/user/task.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/locust/user/task.py b/locust/user/task.py index 3dd1df8a65..c5f1834644 100644 --- a/locust/user/task.py +++ b/locust/user/task.py @@ -475,9 +475,7 @@ def get_next_task(self): warning_message = "Use the @task decorator or set the 'tasks' attribute of the User (or mark it as abstract = True if you only intend to subclass it)" if getattr(self.user, "task", None): extra_message = ", but you have set a 'task' attribute on your class - maybe you meant to set 'tasks'?" - raise Exception( - f"No tasks defined on {self.user.__class__.__name__}{extra_message}{warning_message}" - ) + raise Exception(f"No tasks defined on {self.user.__class__.__name__}{extra_message}{warning_message}") else: logger.warning(f"No tasks defined on {self.user.__class__.__name__}. {warning_message}") raise StopUser() From 12059dd7d245b8bb5cf81f09a993609747bd438f Mon Sep 17 00:00:00 2001 From: vijay59122 Date: Tue, 29 Oct 2024 07:52:45 +0530 Subject: [PATCH 05/10] fixed test_error_when_no_tasks_match_tags test --- locust/test/test_main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/locust/test/test_main.py b/locust/test/test_main.py index aab8916f38..ddce31deeb 100644 --- a/locust/test/test_main.py +++ b/locust/test/test_main.py @@ -1390,7 +1390,7 @@ def task1(self): stdout, stderr = proc.communicate() self.assertIn("MyUser had no tasks left after filtering", stderr) self.assertIn("No tasks defined on MyUser", stderr) - self.assertEqual(1, proc.returncode) + self.assertEqual(0, proc.returncode) @unittest.skipIf(os.name == "nt", reason="Signal handling on windows is hard") def test_graceful_exit_when_keyboard_interrupt(self): From 4b9a00c8fcbeacc4de4f6f20b261b1a1e9b1884a Mon Sep 17 00:00:00 2001 From: vijay59122 Date: Tue, 12 Nov 2024 08:20:00 +0530 Subject: [PATCH 06/10] defined custom exception --- locust/exception.py | 5 +++++ locust/test/test_locust_class.py | 5 ++--- locust/test/test_main.py | 2 +- locust/user/task.py | 8 +++++--- 4 files changed, 13 insertions(+), 7 deletions(-) diff --git a/locust/exception.py b/locust/exception.py index c845a81a0f..914642679e 100644 --- a/locust/exception.py +++ b/locust/exception.py @@ -76,3 +76,8 @@ def __init__(self, *args: object, addr=None) -> None: class RunnerAlreadyExistsError(Exception): pass + +class NoTaskToRun(Exception): + def __init__(self, message): + super().__init__(message) + self.exit_code = 1 diff --git a/locust/test/test_locust_class.py b/locust/test/test_locust_class.py index 9cae339012..cb1af99774 100644 --- a/locust/test/test_locust_class.py +++ b/locust/test/test_locust_class.py @@ -6,7 +6,7 @@ RescheduleTask, RescheduleTaskImmediately, ResponseError, - StopUser, + StopUser, NoTaskToRun, ) import gevent @@ -60,8 +60,7 @@ class MyUser(User): wait_time = constant(0.5) l = MyUser(self.environment) - # to make sure exception is not raised - l.run() + self.assertRaisesRegex(NoTaskToRun, "No tasks defined on MyUser.*", l.run) MyUser.task = object() self.assertRaisesRegex(Exception, ".*but you have set a 'task' attribute.*", l.run) diff --git a/locust/test/test_main.py b/locust/test/test_main.py index ddce31deeb..aab8916f38 100644 --- a/locust/test/test_main.py +++ b/locust/test/test_main.py @@ -1390,7 +1390,7 @@ def task1(self): stdout, stderr = proc.communicate() self.assertIn("MyUser had no tasks left after filtering", stderr) self.assertIn("No tasks defined on MyUser", stderr) - self.assertEqual(0, proc.returncode) + self.assertEqual(1, proc.returncode) @unittest.skipIf(os.name == "nt", reason="Signal handling on windows is hard") def test_graceful_exit_when_keyboard_interrupt(self): diff --git a/locust/user/task.py b/locust/user/task.py index c5f1834644..c69909b36e 100644 --- a/locust/user/task.py +++ b/locust/user/task.py @@ -1,6 +1,7 @@ from __future__ import annotations -from locust.exception import InterruptTaskSet, MissingWaitTimeError, RescheduleTask, RescheduleTaskImmediately, StopUser +from locust.exception import InterruptTaskSet, MissingWaitTimeError, RescheduleTask, RescheduleTaskImmediately, \ + StopUser, NoTaskToRun import logging import random @@ -361,6 +362,8 @@ def run(self): except Exception: logging.error("Uncaught exception in on_stop: \n%s", traceback.format_exc()) raise + except NoTaskToRun: + raise except Exception as e: self.user.environment.events.user_error.fire(user_instance=self, exception=e, tb=e.__traceback__) if self.user.environment.catch_exceptions: @@ -477,8 +480,7 @@ def get_next_task(self): extra_message = ", but you have set a 'task' attribute on your class - maybe you meant to set 'tasks'?" raise Exception(f"No tasks defined on {self.user.__class__.__name__}{extra_message}{warning_message}") else: - logger.warning(f"No tasks defined on {self.user.__class__.__name__}. {warning_message}") - raise StopUser() + raise NoTaskToRun(f"No tasks defined on {self.user.__class__.__name__}. {warning_message}") return random.choice(self.user.tasks) def execute_task(self, task): From 98034c5bd24ae2cdb6bc8a875f415c4511302d9b Mon Sep 17 00:00:00 2001 From: vijay59122 Date: Tue, 12 Nov 2024 08:33:11 +0530 Subject: [PATCH 07/10] fixed ruff formatting --- locust/user/task.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/locust/user/task.py b/locust/user/task.py index c69909b36e..5c3aa44e41 100644 --- a/locust/user/task.py +++ b/locust/user/task.py @@ -1,7 +1,13 @@ from __future__ import annotations -from locust.exception import InterruptTaskSet, MissingWaitTimeError, RescheduleTask, RescheduleTaskImmediately, \ - StopUser, NoTaskToRun +from locust.exception import ( + InterruptTaskSet, + MissingWaitTimeError, + RescheduleTask, + RescheduleTaskImmediately, + StopUser, + NoTaskToRun, +) import logging import random From 706c0a8144783fa2ce76d5c92d9e3f4c8bc960ff Mon Sep 17 00:00:00 2001 From: vijay59122 Date: Sun, 17 Nov 2024 09:23:31 +0530 Subject: [PATCH 08/10] fixed ruff format --- locust/user/task.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/locust/user/task.py b/locust/user/task.py index 5c3aa44e41..d5dbb526ac 100644 --- a/locust/user/task.py +++ b/locust/user/task.py @@ -3,10 +3,10 @@ from locust.exception import ( InterruptTaskSet, MissingWaitTimeError, + NoTaskToRun, RescheduleTask, RescheduleTaskImmediately, StopUser, - NoTaskToRun, ) import logging From 9c766e36aea95fd9f1ad66eb9e565f667c78ad9c Mon Sep 17 00:00:00 2001 From: vijay59122 Date: Sun, 17 Nov 2024 09:32:35 +0530 Subject: [PATCH 09/10] fixed ruff format --- locust/test/test_locust_class.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/locust/test/test_locust_class.py b/locust/test/test_locust_class.py index cb1af99774..dc0859744c 100644 --- a/locust/test/test_locust_class.py +++ b/locust/test/test_locust_class.py @@ -3,10 +3,11 @@ from locust.exception import ( CatchResponseError, InterruptTaskSet, + NoTaskToRun, RescheduleTask, RescheduleTaskImmediately, ResponseError, - StopUser, NoTaskToRun, + StopUser, ) import gevent From 09776b086aa48601189dddba414f3d2e5acc6ffc Mon Sep 17 00:00:00 2001 From: vijay59122 Date: Sun, 17 Nov 2024 10:06:08 +0530 Subject: [PATCH 10/10] fixed format issue in exception.py file --- locust/exception.py | 1 + 1 file changed, 1 insertion(+) diff --git a/locust/exception.py b/locust/exception.py index 914642679e..d99a362bd9 100644 --- a/locust/exception.py +++ b/locust/exception.py @@ -77,6 +77,7 @@ def __init__(self, *args: object, addr=None) -> None: class RunnerAlreadyExistsError(Exception): pass + class NoTaskToRun(Exception): def __init__(self, message): super().__init__(message)