locust 2.29.2.dev8__py3-none-any.whl → 2.29.2.dev15__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.29.2.dev8'
16
- __version_tuple__ = version_tuple = (2, 29, 2, 'dev8')
15
+ __version__ = version = '2.29.2.dev15'
16
+ __version_tuple__ = version_tuple = (2, 29, 2, 'dev15')
@@ -12,12 +12,11 @@ import socket
12
12
  import time
13
13
  import traceback
14
14
  from base64 import b64encode
15
- from collections.abc import Generator
16
15
  from contextlib import contextmanager
17
16
  from http.cookiejar import CookieJar
18
17
  from json.decoder import JSONDecodeError
19
18
  from ssl import SSLError
20
- from typing import Any, Callable, cast
19
+ from typing import TYPE_CHECKING, cast
21
20
  from urllib.parse import urlparse, urlunparse
22
21
 
23
22
  import gevent
@@ -32,6 +31,36 @@ from geventhttpclient.useragent import CompatRequest, CompatResponse, Connection
32
31
  # borrow requests's content-type header parsing
33
32
  from requests.utils import get_encoding_from_headers
34
33
 
34
+ if TYPE_CHECKING:
35
+ import sys
36
+ from collections.abc import Callable, Generator
37
+ from typing import TypedDict
38
+
39
+ if sys.version_info >= (3, 11):
40
+ from typing import Unpack
41
+ else:
42
+ from typing_extensions import Unpack
43
+
44
+ class PostKwargs(TypedDict, total=False):
45
+ name: str | None
46
+ catch_response: bool
47
+ stream: bool
48
+ headers: dict | None
49
+ auth: tuple[str | bytes, str | bytes] | None
50
+ allow_redirects: bool
51
+ context: dict
52
+
53
+ class PutKwargs(PostKwargs, total=False):
54
+ json: dict | None
55
+
56
+ class PatchKwargs(PostKwargs, total=False):
57
+ json: dict | None
58
+
59
+ class RESTKwargs(PostKwargs, total=False):
60
+ data: str | dict | None
61
+ json: dict | None
62
+
63
+
35
64
  # Monkey patch geventhttpclient.useragent.CompatRequest so that Cookiejar works with Python >= 3.3
36
65
  # More info: https://github.com/requests/requests/pull/871
37
66
  CompatRequest.unverifiable = False
@@ -85,7 +114,7 @@ class FastHttpSession:
85
114
  client_pool: HTTPClientPool | None = None,
86
115
  ssl_context_factory: Callable | None = None,
87
116
  **kwargs,
88
- ):
117
+ ) -> None:
89
118
  self.environment = environment
90
119
  self.base_url = base_url
91
120
  self.cookiejar = CookieJar()
@@ -117,14 +146,14 @@ class FastHttpSession:
117
146
  # store authentication header (we construct this by using _basic_auth_str() function from requests.auth)
118
147
  self.auth_header = _construct_basic_auth_str(parsed_url.username, parsed_url.password)
119
148
 
120
- def _build_url(self, path):
149
+ def _build_url(self, path: str) -> str:
121
150
  """prepend url with hostname unless it's already an absolute URL"""
122
151
  if absolute_http_url_regexp.match(path):
123
152
  return path
124
153
  else:
125
154
  return f"{self.base_url}{path}"
126
155
 
