locust 2.25.1.dev8__py3-none-any.whl → 2.26.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
locust/_version.py CHANGED
@@ -12,5 +12,5 @@ __version__: str
12
12
  __version_tuple__: VERSION_TUPLE
13
13
  version_tuple: VERSION_TUPLE
14
14
 
15
- __version__ = version = '2.25.1.dev8'
16
- __version_tuple__ = version_tuple = (2, 25, 1, 'dev8')
15
+ __version__ = version = '2.26.0'
16
+ __version_tuple__ = version_tuple = (2, 26, 0)
locust/argument_parser.py CHANGED
@@ -80,8 +80,7 @@ class LocustTomlConfigParser(configargparse.TomlConfigParser):
80
80
  result = OrderedDict()
81
81
 
82
82
  for section in self.sections:
83
- data = configargparse.get_toml_section(config, section)
84
- if data:
83
+ if data := configargparse.get_toml_section(config, section):
85
84
  for key, value in data.items():
86
85
  if isinstance(value, list):
87
86
  result[key] = value
@@ -667,7 +666,7 @@ Typically ONLY these options (and --locustfile) need to be specified on workers,
667
666
  nargs="*",
668
667
  metavar="<tag>",
669
668
  env_var="LOCUST_TAGS",
670
- help="List of tags to include in the test, so only tasks with any matching tags will be executed",
669
+ help="List of tags to include in the test, so only tasks with at least one matching tag will be executed",
671
670
  )
672
671
  tag_group.add_argument(
673
672
  "-E",
locust/clients.py CHANGED
@@ -2,8 +2,8 @@ from __future__ import annotations
2
2
 
3
3
  import re
4
4
  import time
5
+ from collections.abc import Generator
5
6
  from contextlib import contextmanager
6
- from typing import Generator
7
7
  from urllib.parse import urlparse, urlunparse
8
8
 
9
9
  import requests
@@ -12,11 +12,12 @@ import socket
12
12
  import time
13
13
  import traceback
14
14
  from base64 import b64encode
15
+ from collections.abc import Generator
15
16
  from contextlib import contextmanager
16
17
  from http.cookiejar import CookieJar
17
18
  from json.decoder import JSONDecodeError
18
19
  from ssl import SSLError
19
- from typing import Any, Callable, Generator, cast
20
+ from typing import Any, Callable, cast
20
21
  from urllib.parse import urlparse, urlunparse
21
22
 
22
23
  import gevent
@@ -404,8 +405,7 @@ class FastHttpUser(User):
404
405
  except Exception as e:
405
406
  error_lines = []
406
407
  for l in traceback.format_exc().split("\n"):
407
- m = self._callstack_regex.match(l)
408
- if m:
408
+ if m := self._callstack_regex.match(l):
409
409
  filename = re.sub(r"/(home|Users/\w*)/", "~/", m.group(1))
410
410
  error_lines.append(filename + ":" + m.group(2) + m.group(3))
411
411
  short_resp = resp.text[:200] if resp.text else resp.text
locust/dispatch.py CHANGED
@@ -1,14 +1,13 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  import contextlib
4
- import functools
5
4
  import itertools
6
5
  import math
7
- import sys
8
6
  import time
9
7
  from collections import defaultdict
8
+ from collections.abc import Generator, Iterator
10
9
  from operator import attrgetter
11
- from typing import TYPE_CHECKING, Generator, Iterator
10
+ from typing import TYPE_CHECKING
12
11
 
13
12
  import gevent
14
13
  from roundrobin import smooth
@@ -18,20 +17,6 @@ if TYPE_CHECKING:
18
17
  from locust.runners import WorkerNode
19
18
 
20
19
 
21
- def compatible_math_gcd(*args: int) -> int:
22
- """
23
- This function is a workaround for the fact that `math.gcd` in:
24
- - 3.5 <= Python < 3.9 doesn't accept more than two arguments.
25
- - 3.9 <= Python can accept more than two arguments.
26
- See more at https://docs.python.org/3.9/library/math.html#math.gcd
27
- """
28
- if (3, 5) <= sys.version_info < (3, 9):
29
- return functools.reduce(math.gcd, args)
30
- elif sys.version_info >= (3, 9):
31
- return math.gcd(*args)
32
- raise NotImplementedError("This function is only implemented for Python from 3.5")
33
-
34
-
35
20
  # To profile line-by-line, uncomment the code below (i.e. `import line_profiler ...`) and
36
21
  # place `@profile` on the functions/methods you wish to profile. Then, in the unit test you are
37
22
  # running, use `from locust.dispatch import profile; profile.print_stats()` at the end of the unit test.
@@ -406,7 +391,7 @@ class UsersDispatcher(Iterator):
406
391
  max_order_of_magnitude = _get_order_of_magnitude(min(abs(u[1]) for u in users))
407
392
  weights = tuple(int(u[1] * max_order_of_magnitude) for u in users)
408
393
 
409
- greatest_common_divisor = compatible_math_gcd(*weights)
394
+ greatest_common_divisor = math.gcd(*weights)
410
395
  normalized_values = [
411
396
  (
412
397
  user[0].__name__,
locust/event.py CHANGED
@@ -3,8 +3,9 @@ from __future__ import annotations
3
3
  import logging
4
4
  import time
5
5
  import traceback
6
+ from collections.abc import Generator
6
7
  from contextlib import contextmanager
7
- from typing import Any, Generator
8
+ from typing import Any
8
9
 
9
10
  from . import log
10
11
  from .exception import InterruptTaskSet, RescheduleTask, RescheduleTaskImmediately, StopUser
locust/html.py CHANGED
@@ -41,8 +41,7 @@ def get_html_report(
41
41
  start_ts = stats.start_time
42
42
  start_time = datetime.datetime.utcfromtimestamp(start_ts).strftime("%Y-%m-%d %H:%M:%S")
43
43
 
44
- end_ts = stats.last_request_timestamp
45
- if end_ts:
44
+ if end_ts := stats.last_request_timestamp:
46
45
  end_time = datetime.datetime.utcfromtimestamp(end_ts).strftime("%Y-%m-%d %H:%M:%S")
47
46
  else:
48
47
  end_time = start_time
locust/input_events.py CHANGED
@@ -104,8 +104,7 @@ def input_listener(key_to_func_map: dict[str, Callable]):
104
104
 
105
105
  try:
106
106
  while True:
107
- input = poller.poll()
108
- if input:
107
+ if input := poller.poll():
109
108
  for key in key_to_func_map:
110
109
  if input == key:
111
110
  key_to_func_map[key]()
locust/main.py CHANGED
@@ -216,8 +216,7 @@ def main():
216
216
  gc.collect() # avoid freezing garbage
217
217
  gc.freeze() # move all objects to perm gen so ref counts dont get updated
218
218
  for _ in range(options.processes):
219
- child_pid = gevent.fork()
220
- if child_pid:
219
+ if child_pid := gevent.fork():
221
220
  children.append(child_pid)
222
221
  logging.debug(f"Started child worker with pid #{child_pid}")
223
222
  else:
@@ -250,12 +249,8 @@ def main():
250
249
  # nothing more to do, just wait for the children to exit
251
250
  for child_pid in children:
252
251
  _, child_status = os.waitpid(child_pid, 0)
253
- try:
254
- if sys.version_info >= (3, 9):
255
- child_exit_code = os.waitstatus_to_exitcode(child_status)
256
- exit_code = max(exit_code, child_exit_code)
257
- except AttributeError:
258
- pass # dammit python 3.8...
252
+ child_exit_code = os.waitstatus_to_exitcode(child_status)
253
+ exit_code = max(exit_code, child_exit_code)
259
254
  sys.exit(exit_code)
260
255
  else:
261
256
  options.master = True
@@ -270,12 +265,8 @@ def main():
270
265
  try:
271
266
  _, child_status = os.waitpid(child_pid, os.WNOHANG)
272
267
  children.remove(child_pid)
273
- try:
274
- if sys.version_info >= (3, 9):
275
- child_exit_code = os.waitstatus_to_exitcode(child_status)
276
- exit_code = max(exit_code, child_exit_code)
277
- except AttributeError:
278
- pass # dammit python 3.8...
268
+ child_exit_code = os.waitstatus_to_exitcode(child_status)
269
+ exit_code = max(exit_code, child_exit_code)
279
270
  except OSError as e:
280
271
  if e.errno == errno.EINTR:
281
272
  time.sleep(0.1)
@@ -291,12 +282,8 @@ def main():
291
282
  pass # never mind, process was already dead
292
283
  for child_pid in children:
293
284
  _, child_status = os.waitpid(child_pid, 0)
294
- try:
295
- if sys.version_info >= (3, 9):
296
- child_exit_code = os.waitstatus_to_exitcode(child_status)
297
- exit_code = max(exit_code, child_exit_code)
298
- except AttributeError:
299
- pass # dammit python 3.8...
285
+ child_exit_code = os.waitstatus_to_exitcode(child_status)
286
+ exit_code = max(exit_code, child_exit_code)
300
287
  if exit_code > 1:
301
288
  logging.error(f"Bad response code from worker children: {exit_code}")
302
289
  # ensure master doesnt finish until output from workers has arrived
@@ -327,8 +314,7 @@ def main():
327
314
 
328
315
  # make sure specified User exists
329
316
  if options.user_classes:
330
- missing = set(options.user_classes) - set(user_classes.keys())
331
- if missing:
317
+ if missing := set(options.user_classes) - set(user_classes.keys()):
332
318
  logger.error(f"Unknown User(s): {', '.join(missing)}\n")
333
319
  sys.exit(1)
334
320
  else:
@@ -356,9 +342,6 @@ It's not high enough for load testing, and the OS didn't allow locust to increas
356
342
  See https://github.com/locustio/locust/wiki/Installation#increasing-maximum-number-of-open-files-limit for more info."""
357
343
  )
358
344
 
359
- if sys.version_info < (3, 9):
360
- logger.warning("Python 3.8 support is deprecated and will be removed soon")
361
-
362
345
  # create locust Environment
363
346
  locustfile_path = None if not locustfile else os.path.basename(locustfile)
364
347
 
locust/runners.py CHANGED
@@ -14,7 +14,7 @@ import time
14
14
  import traceback
15
15
  from abc import abstractmethod
16
16
  from collections import defaultdict
17
- from collections.abc import MutableMapping
17
+ from collections.abc import Iterator, MutableMapping, ValuesView
18
18
  from operator import (
19
19
  itemgetter,
20
20
  methodcaller,
@@ -24,10 +24,8 @@ from typing import (
24
24
  TYPE_CHECKING,
25
25
  Any,
26
26
  Callable,
27
- Iterator,
28
27
  NoReturn,
29
28
  TypedDict,
30
- ValuesView,
31
29
  cast,
32
30
  )
33
31
  from uuid import uuid4
locust/stats.py CHANGED
@@ -10,6 +10,10 @@ import signal
10
10
  import time
11
11
  from abc import abstractmethod
12
12
  from collections import OrderedDict, defaultdict, namedtuple
13
+ from collections import (
14
+ OrderedDict as OrderedDictType,
15
+ )
16
+ from collections.abc import Iterable
13
17
  from copy import copy
14
18
  from html import escape
15
19
  from itertools import chain
@@ -19,16 +23,12 @@ from typing import (
19
23
  TYPE_CHECKING,
20
24
  Any,
21
25
  Callable,
22
- Iterable,
23
26
  NoReturn,
24
27
  Protocol,
25
28
  TypedDict,
26
29
  TypeVar,
27
30
  cast,
28
31
  )
29
- from typing import (
30
- OrderedDict as OrderedDictType,
31
- )
32
32
 
33
33
  import gevent
34
34
 
@@ -177,8 +177,7 @@ def diff_response_time_dicts(latest: dict[int, int], old: dict[int, int]) -> dic
177
177
  """
178
178
  new = {}
179
179
  for t in latest:
180
- diff = latest[t] - old.get(t, 0)
181
- if diff:
180
+ if diff := latest[t] - old.get(t, 0):
182
181
  new[t] = diff
183
182
  return new
184
183
 
@@ -1,11 +1,10 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  import logging
4
-
5
- from typing import List, Union, Dict
6
4
  from types import TracebackType
5
+ from typing import Union
7
6
 
8
- LogMessage = List[Union[str, Dict[str, TracebackType]]]
7
+ LogMessage = list[Union[str, dict[str, TracebackType]]]
9
8
 
10
9
 
11
10
  class MockedLoggingHandler(logging.Handler):
@@ -27,8 +27,7 @@ class TestDebugging(DebugTestCase):
27
27
  pass
28
28
 
29
29
  def _stop_user():
30
- user = getattr(debug._env, "single_user_instance", None)
31
- if user:
30
+ if user := getattr(debug._env, "single_user_instance", None):
32
31
  user._state = LOCUST_STATE_STOPPING
33
32
 
34
33
  t = Timer(1, _stop_user)
@@ -2167,9 +2167,7 @@ class TestLargeScale(unittest.TestCase):
2167
2167
  dispatch_iteration_duration <= tol
2168
2168
  for dispatch_iteration_duration in users_dispatcher.dispatch_iteration_durations
2169
2169
  ),
2170
- "One or more dispatch took more than {:.0f}s to compute (max = {}ms)".format(
2171
- tol * 1000, 1000 * max(users_dispatcher.dispatch_iteration_durations)
2172
- ),
2170
+ f"One or more dispatch took more than {tol * 1000:.0f}s to compute (max = {1000 * max(users_dispatcher.dispatch_iteration_durations)}ms)",
2173
2171
  )
2174
2172
 
2175
2173
  self.assertEqual(_user_count(all_dispatched_users[-1]), target_user_count)
@@ -2181,9 +2179,7 @@ class TestLargeScale(unittest.TestCase):
2181
2179
  self.assertLessEqual(
2182
2180
  max(user_count_on_workers) - min(user_count_on_workers),
2183
2181
  1,
2184
- "One or more workers have too much users compared to the other workers when user count is {}".format(
2185
- _user_count(dispatch_users)
2186
- ),
2182
+ f"One or more workers have too much users compared to the other workers when user count is {_user_count(dispatch_users)}",
2187
2183
  )
2188
2184
 
2189
2185
  for i, dispatch_users in enumerate(all_dispatched_users):
@@ -2202,9 +2198,7 @@ class TestLargeScale(unittest.TestCase):
2202
2198
  self.assertLessEqual(
2203
2199
  error_percent,
2204
2200
  tol,
2205
- "Distribution for user class {} is off by more than {}% when user count is {}".format(
2206
- user_class, tol, _user_count(dispatch_users)
2207
- ),
2201
+ f"Distribution for user class {user_class} is off by more than {tol}% when user count is {_user_count(dispatch_users)}",
2208
2202
  )
2209
2203
 
2210
2204
  def test_ramp_down_from_100_000_to_0_users_with_50_user_classes_and_1000_workers_and_5000_spawn_rate(self):
@@ -2236,9 +2230,7 @@ class TestLargeScale(unittest.TestCase):
2236
2230
  dispatch_iteration_duration <= tol
2237
2231
  for dispatch_iteration_duration in users_dispatcher.dispatch_iteration_durations
2238
2232
  ),
2239
- "One or more dispatch took more than {:.0f}ms to compute (max = {}ms)".format(
2240
- tol * 1000, 1000 * max(users_dispatcher.dispatch_iteration_durations)
2241
- ),
2233
+ f"One or more dispatch took more than {tol * 1000:.0f}ms to compute (max = {1000 * max(users_dispatcher.dispatch_iteration_durations)}ms)",
2242
2234
  )
2243
2235
 
2244
2236
  self.assertEqual(_user_count(all_dispatched_users[-1]), 0)
@@ -2250,9 +2242,7 @@ class TestLargeScale(unittest.TestCase):
2250
2242
  self.assertLessEqual(
2251
2243
  max(user_count_on_workers) - min(user_count_on_workers),
2252
2244
  1,
2253
- "One or more workers have too much users compared to the other workers when user count is {}".format(
2254
- _user_count(dispatch_users)
2255
- ),
2245
+ f"One or more workers have too much users compared to the other workers when user count is {_user_count(dispatch_users)}",
2256
2246
  )
2257
2247
 
2258
2248
  for dispatch_users in all_dispatched_users[:-1]:
@@ -2267,9 +2257,7 @@ class TestLargeScale(unittest.TestCase):
2267
2257
  self.assertLessEqual(
2268
2258
  error_percent,
2269
2259
  tol,
2270
- "Distribution for user class {} is off by more than {}% when user count is {}".format(
2271
- user_class, tol, _user_count(dispatch_users)
2272
- ),
2260
+ f"Distribution for user class {user_class} is off by more than {tol}% when user count is {_user_count(dispatch_users)}",
2273
2261
  )
2274
2262
 
2275
2263
 
@@ -3448,9 +3436,7 @@ class TestRampUpUsersFromZeroWithFixed(unittest.TestCase):
3448
3436
  self.target_user_count = target_user_count
3449
3437
 
3450
3438
  def __str__(self):
3451
- return "<RampUpCase fixed_counts={} weights={} target_user_count={}>".format(
3452
- self.fixed_counts, self.weights, self.target_user_count
3453
- )
3439
+ return f"<RampUpCase fixed_counts={self.fixed_counts} weights={self.weights} target_user_count={self.target_user_count}>"
3454
3440
 
3455
3441
  def case_handler(self, cases: list[RampUpCase], expected: list[dict[str, int]], user_classes: list[type[User]]):
3456
3442
  self.assertEqual(len(cases), len(expected))
@@ -3734,8 +3720,6 @@ class TestRampUpDifferentUsers(unittest.TestCase):
3734
3720
 
3735
3721
  worker_node1 = WorkerNode("1")
3736
3722
 
3737
- sleep_time = 0.2
3738
-
3739
3723
  user_dispatcher = UsersDispatcher(worker_nodes=[worker_node1], user_classes=[User1, User2, User3])
3740
3724
 
3741
3725
  user_dispatcher.new_dispatch(target_user_count=3, spawn_rate=3)
@@ -3761,8 +3745,6 @@ class TestRampUpDifferentUsers(unittest.TestCase):
3761
3745
 
3762
3746
  worker_node1 = WorkerNode("1")
3763
3747
 
3764
- sleep_time = 0.2
3765
-
3766
3748
  user_dispatcher = UsersDispatcher(worker_nodes=[worker_node1], user_classes=[User1, User2, User3])
3767
3749
 
3768
3750
  user_dispatcher.new_dispatch(target_user_count=10, spawn_rate=10, user_classes=[User2])
@@ -3780,8 +3762,6 @@ class TestRampUpDifferentUsers(unittest.TestCase):
3780
3762
 
3781
3763
  worker_node1 = WorkerNode("1")
3782
3764
 
3783
- sleep_time = 0.2
3784
-
3785
3765
  user_dispatcher = UsersDispatcher(worker_nodes=[worker_node1], user_classes=[User1, User2, User3])
3786
3766
 
3787
3767
  user_dispatcher.new_dispatch(target_user_count=10, spawn_rate=10, user_classes=[User2])
@@ -3802,8 +3782,6 @@ class TestRampUpDifferentUsers(unittest.TestCase):
3802
3782
 
3803
3783
  worker_node1 = WorkerNode("1")
3804
3784
 
3805
- sleep_time = 0.2
3806
-
3807
3785
  user_dispatcher = UsersDispatcher(worker_nodes=[worker_node1], user_classes=[User1, User2, User3])
3808
3786
 
3809
3787
  user_dispatcher.new_dispatch(target_user_count=10, spawn_rate=10, user_classes=[User2])
@@ -3826,8 +3804,6 @@ class TestRampUpDifferentUsers(unittest.TestCase):
3826
3804
  worker_node2 = WorkerNode("2")
3827
3805
  worker_node3 = WorkerNode("3")
3828
3806
 
3829
- sleep_time = 0.2
3830
-
3831
3807
  user_dispatcher = UsersDispatcher(
3832
3808
  worker_nodes=[worker_node1, worker_node2, worker_node3], user_classes=[User1, User2, User3]
3833
3809
  )
@@ -3886,8 +3862,6 @@ class TestRampUpDifferentUsers(unittest.TestCase):
3886
3862
  worker_node2 = WorkerNode("2")
3887
3863
  worker_node3 = WorkerNode("3")
3888
3864
 
3889
- sleep_time = 0.2
3890
-
3891
3865
  user_dispatcher = UsersDispatcher(
3892
3866
  worker_nodes=[worker_node1, worker_node2, worker_node3], user_classes=[User1, User2, User3]
3893
3867
  )
locust/test/test_env.py CHANGED
@@ -36,7 +36,7 @@ class TestEnvironment(LocustTestCase):
36
36
 
37
37
  def test_user_classes_with_same_name_is_error(self):
38
38
  with self.assertRaises(ValueError) as e:
39
- environment = Environment(user_classes=[MyUserWithSameName1, MyUserWithSameName2])
39
+ Environment(user_classes=[MyUserWithSameName1, MyUserWithSameName2])
40
40
 
41
41
  self.assertEqual(
42
42
  e.exception.args[0],
@@ -186,7 +186,7 @@ class TestEnvironment(LocustTestCase):
186
186
  pass
187
187
 
188
188
  with self.assertRaises(ValueError) as e:
189
- environment = Environment(user_classes=[MyUser1, MyUser2])
189
+ Environment(user_classes=[MyUser1, MyUser2])
190
190
 
191
191
  self.assertEqual(
192
192
  e.exception.args[0],
@@ -269,7 +269,7 @@ class TestEnvironment(LocustTestCase):
269
269
  available_user_classes={"User1": MyUser1, "User2": MyUser2},
270
270
  available_user_tasks={"User1": MyUser1.tasks, "User2": MyUser2.tasks},
271
271
  )
272
- worker = worker_env.create_worker_runner("127.0.0.1", master.server.port)
272
+ worker_env.create_worker_runner("127.0.0.1", master.server.port)
273
273
 
274
274
  master_env.update_user_class({"user_class_name": "User1", "host": "http://localhost", "tasks": ["my_task_2"]})
275
275
 
@@ -96,7 +96,7 @@ class TestFastHttpSession(WebserverTestCase):
96
96
  def test_slow_redirect(self):
97
97
  s = self.get_client()
98
98
  url = "/redirect?url=/redirect&delay=0.5"
99
- r = s.get(url)
99
+ s.get(url)
100
100
  stats = self.runner.stats.get(url, method="GET")
101
101
  self.assertEqual(1, stats.num_requests)
102
102
  self.assertGreater(stats.avg_response_time, 500)
@@ -187,7 +187,7 @@ class TestFastHttpSession(WebserverTestCase):
187
187
  with s.get("/fail", catch_response=True) as r:
188
188
  r.success()
189
189
  raise OtherException("wtf")
190
- except OtherException as e:
190
+ except OtherException:
191
191
  pass
192
192
  else:
193
193
  self.fail("OtherException should have been raised")
@@ -197,14 +197,14 @@ class TestFastHttpSession(WebserverTestCase):
197
197
 
198
198
  def test_catch_response_default_success(self):
199
199
  s = self.get_client()
200
- with s.get("/ultra_fast", catch_response=True) as r:
200
+ with s.get("/ultra_fast", catch_response=True):
201
201
  pass
202
202
  self.assertEqual(1, self.environment.stats.get("/ultra_fast", "GET").num_requests)
203
203
  self.assertEqual(0, self.environment.stats.get("/ultra_fast", "GET").num_failures)
204
204
 
205
205
  def test_catch_response_default_fail(self):
206
206
  s = self.get_client()
207
- with s.get("/fail", catch_response=True) as r:
207
+ with s.get("/fail", catch_response=True):
208
208
  pass
209
209
  self.assertEqual(1, self.environment.stats.total.num_requests)
210
210
  self.assertEqual(1, self.environment.stats.total.num_failures)
@@ -301,7 +301,7 @@ class TestRequestStatsWithWebserver(WebserverTestCase):
301
301
 
302
302
  l = MyUser(self.environment)
303
303
  path = "/no_content_length"
304
- r = l.client.get(path)
304
+ l.client.get(path)
305
305
  self.assertEqual(
306
306
  self.runner.stats.get(path, "GET").avg_content_length,
307
307
  len("This response does not have content-length in the header"),
@@ -313,7 +313,7 @@ class TestRequestStatsWithWebserver(WebserverTestCase):
313
313
 
314
314
  l = MyUser(self.environment)
315
315
  path = "/no_content_length"
316
- r = l.client.get(path, stream=True)
316
+ l.client.get(path, stream=True)
317
317
  self.assertEqual(0, self.runner.stats.get(path, "GET").avg_content_length)
318
318
 
319
319
  def test_request_stats_named_endpoint(self):
@@ -526,7 +526,7 @@ class TestFastHttpUserClass(WebserverTestCase):
526
526
  def test_slow_redirect(self):
527
527
  s = FastHttpSession(self.environment, "http://127.0.0.1:%i" % self.port, user=None)
528
528
  url = "/redirect?url=/redirect&delay=0.5"
529
- r = s.get(url)
529
+ s.get(url)
530
530
  stats = self.runner.stats.get(url, method="GET")
531
531
  self.assertEqual(1, stats.num_requests)
532
532
  self.assertGreater(stats.avg_response_time, 500)
@@ -650,7 +650,7 @@ class TestFastHttpCatchResponse(WebserverTestCase):
650
650
  self.assertEqual(1, self.num_success)
651
651
 
652
652
  def test_catch_response_http_fail(self):
653
- with self.user.client.get("/fail", catch_response=True) as response:
653
+ with self.user.client.get("/fail", catch_response=True):
654
654
  pass
655
655
  self.assertEqual(1, self.num_failures)
656
656
  self.assertEqual(0, self.num_success)
@@ -683,7 +683,7 @@ class TestFastHttpCatchResponse(WebserverTestCase):
683
683
  class MyTaskSet(TaskSet):
684
684
  @task
685
685
  def interrupted_task(self):
686
- with self.client.get("/ultra_fast", catch_response=True) as r:
686
+ with self.client.get("/ultra_fast", catch_response=True):
687
687
  raise InterruptTaskSet()
688
688
 
689
689
  class MyUser(FastHttpUser):
locust/test/test_http.py CHANGED
@@ -65,7 +65,7 @@ class TestHttpSession(WebserverTestCase):
65
65
  def test_slow_redirect(self):
66
66
  s = self.get_client()
67
67
  url = "/redirect?url=/redirect&delay=0.5"
68
- r = s.get(url)
68
+ s.get(url)
69
69
  stats = self.runner.stats.get(url, method="GET")
70
70
  self.assertEqual(1, stats.num_requests)
71
71
  self.assertGreater(stats.avg_response_time, 500)
@@ -217,7 +217,7 @@ class TestHttpSession(WebserverTestCase):
217
217
  with s.get("/fail", catch_response=True) as r:
218
218
  r.success()
219
219
  raise OtherException("wtf")
220
- except OtherException as e:
220
+ except OtherException:
221
221
  pass
222
222
  else:
223
223
  self.fail("OtherException should have been raised")
@@ -228,9 +228,9 @@ class TestHttpSession(WebserverTestCase):
228
228
  def test_catch_response_response_error(self):
229
229
  s = self.get_client()
230
230
  try:
231
- with s.get("/fail", catch_response=True) as r:
231
+ with s.get("/fail", catch_response=True):
232
232
  raise ResponseError("response error")
233
- except ResponseError as e:
233
+ except ResponseError:
234
234
  self.fail("ResponseError should not have been raised")
235
235
 
236
236
  self.assertEqual(1, self.environment.stats.total.num_requests)
@@ -238,14 +238,14 @@ class TestHttpSession(WebserverTestCase):
238
238
 
239
239
  def test_catch_response_default_success(self):
240
240
  s = self.get_client()
241
- with s.get("/ultra_fast", catch_response=True) as r:
241
+ with s.get("/ultra_fast", catch_response=True):
242
242
  pass
243
243
  self.assertEqual(1, self.environment.stats.get("/ultra_fast", "GET").num_requests)
244
244
  self.assertEqual(0, self.environment.stats.get("/ultra_fast", "GET").num_failures)
245
245
 
246
246
  def test_catch_response_default_fail(self):
247
247
  s = self.get_client()
248
- with s.get("/fail", catch_response=True) as r:
248
+ with s.get("/fail", catch_response=True):
249
249
  pass
250
250
  self.assertEqual(1, self.environment.stats.total.num_requests)
251
251
  self.assertEqual(1, self.environment.stats.total.num_failures)
@@ -260,7 +260,7 @@ class TestHttpSession(WebserverTestCase):
260
260
 
261
261
  self.environment.events.request.add_listener(on_request)
262
262
 
263
- with s.get("/wrong_url/01", name="replaced_url_name") as r:
263
+ with s.get("/wrong_url/01", name="replaced_url_name"):
264
264
  pass
265
265
 
266
266
  self.assertIn("for url: replaced_url_name", str(kwargs["exception"]))
@@ -3,12 +3,11 @@ from locust.env import Environment
3
3
  from locust.exception import StopUser
4
4
 
5
5
  from collections import defaultdict
6
- from typing import DefaultDict
7
6
  from unittest import TestCase
8
7
 
9
8
 
10
9
  class InterruptableTaskSet(SequentialTaskSet):
11
- counter: DefaultDict[str, int] = defaultdict(int)
10
+ counter: defaultdict[str, int] = defaultdict(int)
12
11
 
13
12
  def on_start(self):
14
13
  super().on_start()
@@ -748,19 +748,19 @@ class TestCatchResponse(WebserverTestCase):
748
748
  self.assertEqual(1, self.num_failures)
749
749
  self.assertEqual(0, self.num_success)
750
750
 
751
- with self.locust.client.get("/ultra_fast", catch_response=True) as response:
751
+ with self.locust.client.get("/ultra_fast", catch_response=True):
752
752
  pass
753
753
  self.assertEqual(1, self.num_failures)
754
754
  self.assertEqual(1, self.num_success)
755
755
 
756
- with self.locust.client.get("/ultra_fast", catch_response=True) as response:
756
+ with self.locust.client.get("/ultra_fast", catch_response=True):
757
757
  raise ResponseError("Not working")
758
758
 
759
759
  self.assertEqual(2, self.num_failures)
760
760
  self.assertEqual(1, self.num_success)
761
761
 
762
762
  def test_catch_response_http_fail(self):
763
- with self.locust.client.get("/fail", catch_response=True) as response:
763
+ with self.locust.client.get("/fail", catch_response=True):
764
764
  pass
765
765
  self.assertEqual(1, self.num_failures)
766
766
  self.assertEqual(0, self.num_success)
@@ -793,7 +793,7 @@ class TestCatchResponse(WebserverTestCase):
793
793
  class MyTaskSet(TaskSet):
794
794
  @task
795
795
  def interrupted_task(self):
796
- with self.client.get("/ultra_fast", catch_response=True) as r:
796
+ with self.client.get("/ultra_fast", catch_response=True):
797
797
  raise InterruptTaskSet()
798
798
 
799
799
  class MyUser(HttpUser):
locust/test/test_main.py CHANGED
@@ -483,7 +483,6 @@ class StandaloneIntegrationTests(ProcessIntegrationTest):
483
483
  self.assertIn("Shutting down (exit code 0)", stderr)
484
484
  self.assertEqual(0, proc.returncode)
485
485
 
486
- @unittest.skipIf(sys.version_info < (3, 9), reason="dies in 3.8 on GH and I cant be bothered to investigate it")
487
486
  def test_default_headless_spawn_options_with_shape(self):
488
487
  content = MOCK_LOCUSTFILE_CONTENT + textwrap.dedent(
489
488
  """
@@ -812,7 +811,7 @@ class StandaloneIntegrationTests(ProcessIntegrationTest):
812
811
  try:
813
812
  response = requests.get(f"http://localhost:{port}/")
814
813
  except ConnectionError:
815
- succcess = False
814
+ success = False
816
815
  try:
817
816
  _, stderr = proc.communicate(timeout=5)
818
817
  except subprocess.TimeoutExpired:
@@ -1085,7 +1084,7 @@ class StandaloneIntegrationTests(ProcessIntegrationTest):
1085
1084
  with mock_locustfile() as mocked:
1086
1085
  with temporary_file("", suffix=".html") as html_report_file_path:
1087
1086
  try:
1088
- output = subprocess.check_output(
1087
+ subprocess.check_output(
1089
1088
  [
1090
1089
  "locust",
1091
1090
  "-f",
@@ -1618,9 +1617,10 @@ class SecondUser(HttpUser):
1618
1617
  pass
1619
1618
  """
1620
1619
  )
1621
- with mock_locustfile(content=LOCUSTFILE_CONTENT) as mocked, patch_env(
1622
- "LOCUST_WAIT_FOR_WORKERS_REPORT_AFTER_RAMP_UP", "0.01"
1623
- ) as _:
1620
+ with (
1621
+ mock_locustfile(content=LOCUSTFILE_CONTENT) as mocked,
1622
+ patch_env("LOCUST_WAIT_FOR_WORKERS_REPORT_AFTER_RAMP_UP", "0.01") as _,
1623
+ ):
1624
1624
  proc = subprocess.Popen(
1625
1625
  [
1626
1626
  "locust",
@@ -2225,7 +2225,6 @@ class AnyUser(User):
2225
2225
 
2226
2226
  self.assertNotIn("Traceback", stderr)
2227
2227
  self.assertIn("INFO/locust.runners: sys.exit(42) called", stderr)
2228
- if sys.version_info >= (3, 9):
2229
- self.assertEqual(status_code, 42)
2228
+ self.assertEqual(status_code, 42)
2230
2229
  self.assertNotIn("Traceback", master_stderr)
2231
2230
  self.assertIn("failed to send heartbeat, setting state to missing", master_stderr)
@@ -69,6 +69,8 @@ class TestParser(unittest.TestCase):
69
69
  web-port = 45787
70
70
  headless = true
71
71
  tags = ["Critical", "Normal"]
72
+ [tool.something_else]
73
+ this = "should be ignored by locust"
72
74
  """
73
75
 
74
76
  file.write(config_data)
@@ -248,7 +250,7 @@ class TestArgumentParser(LocustTestCase):
248
250
  def test_parse_locustfile_empty_directory_error(self):
249
251
  with mock.patch("sys.stderr", new=StringIO()):
250
252
  with self.assertRaises(SystemExit):
251
- locustfiles = parse_locustfile_option(
253
+ parse_locustfile_option(
252
254
  args=[
253
255
  "-f",
254
256
  self.parent_dir.name,
@@ -258,7 +260,7 @@ class TestArgumentParser(LocustTestCase):
258
260
  def test_parse_locustfile_invalid_directory_error(self):
259
261
  with mock.patch("sys.stderr", new=StringIO()):
260
262
  with self.assertRaises(SystemExit):
261
- locustfiles = parse_locustfile_option(
263
+ parse_locustfile_option(
262
264
  args=[
263
265
  "-f",
264
266
  "non_existent_dir",
@@ -401,13 +403,12 @@ class TestFindLocustfiles(LocustTestCase):
401
403
  def test_find_locustfiles_with_multiple_locustfiles(self):
402
404
  with mock_locustfile() as mocked1:
403
405
  with mock_locustfile() as mocked2:
404
- with mock_locustfile() as mocked3:
405
- locustfiles = find_locustfiles([mocked1.file_path, mocked2.file_path], False)
406
+ locustfiles = find_locustfiles([mocked1.file_path, mocked2.file_path], False)
406
407
 
407
- self.assertIn(mocked1.file_path, locustfiles)
408
- self.assertIn(mocked2.file_path, locustfiles)
408
+ self.assertIn(mocked1.file_path, locustfiles)
409
+ self.assertIn(mocked2.file_path, locustfiles)
409
410
 
410
- assert 2 == len(locustfiles)
411
+ assert 2 == len(locustfiles)
411
412
 
412
413
  def test_find_locustfiles_error_for_invalid_file_extension(self):
413
414
  with mock.patch("sys.stderr", new=StringIO()):
@@ -450,7 +451,7 @@ class TestLocustfileIsDirectory(LocustTestCase):
450
451
 
451
452
  def test_locustfile_is_directory_single_locustfile_without_file_extension(self):
452
453
  prefix_name = "foobar"
453
- with NamedTemporaryFile(prefix=prefix_name, suffix=".py") as mocked:
454
+ with NamedTemporaryFile(prefix=prefix_name, suffix=".py"):
454
455
  is_dir = locustfile_is_directory([prefix_name])
455
456
  assert not is_dir
456
457
 
@@ -992,8 +992,9 @@ class TestMasterWorkerRunners(LocustTestCase):
992
992
  context={},
993
993
  )
994
994
 
995
- with mock.patch("locust.runners.WORKER_REPORT_INTERVAL", new=0.3), patch_env(
996
- "LOCUST_WAIT_FOR_WORKERS_REPORT_AFTER_RAMP_UP", "0.1"
995
+ with (
996
+ mock.patch("locust.runners.WORKER_REPORT_INTERVAL", new=0.3),
997
+ patch_env("LOCUST_WAIT_FOR_WORKERS_REPORT_AFTER_RAMP_UP", "0.1"),
997
998
  ):
998
999
  # start a Master runner
999
1000
  options = parse_options(["--enable-rebalancing"])
@@ -1419,9 +1420,12 @@ class TestMasterWorkerRunners(LocustTestCase):
1419
1420
  return None
1420
1421
 
1421
1422
  locust_worker_additional_wait_before_ready_after_stop = 5
1422
- with mock.patch("locust.runners.WORKER_REPORT_INTERVAL", new=0.3), patch_env(
1423
- "LOCUST_WORKER_ADDITIONAL_WAIT_BEFORE_READY_AFTER_STOP",
1424
- str(locust_worker_additional_wait_before_ready_after_stop),
1423
+ with (
1424
+ mock.patch("locust.runners.WORKER_REPORT_INTERVAL", new=0.3),
1425
+ patch_env(
1426
+ "LOCUST_WORKER_ADDITIONAL_WAIT_BEFORE_READY_AFTER_STOP",
1427
+ str(locust_worker_additional_wait_before_ready_after_stop),
1428
+ ),
1425
1429
  ):
1426
1430
  stop_timeout = 5
1427
1431
  master_env = Environment(
@@ -1676,9 +1680,12 @@ class TestMasterWorkerRunners(LocustTestCase):
1676
1680
  user_class.weight = random.uniform(1, 20)
1677
1681
 
1678
1682
  locust_worker_additional_wait_before_ready_after_stop = 5
1679
- with mock.patch("locust.runners.WORKER_REPORT_INTERVAL", new=0.3), patch_env(
1680
- "LOCUST_WORKER_ADDITIONAL_WAIT_BEFORE_READY_AFTER_STOP",
1681
- str(locust_worker_additional_wait_before_ready_after_stop),
1683
+ with (
1684
+ mock.patch("locust.runners.WORKER_REPORT_INTERVAL", new=0.3),
1685
+ patch_env(
1686
+ "LOCUST_WORKER_ADDITIONAL_WAIT_BEFORE_READY_AFTER_STOP",
1687
+ str(locust_worker_additional_wait_before_ready_after_stop),
1688
+ ),
1682
1689
  ):
1683
1690
  stop_timeout = 5
1684
1691
  master_env = Environment(
@@ -1706,12 +1713,7 @@ class TestMasterWorkerRunners(LocustTestCase):
1706
1713
  while master.state != STATE_STOPPED:
1707
1714
  self.assertTrue(time.time() - ts <= master_env.shape_class.stages[-1][0] + 60, master.state)
1708
1715
  print(
1709
- "{:.2f}/{:.2f} | {} | {:.0f} | ".format(
1710
- time.time() - ts,
1711
- master_env.shape_class.stages[-1][0],
1712
- master.state,
1713
- sum(master.reported_user_classes_count.values()),
1714
- )
1716
+ f"{time.time() - ts:.2f}/{master_env.shape_class.stages[-1][0]:.2f} | {master.state} | {sum(master.reported_user_classes_count.values()):.0f} | "
1715
1717
  + json.dumps(dict(sorted(master.reported_user_classes_count.items(), key=itemgetter(0))))
1716
1718
  )
1717
1719
  sleep(1)
@@ -1822,9 +1824,12 @@ class TestMasterWorkerRunners(LocustTestCase):
1822
1824
  return None
1823
1825
 
1824
1826
  locust_worker_additional_wait_before_ready_after_stop = 2
1825
- with mock.patch("locust.runners.WORKER_REPORT_INTERVAL", new=0.3), patch_env(
1826
- "LOCUST_WORKER_ADDITIONAL_WAIT_BEFORE_READY_AFTER_STOP",
1827
- str(locust_worker_additional_wait_before_ready_after_stop),
1827
+ with (
1828
+ mock.patch("locust.runners.WORKER_REPORT_INTERVAL", new=0.3),
1829
+ patch_env(
1830
+ "LOCUST_WORKER_ADDITIONAL_WAIT_BEFORE_READY_AFTER_STOP",
1831
+ str(locust_worker_additional_wait_before_ready_after_stop),
1832
+ ),
1828
1833
  ):
1829
1834
  master_env = Environment(user_classes=[TestUser1], shape_class=TestShape())
1830
1835
 
@@ -2192,8 +2197,9 @@ class TestMasterRunner(LocustRunnerTestCase):
2192
2197
  def my_task(self):
2193
2198
  gevent.sleep(600)
2194
2199
 
2195
- with mock.patch("locust.rpc.rpc.Server", mocked_rpc()) as server, patch_env(
2196
- "LOCUST_WAIT_FOR_WORKERS_REPORT_AFTER_RAMP_UP", "0.1"
2200
+ with (
2201
+ mock.patch("locust.rpc.rpc.Server", mocked_rpc()) as server,
2202
+ patch_env("LOCUST_WAIT_FOR_WORKERS_REPORT_AFTER_RAMP_UP", "0.1"),
2197
2203
  ):
2198
2204
  master = self.get_runner(user_classes=[TestUser])
2199
2205
  server.mocked_send(Message("client_ready", __version__, "fake_client1"))
@@ -2220,8 +2226,9 @@ class TestMasterRunner(LocustRunnerTestCase):
2220
2226
  def my_task(self):
2221
2227
  gevent.sleep(600)
2222
2228
 
2223
- with mock.patch("locust.rpc.rpc.Server", mocked_rpc()) as server, patch_env(
2224
- "LOCUST_WAIT_FOR_WORKERS_REPORT_AFTER_RAMP_UP", "0.1"
2229
+ with (
2230
+ mock.patch("locust.rpc.rpc.Server", mocked_rpc()) as server,
2231
+ patch_env("LOCUST_WAIT_FOR_WORKERS_REPORT_AFTER_RAMP_UP", "0.1"),
2225
2232
  ):
2226
2233
  master = self.get_runner(user_classes=[TestUser])
2227
2234
  server.mocked_send(Message("client_ready", __version__, "fake_client1"))
@@ -2291,8 +2298,9 @@ class TestMasterRunner(LocustRunnerTestCase):
2291
2298
  def my_task(self):
2292
2299
  gevent.sleep(600)
2293
2300
 
2294
- with mock.patch("locust.rpc.rpc.Server", mocked_rpc()) as server, patch_env(
2295
- "LOCUST_WAIT_FOR_WORKERS_REPORT_AFTER_RAMP_UP", "0.1"
2301
+ with (
2302
+ mock.patch("locust.rpc.rpc.Server", mocked_rpc()) as server,
2303
+ patch_env("LOCUST_WAIT_FOR_WORKERS_REPORT_AFTER_RAMP_UP", "0.1"),
2296
2304
  ):
2297
2305
  master = self.get_runner(user_classes=[TestUser])
2298
2306
  server.mocked_send(Message("client_ready", __version__, "fake_client1"))
@@ -3154,8 +3162,9 @@ class TestMasterRunner(LocustRunnerTestCase):
3154
3162
  assert_cache_hits()
3155
3163
 
3156
3164
  master._wait_for_workers_report_after_ramp_up.cache_clear()
3157
- with mock.patch("locust.runners.WORKER_REPORT_INTERVAL", new=1.5), patch_env(
3158
- "LOCUST_WAIT_FOR_WORKERS_REPORT_AFTER_RAMP_UP", "5.7 * WORKER_REPORT_INTERVAL"
3165
+ with (
3166
+ mock.patch("locust.runners.WORKER_REPORT_INTERVAL", new=1.5),
3167
+ patch_env("LOCUST_WAIT_FOR_WORKERS_REPORT_AFTER_RAMP_UP", "5.7 * WORKER_REPORT_INTERVAL"),
3159
3168
  ):
3160
3169
  self.assertEqual(master._wait_for_workers_report_after_ramp_up(), 5.7 * 1.5)
3161
3170
  assert_cache_hits()
@@ -3538,7 +3547,6 @@ class TestWorkerRunner(LocustTestCase):
3538
3547
  pass
3539
3548
 
3540
3549
  with mock.patch("locust.rpc.rpc.Client", mocked_rpc(raise_on_close=False)) as client:
3541
- client_id = id(client)
3542
3550
  worker = self.get_runner(environment=Environment(), user_classes=[MyUser], client=client)
3543
3551
  client.mocked_send(
3544
3552
  Message(
locust/test/test_web.py CHANGED
@@ -1110,11 +1110,7 @@ class TestWebUI(LocustTestCase, _HeaderCheckMixin):
1110
1110
  self.environment.available_user_classes = {"User1": MyUser, "User2": MyUser2}
1111
1111
  self.environment.available_user_tasks = {"User1": MyUser.tasks, "User2": MyUser2.tasks}
1112
1112
 
1113
- users = {"User1": MyUser.json(), "User2": MyUser2.json()}
1114
- available_user_tasks = {"User1": ["my_task", "my_task_2"], "User2": []}
1115
-
1116
- # environment.update_user_class({"user_class_name": "User1", "host": "http://localhost", "tasks": ["my_task_2"]})
1117
- response = requests.post(
1113
+ requests.post(
1118
1114
  "http://127.0.0.1:%i/user" % self.web_port,
1119
1115
  json={"user_class_name": "User1", "host": "http://localhost", "tasks": ["my_task_2"]},
1120
1116
  )
@@ -1290,7 +1286,7 @@ class TestModernWebUI(LocustTestCase, _HeaderCheckMixin):
1290
1286
  def setUp(self):
1291
1287
  super().setUp()
1292
1288
 
1293
- parser = get_parser(default_config_files=[])
1289
+ get_parser(default_config_files=[])
1294
1290
  self.stats = self.environment.stats
1295
1291
 
1296
1292
  self.web_ui = self.environment.create_web_ui("127.0.0.1", 0, modern_ui=True)
locust/test/testcases.py CHANGED
@@ -34,8 +34,7 @@ def fast():
34
34
 
35
35
  @app.route("/slow")
36
36
  def slow():
37
- delay = request.args.get("delay")
38
- if delay:
37
+ if delay := request.args.get("delay"):
39
38
  gevent.sleep(float(delay))
40
39
  else:
41
40
  gevent.sleep(random.choice([0.5, 1, 1.5]))
@@ -85,8 +84,7 @@ def status_204():
85
84
 
86
85
  @app.route("/redirect", methods=["GET", "POST"])
87
86
  def do_redirect():
88
- delay = request.args.get("delay")
89
- if delay:
87
+ if delay := request.args.get("delay"):
90
88
  gevent.sleep(float(delay))
91
89
  url = request.args.get("url", "/ultra_fast")
92
90
  return redirect(url)
locust/user/task.py CHANGED
@@ -10,7 +10,6 @@ from typing import (
10
10
  TYPE_CHECKING,
11
11
  Callable,
12
12
  Protocol,
13
- Type,
14
13
  TypeVar,
15
14
  final,
16
15
  overload,
@@ -25,7 +24,7 @@ if TYPE_CHECKING:
25
24
 
26
25
 
27
26
  logger = logging.getLogger(__name__)
28
- TaskT = TypeVar("TaskT", Callable[..., None], Type["TaskSet"])
27
+ TaskT = TypeVar("TaskT", Callable[..., None], type["TaskSet"])
29
28
 
30
29
  LOCUST_STATE_RUNNING, LOCUST_STATE_WAITING, LOCUST_STATE_STOPPING = ["running", "waiting", "stopping"]
31
30
 
locust/web.py CHANGED
@@ -604,8 +604,7 @@ class WebUI:
604
604
 
605
605
  options = self.environment.parsed_options
606
606
 
607
- is_distributed = isinstance(self.environment.runner, MasterRunner)
608
- if is_distributed:
607
+ if is_distributed := isinstance(self.environment.runner, MasterRunner):
609
608
  worker_count = self.environment.runner.worker_count
610
609
  else:
611
610
  worker_count = 0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: locust
3
- Version: 2.25.1.dev8
3
+ Version: 2.26.0
4
4
  Summary: Developer friendly load testing framework
5
5
  License: MIT
6
6
  Project-URL: Homepage, https://github.com/locustio/locust
@@ -32,7 +32,7 @@ Requires-Dist: Werkzeug >=2.0.0
32
32
  Requires-Dist: requests >=2.26.0
33
33
  Requires-Dist: msgpack >=1.0.0
34
34
  Requires-Dist: pyzmq >=25.0.0
35
- Requires-Dist: geventhttpclient >=2.2.1
35
+ Requires-Dist: geventhttpclient ==2.2.1
36
36
  Requires-Dist: ConfigArgParse >=1.5.5
37
37
  Requires-Dist: psutil >=5.9.1
38
38
  Requires-Dist: Flask-Login >=0.6.3
@@ -44,7 +44,7 @@ Requires-Dist: tomli >=1.1.0 ; python_version < "3.11"
44
44
  # Locust
45
45
 
46
46
  [![PyPI](https://img.shields.io/pypi/v/locust.svg)](https://pypi.org/project/locust/)
47
- ![Python Version from PEP 621 TOML](https://img.shields.io/python/required-version-toml?tomlFilePath=https%3A%2F%2Fraw.githubusercontent.com%2Flocustio%2Flocust%2Fmaster%2Fpyproject.toml&link=https%3A%2F%2Fpypi.org%2Fproject%2Flocust)
47
+ ![Python Version from PEP 621 TOML](https://img.shields.io/python/required-version-toml?tomlFilePath=https%3A%2F%2Fraw.githubusercontent.com%2Flocustio%2Flocust%2Fmaster%2Fpyproject.toml)
48
48
  [![Downloads](https://pepy.tech/badge/locust/week)](https://pepy.tech/project/locust)
49
49
  [![Build Status](https://github.com/locustio/locust/workflows/Tests/badge.svg)](https://github.com/locustio/locust/actions?query=workflow%3ATests)
50
50
  [![GitHub contributors](https://img.shields.io/github/contributors/locustio/locust.svg)](https://github.com/locustio/locust/graphs/contributors)
@@ -1,24 +1,24 @@
1
1
  locust/__init__.py,sha256=g6oA-Ba_hs3gLWVf5MKJ1mvfltI8MFnDWG8qslqm8yg,1402
2
2
  locust/__main__.py,sha256=vBQ82334kX06ImDbFlPFgiBRiLIinwNk3z8Khs6hd74,31
3
- locust/_version.py,sha256=W2iy6zTQVMHHk-IWLxYUWz82mKJaHowf07jlAUmqwRc,426
4
- locust/argument_parser.py,sha256=W0X5t-9BFq1DtOBgTBbMoDYBIXfWEqUD7CZ5Rn-i6LQ,32016
5
- locust/clients.py,sha256=o3G9welWb-zhgDUM5TKnMVFMJckr_m0FI8Dxn3OtBUA,14810
3
+ locust/_version.py,sha256=fMCGN_nkzccFJR0ERimrQlI738fFJWzDZ_f2UP5Pbqs,413
4
+ locust/argument_parser.py,sha256=gOyB1rqEEFNVkhGa-oAuCxf573aB_lATSY9w6FlCbHk,32008
5
+ locust/clients.py,sha256=-vKHkTkUQwYUXUpuROvHdiAbSbOPY8s4V7xFDF5KU1A,14819
6
6
  locust/debug.py,sha256=We6Z9W0btkKSc7PxWmrZx-xMynvOOsKhG6jmDgQin0g,5134
7
- locust/dispatch.py,sha256=sPtRRer_dJVOaLaIvVriIf4gLduvCcRf11O-E7ohzSc,20101
7
+ locust/dispatch.py,sha256=t1gMvCdE7SFq7OIyYEhmKi5nW_8_d__iNUJgf4P_c6c,19502
8
8
  locust/env.py,sha256=nd6ui1bv6n-kkLkP3r61ZkskDY627dsKOAkYHhtOW7o,12472
9
- locust/event.py,sha256=Dip3aRKyd4MhAkfd5nPYmWcGKtQEX8NH1mHT74INZT4,7713
9
+ locust/event.py,sha256=xgNKbcejxy1TNUfIdgV75KgD2_BOwQmvjrJ4hWuydRw,7740
10
10
  locust/exception.py,sha256=jGgJ32ubuf4pWdlaVOkbh2Y0LlG0_DHi-lv3ib8ppOE,1791
11
- locust/html.py,sha256=S2vucumZbGADt0PKv__Aow_kt-MpbCCxBqMO9QiRcUg,5718
12
- locust/input_events.py,sha256=QBO6Kb0bmNLZHaIvcBORk57CvCJHAYVB5ILfpV8Lrfc,3292
11
+ locust/html.py,sha256=IrOYxmmowzcO96c9fytzR4U0lifTJyMTA7Rd96WOXkk,5708
12
+ locust/input_events.py,sha256=WZtjFMJQpPszxgqwZkxzRBOhygHIersHsvt-9S34M9k,3271
13
13
  locust/log.py,sha256=2IVp9YL4ZPfWdj3sBFuOHfgneg3g7m7tUGR-sy2s3E8,3155
14
- locust/main.py,sha256=Yi0vMJ3HVNqmjbZXBwaK8N-SbzHyaGRnr46hgxpkP0M,28989
14
+ locust/main.py,sha256=emuULU-y1SmHTLcLqfOiZn_SnZzWDcf_IYRmB4Yc348,28194
15
15
  locust/py.typed,sha256=gkWLl8yD4mIZnNYYAIRM8g9VarLvWmTAFeUfEbxJLBw,65
16
- locust/runners.py,sha256=8z-axnOs3yLWjOoc91rQzQH6hp6qu3ZpkBQ_IGZeFE0,67978
16
+ locust/runners.py,sha256=OybWcJfhrr_UVWWPfmpiDM3fQF_mrR3D_GcAMArWt78,67970
17
17
  locust/shape.py,sha256=t-lwBS8LOjWcKXNL7j2U3zroIXJ1b0fazUwpRYQOKXw,1973
18
- locust/stats.py,sha256=BXvAybKiqI6QF5THdnk-fWkL-FiZKwrAm2W8KzkTchg,46118
19
- locust/web.py,sha256=DVcx53VXApAc6kFfG7so2_kB_qqcw7ojKpBd-dJoijU,28267
18
+ locust/stats.py,sha256=l2cxxVre8dvA4MIOD_ZKNj_fYySz5gTGC2f9Rc4-CL0,46134
19
+ locust/web.py,sha256=tgTRfzAxKBxudjhLkQr5JGppoEOD6hcmZ-i_rGvwOlQ,28245
20
20
  locust/contrib/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
21
- locust/contrib/fasthttp.py,sha256=OZtYHt0HEIRaiundpHC5w-J3xCG8NckrONXTS9UQQr8,26743
21
+ locust/contrib/fasthttp.py,sha256=B_VofSuvb9cehQxlUZnLVvYAr2AquedxeALua4mVOuM,26749
22
22
  locust/rpc/__init__.py,sha256=nVGoHWFQxZjnhCDWjbgXIbmFbN9sizAjkhvSs9_642c,58
23
23
  locust/rpc/protocol.py,sha256=oHR1yHdg_OysxZ2os3HS5Rf5hRi7I0d-3LIvWAn2QF0,1298
24
24
  locust/rpc/zmqrpc.py,sha256=7DLIXzkQr7992zmZwAqNgcqzm7LOQAOQtz0tUGv5-Gg,2637
@@ -51,20 +51,20 @@ locust/test/__init__.py,sha256=CaVC4yA4DnCO8EY3LbedPHFg86a9Lqlpe92JuiX3THw,396
51
51
  locust/test/fake_module1_for_env_test.py,sha256=dzGYWCr1SSkd8Yyo68paUNrCNW7YY_QgjRb7sM37gG0,164
52
52
  locust/test/fake_module2_for_env_test.py,sha256=dzGYWCr1SSkd8Yyo68paUNrCNW7YY_QgjRb7sM37gG0,164
53
53
  locust/test/mock_locustfile.py,sha256=N9sGjW-BmJ-J_x-5bEOR82VQ0DhR1hki313BHPOWq4g,1273
54
- locust/test/mock_logging.py,sha256=dvfXaY2eb0ZHx7Bjn7R69BarnRq9uu0z4HD8hCiRNmU,819
55
- locust/test/test_debugging.py,sha256=w5Lx6h101novinKjTJJDg5AqqY28U2Wg1W4hgCk6Sx8,1069
56
- locust/test/test_dispatch.py,sha256=IVfoBTErABqpRs9B1_D5IP9BrfSBz9qToLiN03Kt9B4,168304
57
- locust/test/test_env.py,sha256=ggyx7ZbS7sZPae2wb6JzrvA0p0H7c9HhcBVJn7u1HTw,8956
58
- locust/test/test_fasthttp.py,sha256=AHuuAg0d88w7_QUjoNf3ZSHz38WYf5rY95_eEFZ0vH8,30775
59
- locust/test/test_http.py,sha256=R23BWBNLjU3OOWCAgIAW8F9H5kqtBx43gPaXC-hhM2g,12570
60
- locust/test/test_interruptable_task.py,sha256=HqStHxtdZPT7WtytBiqTpKeNPg9upXzV7UI4QgFdUoU,1408
54
+ locust/test/mock_logging.py,sha256=qapKrKhTdlVc8foJB2Hxjn7SB6soaLeAj3VF4A6kZtw,806
55
+ locust/test/test_debugging.py,sha256=omQ0w5_Xh1xuTBzkd3VavEIircwtlmoOEHcMInY67vU,1053
56
+ locust/test/test_dispatch.py,sha256=i9fCVV-uYhB2ygIK5r_d3Zzqmxj4vy5X_p4VJiInsEM,167770
57
+ locust/test/test_env.py,sha256=l0fLl9nubdgzxwFNajmBkJvQc5cO5rOTE4p12lbCbs0,8919
58
+ locust/test/test_fasthttp.py,sha256=jVA5wWjZxXYW6emzy-lfPC0AOabzT6rDCX0N7DPP9mc,30727
59
+ locust/test/test_http.py,sha256=VQCVY0inLC0RS-V3E9WHL3vBLGokZjQt0zKSrTNlQmM,12536
60
+ locust/test/test_interruptable_task.py,sha256=LZKSV-aJNnwfvAxguz6SckBEuGEnfGimoIgVfJ2wQTA,1377
61
61
  locust/test/test_load_locustfile.py,sha256=v-muHoM-CYu8t7DXm4AQtFP2q8RYfnTTUBqj7uVqhig,8494
62
- locust/test/test_locust_class.py,sha256=isZPJkIK82uWbqoJbSvwvNJ4CA0QAviQ4_HPwlQVyB8,25547
62
+ locust/test/test_locust_class.py,sha256=oGhhOX848jHRQnIfFlhLlW-kHGYLyYsfDX8hM07Ro7g,25506
63
63
  locust/test/test_log.py,sha256=YPY6vgTAy1KaNU2qoVvQrTH5x_mzRrljEHrkSBy3yxs,7553
64
- locust/test/test_main.py,sha256=Fgvae1Nas7DyIlWmTjJ-2dhBZmVv2Pj9Cqa-r0Z4SN8,83712
64
+ locust/test/test_main.py,sha256=lchekHHgQBsY5wOuKbjjVm7U8cJ9qzJWmGSUu_Ebw7k,83553
65
65
  locust/test/test_old_wait_api.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
66
- locust/test/test_parser.py,sha256=eV3HSKWkgr9wh87ZcO3-bt2sg8vYS99LnJ9yRCyMahE,18309
67
- locust/test/test_runners.py,sha256=6PDbv4Fyv6vLBJCl7ghEh_wGlFy80Ha8M0zixRvC2LM,159328
66
+ locust/test/test_parser.py,sha256=R2RATAHVC1n4gRYZyRD3yO5P9QMFbruZ3A4dwaw8Up0,18287
67
+ locust/test/test_runners.py,sha256=rtmm9cV82lc7jqEYW3FTM8CNmLlswTIPr9UbeE5vfPc,159382
68
68
  locust/test/test_sequential_taskset.py,sha256=QjVMWWfGHn9hU5AvPxRDU7Vo5DcVW1VkMVfDA0k9OPE,3398
69
69
  locust/test/test_stats.py,sha256=g5WXKbKtjtPxR_Ixukz04wZUsEC7RkHx5hCNHzofob4,33928
70
70
  locust/test/test_tags.py,sha256=mzhGLPMizSnSItTHLHizYvloxDfuIDAOgelwInyrf28,13138
@@ -72,14 +72,14 @@ locust/test/test_taskratio.py,sha256=SQ-sBqeFm2GhkfCD_57-fPzQrk1ilSw3DRb0_nwyxAI
72
72
  locust/test/test_users.py,sha256=lp6yAKGK9_MIs9F7s1Vc3561P4oRavhpeVo2y9w3SUU,2135
73
73
  locust/test/test_util.py,sha256=DmFTgNSWWx8zrsx9_ZGO6MsySmBV1H_GzNIVzzyapCM,1229
74
74
  locust/test/test_wait_time.py,sha256=3evSEp6amMWFrzmSYs71MCeIsu7Rtarldb_HnwgSrU0,2353
75
- locust/test/test_web.py,sha256=kvdOewTXbNAwwNjO7ise60zE_Vj_eu6dRPVnvj5y1sQ,52702
75
+ locust/test/test_web.py,sha256=5EL7j8iAZSWlF2t4iGln8euWhC2HQmX6eKbjTSpkq1Q,52413
76
76
  locust/test/test_zmqrpc.py,sha256=kONaZ11hwnneLwaVn7lIDVV7KHpEP2nkxuKhfb9ba3o,2173
77
- locust/test/testcases.py,sha256=N4l0gFd8HKg-0bfIjq9nW5o0aNpv0YRTfOtwrtsPpUw,6979
77
+ locust/test/testcases.py,sha256=ZaPYNxSSChAs0nts_13mCGY7WFW8AjXQZdPOvwAK0TY,6961
78
78
  locust/test/util.py,sha256=98HXLClkycNTxLiuy1d3W_tM6dBU9bA-p5ZXMfncaWE,2754
79
79
  locust/user/__init__.py,sha256=S2yvmI_AU9kXirtTIVqiV_Hs7yXzqXvaSgkNo9ig-fk,71
80
80
  locust/user/inspectuser.py,sha256=KgrWHyE5jhK6or58R7soLRf-_st42AaQrR72qbiXw9E,2641
81
81
  locust/user/sequential_taskset.py,sha256=E8yykSZBO-QMcza1frr-7l8Cv_5bbSpjRO6sbkmGpZE,2544
82
- locust/user/task.py,sha256=tjmJkismY0PflobpPWemAsCDqZDOhWxQ0sE71OxGIBE,16710
82
+ locust/user/task.py,sha256=JvVVCQ1_UQSsahqaEZoFCD-cBXlOJLJ51ewXHNesSAI,16700
83
83
  locust/user/users.py,sha256=qhOW5dDmGbsukWDVb1YDs92D_vbCKRIW60jB5I2bRxs,9950
84
84
  locust/user/wait_time.py,sha256=bGRKMVx4lom75sX3POYJUa1CPeME2bEAXG6CEgxSO5U,2675
85
85
  locust/util/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -95,9 +95,9 @@ locust/webui/dist/report.html,sha256=sOdZZVgZbqgu86BBCSQf3uQUYXgmgSnXF32JpnyAII8
95
95
  locust/webui/dist/assets/favicon.ico,sha256=IUl-rYqfpHdV38e-s0bkmFIeLS-n3Ug0DQxk-h202hI,8348
96
96
  locust/webui/dist/assets/index-941b6e82.js,sha256=G3n5R81Svt0HzbWaV3AV20jLWGLr4X50UZ-Adu2KcxU,1645614
97
97
  locust/webui/dist/assets/logo.png,sha256=EIVPqr6wE_yqguHaqFHIsH0ZACLSrvNWyYO7PbyIj4w,19299
98
- locust-2.25.1.dev8.dist-info/LICENSE,sha256=78XGpIn3fHVBfaxlPNUfjVufSN7QsdhpJMRJHv2AFpo,1095
99
- locust-2.25.1.dev8.dist-info/METADATA,sha256=J-IPK-30GYN_M4zU1Uh2j2dNB7mcYRAyNmUuAbYqZtw,7300
100
- locust-2.25.1.dev8.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
101
- locust-2.25.1.dev8.dist-info/entry_points.txt,sha256=RAdt8Ku-56m7bFjmdj-MBhbF6h4NX7tVODR9QNnOg0E,44
102
- locust-2.25.1.dev8.dist-info/top_level.txt,sha256=XSsjgPA8Ggf9TqKVbkwSqZFuPlZ085X13M9orDycE20,7
103
- locust-2.25.1.dev8.dist-info/RECORD,,
98
+ locust-2.26.0.dist-info/LICENSE,sha256=78XGpIn3fHVBfaxlPNUfjVufSN7QsdhpJMRJHv2AFpo,1095
99
+ locust-2.26.0.dist-info/METADATA,sha256=nEAL6OBW_otmbuSOAv8kOQu8D17K-yvNUt_gwVkDtc4,7248
100
+ locust-2.26.0.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
101
+ locust-2.26.0.dist-info/entry_points.txt,sha256=RAdt8Ku-56m7bFjmdj-MBhbF6h4NX7tVODR9QNnOg0E,44
102
+ locust-2.26.0.dist-info/top_level.txt,sha256=XSsjgPA8Ggf9TqKVbkwSqZFuPlZ085X13M9orDycE20,7
103
+ locust-2.26.0.dist-info/RECORD,,