127
- def _send_request_safe_mode(self, method, url, **kwargs):
156
+ def _send_request_safe_mode(self, method: str, url: str, **kwargs):
128
157
  """
129
158
  Send an HTTP request, and catch any exception that might occur due to either
130
159
  connection problems, or invalid HTTP status codes
@@ -155,7 +184,7 @@ class FastHttpSession:
155
184
  catch_response: bool = False,
156
185
  stream: bool = False,
157
186
  headers: dict | None = None,
158
- auth=None,
187
+ auth: tuple[str | bytes, str | bytes] | None = None,
159
188
  json: dict | None = None,
160
189
  allow_redirects: bool = True,
161
190
  context: dict = {},
@@ -264,31 +293,37 @@ class FastHttpSession:
264
293
  self.environment.events.request.fire(**request_meta)
265
294
  return response
266
295
 
267
- def delete(self, url, **kwargs):
296
+ def delete(self, url: str, **kwargs: Unpack[RESTKwargs]) -> ResponseContextManager | FastResponse:
268
297
  """Sends a DELETE request"""
269
298
  return self.request("DELETE", url, **kwargs)
270
299
 
271
- def get(self, url, **kwargs):
300
+ def get(self, url: str, **kwargs: Unpack[RESTKwargs]) -> ResponseContextManager | FastResponse:
272
301
  """Sends a GET request"""
273
302
  return self.request("GET", url, **kwargs)
274
303
 
275
- def head(self, url, **kwargs):
304
+ def head(self, url: str, **kwargs: Unpack[RESTKwargs]) -> ResponseContextManager | FastResponse:
276
305
  """Sends a HEAD request"""
277
306
  return self.request("HEAD", url, **kwargs)
278
307
 
279
- def options(self, url, **kwargs):
308
+ def options(self, url: str, **kwargs: Unpack[RESTKwargs]) -> ResponseContextManager | FastResponse:
280
309
  """Sends a OPTIONS request"""
281
310
  return self.request("OPTIONS", url, **kwargs)
282
311
 
283
- def patch(self, url, data=None, **kwargs):
312
+ def patch(
313
+ self, url: str, data: str | dict | None = None, **kwargs: Unpack[PatchKwargs]
314
+ ) -> ResponseContextManager | FastResponse:
284
315
  """Sends a PATCH request"""
285
316
  return self.request("PATCH", url, data=data, **kwargs)
286
317
 
287
- def post(self, url, data=None, json=None, **kwargs):
318
+ def post(
319
+ self, url: str, data: str | dict | None = None, json: dict | None = None, **kwargs: Unpack[PostKwargs]
320
+ ) -> ResponseContextManager | FastResponse:
288
321
  """Sends a POST request"""
289
322
  return self.request("POST", url, data=data, json=json, **kwargs)
290
323
 
291
- def put(self, url, data=None, **kwargs):
324
+ def put(
325
+ self, url: str, data: str | dict | None = None, **kwargs: Unpack[PutKwargs]
326
+ ) -> ResponseContextManager | FastResponse:
292
327
  """Sends a PUT request"""
293
328
  return self.request("PUT", url, data=data, **kwargs)
294
329
 
locust/event.py CHANGED
@@ -235,6 +235,38 @@ class Events:
235
235
  Fired when the CPU usage exceeds runners.CPU_WARNING_THRESHOLD (90% by default)
236
236
  """
237
237
 
238
+ heartbeat_sent: EventHook
239
+ """
240
+ Fired when a heartbeat is sent by master to a worker.
241
+
242
+ Event arguments:
243
+
244
+ :param client_id: worker client id
245
+ :param timestamp: time in seconds since the epoch (float) when the event occured
246
+ """
247
+
248
+ heartbeat_received: EventHook
249
+ """
250
+ Fired when a heartbeat is received by a worker from master.
251
+
252
+ Event arguments:
253
+
254
+ :param client_id: worker client id
255
+ :param timestamp: time in seconds since the epoch (float) when the event occured
256
+ """
257
+
258
+ usage_monitor: EventHook
259
+ """
260
+ Fired every runners.CPU_MONITOR_INTERVAL (5.0 seconds by default) with information about
261
+ current CPU and memory usage.
262
+
263
+ Event arguments:
264
+
265
+ :param environment: locust environment
266
+ :param cpu_usage: current CPU usage in percent
267
+ :param memory_usage: current memory usage (RSS) in bytes
268
+ """
269
+
238
270
  def __init__(self):
239
271
  # For backward compatibility use also values of class attributes
240
272
  for name, value in vars(type(self)).items():
locust/runners.py CHANGED
@@ -15,19 +15,9 @@ import traceback
15
15
  from abc import abstractmethod
16
16
  from collections import defaultdict
17
17
  from collections.abc import Iterator, MutableMapping, ValuesView
18
- from operator import (
19
- itemgetter,
20
- methodcaller,
21
- )
18
+ from operator import itemgetter, methodcaller
22
19
  from types import TracebackType
23
- from typing import (
24
- TYPE_CHECKING,
25
- Any,
26
- Callable,
27
- NoReturn,
28
- TypedDict,
29
- cast,
30
- )
20
+ from typing import TYPE_CHECKING, Any, Callable, NoReturn, TypedDict, cast
31
21
  from uuid import uuid4
32
22
 
33
23
  import gevent
@@ -40,15 +30,8 @@ from . import argument_parser
40
30
  from .dispatch import UsersDispatcher
41
31
  from .exception import RPCError, RPCReceiveError, RPCSendError
42
32
  from .log import get_logs, greenlet_exception_logger
43
- from .rpc import (
44
- Message,
45
- rpc,
46
- )
47
- from .stats import (
48
- RequestStats,
49
- StatsError,
50
- setup_distributed_stats_event_listeners,
51
- )
33
+ from .rpc import Message, rpc
34
+ from .stats import RequestStats, StatsError, setup_distributed_stats_event_listeners
52
35
 
53
36
  if TYPE_CHECKING:
54
37
  from . import User
@@ -106,7 +89,7 @@ class Runner:
106
89
  self.spawning_greenlet: gevent.Greenlet | None = None
107
90
  self.shape_greenlet: gevent.Greenlet | None = None
108
91
  self.shape_last_tick: tuple[int, float] | tuple[int, float, list[type[User]] | None] | None = None
109
- self.current_cpu_usage: int = 0
92
+ self.current_cpu_usage: float = 0.0
110
93
  self.cpu_warning_emitted: bool = False
111
94
  self.worker_cpu_warning_emitted: bool = False
112
95
  self.current_memory_usage: int = 0
@@ -308,6 +291,10 @@ class Runner:
308
291
  f"CPU usage above {CPU_WARNING_THRESHOLD}%! This may constrain your throughput and may even give inconsistent response time measurements! See https://docs.locust.io/en/stable/running-distributed.html for how to distribute the load over multiple CPU cores or machines"
309
292
  )
310
293
  self.cpu_warning_emitted = True
294
+
295
+ self.environment.events.usage_monitor.fire(
296
+ environment=self.environment, cpu_usage=self.current_cpu_usage, memory_usage=self.current_memory_usage
297
+ )
311
298
  gevent.sleep(CPU_MONITOR_INTERVAL)
312
299
 
313
300
  @abstractmethod
@@ -1102,6 +1089,7 @@ class MasterRunner(DistributedRunner):
1102
1089
  )
1103
1090
  if "current_memory_usage" in msg.data:
1104
1091
  c.memory_usage = msg.data["current_memory_usage"]
1092
+ self.environment.events.heartbeat_sent.fire(client_id=msg.node_id, timestamp=time.time())
1105
1093
  self.server.send_to_client(Message("heartbeat", None, msg.node_id))
1106
1094
  else:
1107
1095
  logging.debug(f"Got heartbeat message from unknown worker {msg.node_id}")
@@ -1399,6 +1387,9 @@ class WorkerRunner(DistributedRunner):
1399
1387
  self.reset_connection()
1400
1388
  elif msg.type == "heartbeat":
1401
1389
  self.last_heartbeat_timestamp = time.time()
1390
+ self.environment.events.heartbeat_received.fire(
1391
+ client_id=msg.node_id, timestamp=self.last_heartbeat_timestamp
1392
+ )
1402
1393
  elif msg.type == "update_user_class":
1403
1394
  self.environment.update_user_class(msg.data)
1404
1395
  elif msg.type == "spawning_complete":
@@ -1,12 +1,7 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  import locust
4
- from locust import (
5
- LoadTestShape,
6
- __version__,
7
- constant,
8
- runners,
9
- )
4
+ from locust import LoadTestShape, __version__, constant, runners
10
5
  from locust.argument_parser import parse_options
11
6
  from locust.dispatch import UsersDispatcher
12
7
  from locust.env import Environment
@@ -26,11 +21,7 @@ from locust.runners import (
26
21
  WorkerRunner,
27
22
  )
28
23
  from locust.stats import RequestStats
29
- from locust.user import (
30
- TaskSet,
31
- User,
32
- task,
33
- )
24
+ from locust.user import TaskSet, User, task
34
25
 
35
26
  import json
36
27
  import logging
@@ -2136,6 +2127,149 @@ class TestMasterWorkerRunners(LocustTestCase):
2136
2127
 
2137
2128
  self.assertEqual(test_start_exec_count, 1)
2138
2129
 
2130
+ def test_heartbeat_event(self) -> None:
2131
+ """
2132
+ Tests that heartbeat event is fired during a test
2133
+ """
2134
+
2135
+ class TestUser(User):
2136
+ wait_time = constant(0.1)
2137
+
2138
+ @task
2139
+ def noop(self) -> None:
2140
+ pass
2141
+
2142
+ with mock.patch("locust.runners.HEARTBEAT_INTERVAL", new=1):
2143
+ # start a Master runner
2144
+ master_env = Environment(user_classes=[TestUser])
2145
+ worker_connect_events = []
2146
+ timestamp_start: list[float] = [time.time() + 3600.0]
2147
+
2148
+ def on_connect(client_id: str) -> None:
2149
+ worker_connect_events.append(client_id)
2150
+ timestamp_start[0] = time.time()
2151
+
2152
+ master_env.events.worker_connect.add_listener(on_connect)
2153
+ master = master_env.create_master_runner("*", 0)
2154
+ sleep(0)
2155
+ worker_env = Environment(user_classes=[TestUser])
2156
+ worker: WorkerRunner = worker_env.create_worker_runner("127.0.0.1", master.server.port)
2157
+
2158
+ with (
2159
+ mock.patch.object(
2160
+ worker.environment.events.heartbeat_received,
2161
+ "fire",
2162
+ wraps=worker.environment.events.heartbeat_received.fire,
2163
+ ) as worker_heartbeat_received_mock,
2164
+ mock.patch.object(
2165
+ master.environment.events.heartbeat_sent,
2166
+ "fire",
2167
+ wraps=master.environment.events.heartbeat_sent.fire,
2168
+ ) as master_heartbeat_sent_mock,
2169
+ ):
2170
+ # give workers time to connect
2171
+ sleep(0.1)
2172
+ # issue start command that should trigger TestUsers to be spawned in the Workers
2173
+ master.start(2, spawn_rate=2)
2174
+ sleep(0.1)
2175
+ # check that worker nodes have started locusts
2176
+ self.assertEqual(2, worker.user_count)
2177
+
2178
+ # give time for nodes to send and receive 5 heartbeats, HEARTBEAT_INTERVAL mocked to 1 second, so
2179
+ # sleep 5 seconds - 1 second that represents the overhead from connecting
2180
+ sleep(5 - 1)
2181
+ master.quit()
2182
+
2183
+ # make sure users are killed
2184
+ self.assertEqual(0, worker.user_count)
2185
+ # make sure events happened correctly
2186
+ self.assertIn(worker.client_id, worker_connect_events)
2187
+
2188
+ timestamp_stop = time.time()
2189
+
2190
+ self.assertEqual(worker_heartbeat_received_mock.call_count, 5)
2191
+ self.assertEqual(master_heartbeat_sent_mock.call_count, 5)
2192
+
2193
+ for call_args, call_kwargs in [
2194
+ *worker_heartbeat_received_mock.call_args_list,
2195
+ *master_heartbeat_sent_mock.call_args_list,
2196
+ ]:
2197
+ self.assertEqual(call_args, ()) # args
2198
+ self.assertEqual(call_kwargs, {"client_id": worker.client_id, "timestamp": mock.ANY}) # kwargs
2199
+ self.assertGreaterEqual(call_kwargs["timestamp"], timestamp_start[0])
2200
+ self.assertLessEqual(call_kwargs["timestamp"], timestamp_stop)
2201
+
2202
+ def test_usage_monitor_event(self) -> None:
2203
+ """
2204
+ Tests that usage_monitor event is fired during a test
2205
+ """
2206
+
2207
+ class TestUser(User):
2208
+ wait_time = constant(0.1)
2209
+
2210
+ @task
2211
+ def noop(self) -> None:
2212
+ pass
2213
+
2214
+ with mock.patch("locust.runners.CPU_MONITOR_INTERVAL", new=1):
2215
+ # start a Master runner
2216
+ master_env = Environment(user_classes=[TestUser])
2217
+ worker_connect_events = []
2218
+
2219
+ def on_connect(client_id: str) -> None:
2220
+ worker_connect_events.append(client_id)
2221
+
2222
+ master_env.events.worker_connect.add_listener(on_connect)
2223
+ master = master_env.create_master_runner("*", 0)
2224
+ sleep(0)
2225
+ worker_env = Environment(user_classes=[TestUser])
2226
+ worker: WorkerRunner = worker_env.create_worker_runner("127.0.0.1", master.server.port)
2227
+
2228
+ with (
2229
+ mock.patch.object(
2230
+ worker.environment.events.usage_monitor, "fire", wraps=worker.environment.events.usage_monitor.fire
2231
+ ) as worker_usage_monitor_mock,
2232
+ mock.patch.object(
2233
+ master.environment.events.usage_monitor, "fire", wraps=master.environment.events.usage_monitor.fire
2234
+ ) as master_usage_monitor_mock,
2235
+ ):
2236
+ # give workers time to connect
2237
+ sleep(0.1)
2238
+ # issue start command that should trigger TestUsers to be spawned in the Workers
2239
+ master.start(2, spawn_rate=2)
2240
+ sleep(0.1)
2241
+ # check that worker nodes have started locusts
2242
+ self.assertEqual(2, worker.user_count)
2243
+
2244
+ # give time for nodes to send 5 usage_monitor events, CPU_MONITOR_INTERVAL mocked to 1 second, so
2245
+ # sleep 5 seconds
2246
+ sleep(5)
2247
+ master.quit()
2248
+
2249
+ # make sure users are killed
2250
+ self.assertEqual(0, worker.user_count)
2251
+ # make sure events happened correctly
2252
+ self.assertIn(worker.client_id, worker_connect_events)
2253
+
2254
+ self.assertEqual(worker_usage_monitor_mock.call_count, 5)
2255
+ self.assertEqual(master_usage_monitor_mock.call_count, 5)
2256
+
2257
+ for call_args, call_kwargs in master_usage_monitor_mock:
2258
+ self.assertEqual(call_args, ()) # args
2259
+ self.assertEqual(
2260
+ call_kwargs, {"environment": master_env, "cpu_usage": mock.ANY, "memory_usage": mock.ANY}
2261
+ ) # kwargs
2262
+ self.assertTrue(isinstance(call_kwargs["cpu_usage"], float))
2263
+ self.assertTrue(isinstance(call_kwargs["memory_usage"], int))
2264
+
2265
+ for call_args, call_kwargs in worker_usage_monitor_mock:
2266
+ self.assertEqual(call_args, ()) # args
2267
+ self.assertEqual(
2268
+ call_kwargs, {"environment": worker_env, "cpu_usage": mock.ANY, "memory_usage": mock.ANY}
2269
+ ) # kwargs
2270
+ self.assertTrue(isinstance(call_kwargs["cpu_usage"], float))
2271
+ self.assertTrue(isinstance(call_kwargs["memory_usage"], int))
2272
+
2139
2273
 
2140
2274
  class TestMasterRunner(LocustRunnerTestCase):
2141
2275
  def setUp(self):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: locust
3
- Version: 2.29.2.dev8
3
+ Version: 2.29.2.dev15
4
4
  Summary: Developer-friendly load testing framework
5
5
  License: MIT
6
6
  Project-URL: Homepage, https://github.com/locustio/locust
@@ -1,24 +1,24 @@
1
1
  locust/__init__.py,sha256=Hmw2vNf75eLQ1mQIPXAwlQrJ_XFY65MOb92fGsNCukQ,1458
2
2
  locust/__main__.py,sha256=vBQ82334kX06ImDbFlPFgiBRiLIinwNk3z8Khs6hd74,31
3
- locust/_version.py,sha256=5YNva4b3ZEMTG2qda7JaWF6Bb7Ck5Cj_aJqtsQk40EI,426
3
+ locust/_version.py,sha256=ZoGVgC2lL7aipXStKMVEIu1JxbIXfEYmFmNyXQQY1RM,428
4
4
  locust/argument_parser.py,sha256=sjQoJ1NTac9LdNYT7zn8RajlWqBQs8YFNv6uRExb2gg,28941
5
5
  locust/clients.py,sha256=OHPv6hBAt4gt3HI67yqyT1qrSsF8uMdCwIRu0kIsRWI,19491
6
6
  locust/debug.py,sha256=We6Z9W0btkKSc7PxWmrZx-xMynvOOsKhG6jmDgQin0g,5134
7
7
  locust/dispatch.py,sha256=vYh0QEDFgJ3hY0HgSk-EiNO7IP9ffzXF_Et8wB9JvsI,16995
8
8
  locust/env.py,sha256=sP-fCnZs0e2xodRemLHgTgyyUt5eezwtdA9WsCoqJkQ,12767
9
- locust/event.py,sha256=H2SuxyadPMsRY-LQ6MuK1okHls9lYsS9GgXIDSxpi50,7864
9
+ locust/event.py,sha256=iXEwIYFzra-j1WRldXB9SUibydtD8q8EIKaFPGTTIjk,8729
10
10
  locust/exception.py,sha256=jGgJ32ubuf4pWdlaVOkbh2Y0LlG0_DHi-lv3ib8ppOE,1791
11
11
  locust/html.py,sha256=_n3aB3fxiYzSeE_7RqHF3iiEPjPnbQ3e2Pw9P8AVtPU,3920
12
12
  locust/input_events.py,sha256=ZIyePyAMuA_YFYWg18g_pE4kwuQV3RbEB250MzXRwjY,3314
13
13
  locust/log.py,sha256=Wrkn0Ibugh5Sqjm4hGQ2-jUsy1tNMBdTctp4FyXQI24,3457
14
14
  locust/main.py,sha256=NGjL5QqakU5aeyUzwu2Fh00xVZfC3eoBE3DtfOmRtcM,27854
15
15
  locust/py.typed,sha256=gkWLl8yD4mIZnNYYAIRM8g9VarLvWmTAFeUfEbxJLBw,65
16
- locust/runners.py,sha256=wqf9eIPUGrqz7m-EZtXKdMJ43cainHm0bS-3Cj4haBo,69471
16
+ locust/runners.py,sha256=otH-ZxTygBRXN46Nmocs5ac8R4b0MsnKAUcHRwVnD1E,69869
17
17
  locust/shape.py,sha256=t-lwBS8LOjWcKXNL7j2U3zroIXJ1b0fazUwpRYQOKXw,1973
18
18
  locust/stats.py,sha256=5jx9aD9Sky-kCZ3E-MjRT3xbwvxo9xyDtfcfP56zclo,45875
19
19
  locust/web.py,sha256=rN1NVeZ9LKSEeDwvpRbOJ0bcy8U1U4VjP-7vK7ejlwM,27367
20
20
  locust/contrib/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
21
- locust/contrib/fasthttp.py,sha256=oQPym5pqrX4M7voiHSyzpJ9RasSU7JAkNDhhAj_T30g,27129
21
+ locust/contrib/fasthttp.py,sha256=tcCeXkDou-WlQwdXhj0Wt29sS9gDrqyA2aA9BMqTzeY,28501
22
22
  locust/rpc/__init__.py,sha256=nVGoHWFQxZjnhCDWjbgXIbmFbN9sizAjkhvSs9_642c,58
23
23
  locust/rpc/protocol.py,sha256=n-rb3GZQcAlldYDj4E4GuFGylYj_26GSS5U29meft5Y,1282
24
24
  locust/rpc/zmqrpc.py,sha256=AAY6w7wSFHsW34qqN28666boHFf6dTSAXPQJnAO6iUI,2707
@@ -39,7 +39,7 @@ locust/test/test_log.py,sha256=YPY6vgTAy1KaNU2qoVvQrTH5x_mzRrljEHrkSBy3yxs,7553
39
39
  locust/test/test_main.py,sha256=7OuH2-7noD_rbeoKJD9hIZsylSugu7ze3XFIrU1u0HI,85016
40
40
  locust/test/test_old_wait_api.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
41
41
  locust/test/test_parser.py,sha256=-2VO5Dopg-VoWvIgXrmr7GN40cqrnjUoctBHmVlyewg,17826
42
- locust/test/test_runners.py,sha256=LNZusqKx8brYB30Uk_2dxJMjBMawUmhYwDn0S7EcNH8,163088
42
+ locust/test/test_runners.py,sha256=jvyv5JCD4sJ_8nmB8ZzqGINLkepIAKyIgwdVTzMtG7I,169468
43
43
  locust/test/test_sequential_taskset.py,sha256=QjVMWWfGHn9hU5AvPxRDU7Vo5DcVW1VkMVfDA0k9OPE,3398
44
44
  locust/test/test_stats.py,sha256=F51VkL3k3y4OhYBlRyV6vWzisenSAOmSWKy2IPVrnWM,33929
45
45
  locust/test/test_tags.py,sha256=mzhGLPMizSnSItTHLHizYvloxDfuIDAOgelwInyrf28,13138
@@ -70,9 +70,9 @@ locust/webui/dist/index.html,sha256=S78UvAUZbQ-sH0wBxqFKrT2ZSfRxUFGx5xwQY6FaVMk,
70
70
  locust/webui/dist/report.html,sha256=sOdZZVgZbqgu86BBCSQf3uQUYXgmgSnXF32JpnyAII8,513
71
71
  locust/webui/dist/assets/favicon.ico,sha256=IUl-rYqfpHdV38e-s0bkmFIeLS-n3Ug0DQxk-h202hI,8348
72
72
  locust/webui/dist/assets/logo.png,sha256=EIVPqr6wE_yqguHaqFHIsH0ZACLSrvNWyYO7PbyIj4w,19299
73
- locust-2.29.2.dev8.dist-info/LICENSE,sha256=78XGpIn3fHVBfaxlPNUfjVufSN7QsdhpJMRJHv2AFpo,1095
74
- locust-2.29.2.dev8.dist-info/METADATA,sha256=XiwiuFtVhGFq5uRWUtWgHqeA9hQlvHJwm_zWpQZOnqo,7389
75
- locust-2.29.2.dev8.dist-info/WHEEL,sha256=mguMlWGMX-VHnMpKOjjQidIo1ssRlCFu4a4mBpz1s2M,91
76
- locust-2.29.2.dev8.dist-info/entry_points.txt,sha256=RAdt8Ku-56m7bFjmdj-MBhbF6h4NX7tVODR9QNnOg0E,44
77
- locust-2.29.2.dev8.dist-info/top_level.txt,sha256=XSsjgPA8Ggf9TqKVbkwSqZFuPlZ085X13M9orDycE20,7
78
- locust-2.29.2.dev8.dist-info/RECORD,,
73
+ locust-2.29.2.dev15.dist-info/LICENSE,sha256=78XGpIn3fHVBfaxlPNUfjVufSN7QsdhpJMRJHv2AFpo,1095
74
+ locust-2.29.2.dev15.dist-info/METADATA,sha256=HwQcBqK2CgqJBGYsEhEuyg2Uxftjm0Q4Z1cnLe-2czM,7390
75
+ locust-2.29.2.dev15.dist-info/WHEEL,sha256=mguMlWGMX-VHnMpKOjjQidIo1ssRlCFu4a4mBpz1s2M,91
76
+ locust-2.29.2.dev15.dist-info/entry_points.txt,sha256=RAdt8Ku-56m7bFjmdj-MBhbF6h4NX7tVODR9QNnOg0E,44
77
+ locust-2.29.2.dev15.dist-info/top_level.txt,sha256=XSsjgPA8Ggf9TqKVbkwSqZFuPlZ085X13M9orDycE20,7
78
+ locust-2.29.2.dev15.dist-info/RECORD,,