locust 2.46.6.dev12__tar.gz → 2.46.7.dev7__tar.gz
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-2.46.6.dev12 → locust-2.46.7.dev7}/PKG-INFO +3 -2
- {locust-2.46.6.dev12 → locust-2.46.7.dev7}/README.md +2 -1
- {locust-2.46.6.dev12 → locust-2.46.7.dev7}/locust/_version.py +2 -2
- {locust-2.46.6.dev12 → locust-2.46.7.dev7}/locust/clients.py +6 -9
- {locust-2.46.6.dev12 → locust-2.46.7.dev7}/locust/contrib/fasthttp.py +5 -7
- {locust-2.46.6.dev12 → locust-2.46.7.dev7}/locust/dispatch.py +3 -0
- {locust-2.46.6.dev12 → locust-2.46.7.dev7}/locust/runners.py +5 -7
- {locust-2.46.6.dev12 → locust-2.46.7.dev7}/locust/stats.py +15 -11
- {locust-2.46.6.dev12 → locust-2.46.7.dev7}/locust/util/cache.py +2 -4
- {locust-2.46.6.dev12 → locust-2.46.7.dev7}/locust/util/date.py +1 -1
- {locust-2.46.6.dev12 → locust-2.46.7.dev7}/locust/util/exception_handler.py +1 -1
- {locust-2.46.6.dev12 → locust-2.46.7.dev7}/locust/web.py +1 -1
- {locust-2.46.6.dev12 → locust-2.46.7.dev7}/pyproject.toml +3 -3
- {locust-2.46.6.dev12 → locust-2.46.7.dev7}/.gitignore +0 -0
- {locust-2.46.6.dev12 → locust-2.46.7.dev7}/LICENSE +0 -0
- {locust-2.46.6.dev12 → locust-2.46.7.dev7}/hatch_build.py +0 -0
- {locust-2.46.6.dev12 → locust-2.46.7.dev7}/locust/__init__.py +13 -13
- {locust-2.46.6.dev12 → locust-2.46.7.dev7}/locust/__main__.py +0 -0
- {locust-2.46.6.dev12 → locust-2.46.7.dev7}/locust/argument_parser.py +0 -0
- {locust-2.46.6.dev12 → locust-2.46.7.dev7}/locust/contrib/__init__.py +0 -0
- {locust-2.46.6.dev12 → locust-2.46.7.dev7}/locust/contrib/csv_request_logger.py +0 -0
- {locust-2.46.6.dev12 → locust-2.46.7.dev7}/locust/contrib/dns.py +0 -0
- {locust-2.46.6.dev12 → locust-2.46.7.dev7}/locust/contrib/milvus.py +0 -0
- {locust-2.46.6.dev12 → locust-2.46.7.dev7}/locust/contrib/mongodb.py +0 -0
- {locust-2.46.6.dev12 → locust-2.46.7.dev7}/locust/contrib/mqtt.py +0 -0
- {locust-2.46.6.dev12 → locust-2.46.7.dev7}/locust/contrib/oai.py +0 -0
- {locust-2.46.6.dev12 → locust-2.46.7.dev7}/locust/contrib/postgres.py +0 -0
- {locust-2.46.6.dev12 → locust-2.46.7.dev7}/locust/contrib/qdrant.py +0 -0
- {locust-2.46.6.dev12 → locust-2.46.7.dev7}/locust/contrib/socketio.py +0 -0
- {locust-2.46.6.dev12 → locust-2.46.7.dev7}/locust/debug.py +0 -0
- {locust-2.46.6.dev12 → locust-2.46.7.dev7}/locust/env.py +0 -0
- {locust-2.46.6.dev12 → locust-2.46.7.dev7}/locust/event.py +0 -0
- {locust-2.46.6.dev12 → locust-2.46.7.dev7}/locust/exception.py +0 -0
- {locust-2.46.6.dev12 → locust-2.46.7.dev7}/locust/html.py +0 -0
- {locust-2.46.6.dev12 → locust-2.46.7.dev7}/locust/input_events.py +0 -0
- {locust-2.46.6.dev12 → locust-2.46.7.dev7}/locust/log.py +0 -0
- {locust-2.46.6.dev12 → locust-2.46.7.dev7}/locust/main.py +0 -0
- {locust-2.46.6.dev12 → locust-2.46.7.dev7}/locust/opentelemetry.py +0 -0
- {locust-2.46.6.dev12 → locust-2.46.7.dev7}/locust/py.typed +0 -0
- {locust-2.46.6.dev12 → locust-2.46.7.dev7}/locust/rpc/__init__.py +0 -0
- {locust-2.46.6.dev12 → locust-2.46.7.dev7}/locust/rpc/protocol.py +0 -0
- {locust-2.46.6.dev12 → locust-2.46.7.dev7}/locust/rpc/zmqrpc.py +0 -0
- {locust-2.46.6.dev12 → locust-2.46.7.dev7}/locust/shape.py +0 -0
- {locust-2.46.6.dev12 → locust-2.46.7.dev7}/locust/user/__init__.py +2 -2
- {locust-2.46.6.dev12 → locust-2.46.7.dev7}/locust/user/inspectuser.py +0 -0
- {locust-2.46.6.dev12 → locust-2.46.7.dev7}/locust/user/markov_taskset.py +0 -0
- {locust-2.46.6.dev12 → locust-2.46.7.dev7}/locust/user/sequential_taskset.py +0 -0
- {locust-2.46.6.dev12 → locust-2.46.7.dev7}/locust/user/task.py +0 -0
- {locust-2.46.6.dev12 → locust-2.46.7.dev7}/locust/user/users.py +0 -0
- {locust-2.46.6.dev12 → locust-2.46.7.dev7}/locust/user/wait_time.py +0 -0
- {locust-2.46.6.dev12 → locust-2.46.7.dev7}/locust/util/__init__.py +0 -0
- {locust-2.46.6.dev12 → locust-2.46.7.dev7}/locust/util/deprecation.py +0 -0
- {locust-2.46.6.dev12 → locust-2.46.7.dev7}/locust/util/directory.py +0 -0
- {locust-2.46.6.dev12 → locust-2.46.7.dev7}/locust/util/load_locustfile.py +0 -0
- {locust-2.46.6.dev12 → locust-2.46.7.dev7}/locust/util/rounding.py +0 -0
- {locust-2.46.6.dev12 → locust-2.46.7.dev7}/locust/util/timespan.py +0 -0
- {locust-2.46.6.dev12 → locust-2.46.7.dev7}/locust/util/url.py +0 -0
- {locust-2.46.6.dev12 → locust-2.46.7.dev7}/locust/webui/dist/assets/favicon-dark.png +0 -0
- {locust-2.46.6.dev12 → locust-2.46.7.dev7}/locust/webui/dist/assets/favicon-light.png +0 -0
- {locust-2.46.6.dev12 → locust-2.46.7.dev7}/locust/webui/dist/assets/graphs-dark.png +0 -0
- {locust-2.46.6.dev12 → locust-2.46.7.dev7}/locust/webui/dist/assets/graphs-light.png +0 -0
- {locust-2.46.6.dev12 → locust-2.46.7.dev7}/locust/webui/dist/assets/src-pSlzKFX1.js +0 -0
- {locust-2.46.6.dev12 → locust-2.46.7.dev7}/locust/webui/dist/assets/terminal.gif +0 -0
- {locust-2.46.6.dev12 → locust-2.46.7.dev7}/locust/webui/dist/assets/testruns-dark.png +0 -0
- {locust-2.46.6.dev12 → locust-2.46.7.dev7}/locust/webui/dist/assets/testruns-light.png +0 -0
- {locust-2.46.6.dev12 → locust-2.46.7.dev7}/locust/webui/dist/auth.html +0 -0
- {locust-2.46.6.dev12 → locust-2.46.7.dev7}/locust/webui/dist/index.html +0 -0
- {locust-2.46.6.dev12 → locust-2.46.7.dev7}/locust/webui/dist/report.html +0 -0
- {locust-2.46.6.dev12 → locust-2.46.7.dev7}/pytest_locust/plugin.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: locust
|
|
3
|
-
Version: 2.46.
|
|
3
|
+
Version: 2.46.7.dev7
|
|
4
4
|
Summary: Developer-friendly load testing framework
|
|
5
5
|
Project-URL: Homepage, https://locust.cloud/
|
|
6
6
|
Project-URL: Repository, https://github.com/locustio/locust
|
|
@@ -83,11 +83,12 @@ If you want your users to loop, perform some conditional behaviour or do some ca
|
|
|
83
83
|
```python
|
|
84
84
|
from locust import HttpUser, task, between
|
|
85
85
|
|
|
86
|
+
|
|
86
87
|
class QuickstartUser(HttpUser):
|
|
87
88
|
wait_time = between(1, 2)
|
|
88
89
|
|
|
89
90
|
def on_start(self):
|
|
90
|
-
self.client.post("/login", json={"username":"foo", "password":"bar"})
|
|
91
|
+
self.client.post("/login", json={"username": "foo", "password": "bar"})
|
|
91
92
|
|
|
92
93
|
@task
|
|
93
94
|
def hello_world(self):
|
|
@@ -24,11 +24,12 @@ If you want your users to loop, perform some conditional behaviour or do some ca
|
|
|
24
24
|
```python
|
|
25
25
|
from locust import HttpUser, task, between
|
|
26
26
|
|
|
27
|
+
|
|
27
28
|
class QuickstartUser(HttpUser):
|
|
28
29
|
wait_time = between(1, 2)
|
|
29
30
|
|
|
30
31
|
def on_start(self):
|
|
31
|
-
self.client.post("/login", json={"username":"foo", "password":"bar"})
|
|
32
|
+
self.client.post("/login", json={"username": "foo", "password": "bar"})
|
|
32
33
|
|
|
33
34
|
@task
|
|
34
35
|
def hello_world(self):
|
|
@@ -18,7 +18,7 @@ version_tuple: tuple[int | str, ...]
|
|
|
18
18
|
commit_id: str | None
|
|
19
19
|
__commit_id__: str | None
|
|
20
20
|
|
|
21
|
-
__version__ = version = '2.46.
|
|
22
|
-
__version_tuple__ = version_tuple = (2, 46,
|
|
21
|
+
__version__ = version = '2.46.7.dev7'
|
|
22
|
+
__version_tuple__ = version_tuple = (2, 46, 7, 'dev7')
|
|
23
23
|
|
|
24
24
|
__commit_id__ = commit_id = None
|
|
@@ -8,7 +8,7 @@ import sys
|
|
|
8
8
|
import time
|
|
9
9
|
from contextlib import contextmanager
|
|
10
10
|
from typing import TYPE_CHECKING, cast
|
|
11
|
-
from urllib.parse import urlparse, urlunparse
|
|
11
|
+
from urllib.parse import unquote, urlparse, urlunparse
|
|
12
12
|
|
|
13
13
|
import requests
|
|
14
14
|
from packaging.version import Version
|
|
@@ -104,16 +104,13 @@ class HttpSession(requests.Session):
|
|
|
104
104
|
# Check for basic authentication
|
|
105
105
|
parsed_url = urlparse(self.base_url)
|
|
106
106
|
if parsed_url.username and parsed_url.password:
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
netloc += ":%d" % parsed_url.port
|
|
110
|
-
|
|
111
|
-
# remove username and password from the base_url
|
|
107
|
+
# remove username and password from the base_url (keeping e.g. the brackets of an IPv6 host)
|
|
108
|
+
netloc = parsed_url.netloc.rpartition("@")[2]
|
|
112
109
|
self.base_url = urlunparse(
|
|
113
110
|
(parsed_url.scheme, netloc, parsed_url.path, parsed_url.params, parsed_url.query, parsed_url.fragment)
|
|
114
111
|
)
|
|
115
|
-
# configure requests to use basic auth
|
|
116
|
-
self.auth = HTTPBasicAuth(parsed_url.username, parsed_url.password)
|
|
112
|
+
# configure requests to use basic auth (credentials in a URL are percent-encoded)
|
|
113
|
+
self.auth = HTTPBasicAuth(unquote(parsed_url.username), unquote(parsed_url.password))
|
|
117
114
|
|
|
118
115
|
self.mount("https://", LocustHttpAdapter(pool_manager=pool_manager))
|
|
119
116
|
self.mount("http://", LocustHttpAdapter(pool_manager=pool_manager))
|
|
@@ -198,7 +195,7 @@ class HttpSession(requests.Session):
|
|
|
198
195
|
response = self._send_request_safe_mode(method, complete_url, data=data, json=json, **kwargs)
|
|
199
196
|
response_time = (time.perf_counter() - start_perf_counter) * 1000
|
|
200
197
|
|
|
201
|
-
if request_before_redirect := (response.history and response.history[0] or response).request:
|
|
198
|
+
if request_before_redirect := ((response.history and response.history[0]) or response).request:
|
|
202
199
|
complete_url = str(request_before_redirect.url)
|
|
203
200
|
if not name:
|
|
204
201
|
name = request_before_redirect.path_url
|
|
@@ -15,7 +15,7 @@ from base64 import b64encode
|
|
|
15
15
|
from http.cookiejar import CookieJar
|
|
16
16
|
from ssl import SSLError
|
|
17
17
|
from typing import TYPE_CHECKING
|
|
18
|
-
from urllib.parse import urlparse, urlunparse
|
|
18
|
+
from urllib.parse import unquote, urlparse, urlunparse
|
|
19
19
|
|
|
20
20
|
import gevent
|
|
21
21
|
from charset_normalizer import detect
|
|
@@ -128,11 +128,8 @@ class FastHttpSession:
|
|
|
128
128
|
if self.base_url:
|
|
129
129
|
parsed_url = urlparse(self.base_url)
|
|
130
130
|
if parsed_url.username and parsed_url.password:
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
netloc += ":%d" % parsed_url.port
|
|
134
|
-
|
|
135
|
-
# remove username and password from the base_url
|
|
131
|
+
# remove username and password from the base_url (keeping e.g. the brackets of an IPv6 host)
|
|
132
|
+
netloc = parsed_url.netloc.rpartition("@")[2]
|
|
136
133
|
self.base_url = str(
|
|
137
134
|
urlunparse(
|
|
138
135
|
(
|
|
@@ -146,7 +143,8 @@ class FastHttpSession:
|
|
|
146
143
|
)
|
|
147
144
|
)
|
|
148
145
|
# store authentication header (we construct this by using _basic_auth_str() function from requests.auth)
|
|
149
|
-
|
|
146
|
+
# (credentials in a URL are percent-encoded)
|
|
147
|
+
self.auth_header = _construct_basic_auth_str(unquote(parsed_url.username), unquote(parsed_url.password))
|
|
150
148
|
|
|
151
149
|
def _build_url(self, path: str) -> str:
|
|
152
150
|
"""prepend url with hostname unless it's already an absolute URL"""
|
|
@@ -192,6 +192,9 @@ class UsersDispatcher(Iterator):
|
|
|
192
192
|
:param spawn_rate: The spawn rate
|
|
193
193
|
:param user_classes: The user classes to be used for the new dispatch
|
|
194
194
|
"""
|
|
195
|
+
if target_user_count < 0:
|
|
196
|
+
raise ValueError(f"target_user_count must be >= 0, got {target_user_count}")
|
|
197
|
+
|
|
195
198
|
if user_classes is not None and self._user_classes != sorted(user_classes, key=attrgetter("__name__")):
|
|
196
199
|
self._user_classes = sorted(user_classes, key=attrgetter("__name__"))
|
|
197
200
|
self._user_generator = self._user_gen()
|
|
@@ -917,10 +917,8 @@ class MasterRunner(DistributedRunner):
|
|
|
917
917
|
self.greenlet.kill(block=True)
|
|
918
918
|
|
|
919
919
|
def check_stopped(self) -> None:
|
|
920
|
-
if (
|
|
921
|
-
|
|
922
|
-
and all(x.state == STATE_INIT for x in self.clients.all)
|
|
923
|
-
or all(x.state not in (STATE_RUNNING, STATE_SPAWNING, STATE_INIT) for x in self.clients.all)
|
|
920
|
+
if (self.state == STATE_STOPPING and all(x.state == STATE_INIT for x in self.clients.all)) or all(
|
|
921
|
+
x.state not in (STATE_RUNNING, STATE_SPAWNING, STATE_INIT) for x in self.clients.all
|
|
924
922
|
):
|
|
925
923
|
self.update_state(STATE_STOPPED)
|
|
926
924
|
|
|
@@ -938,7 +936,7 @@ class MasterRunner(DistributedRunner):
|
|
|
938
936
|
missing_clients_to_be_removed.append(client.id)
|
|
939
937
|
|
|
940
938
|
if client.heartbeat < 0 and client.state != STATE_MISSING:
|
|
941
|
-
logger.info(f"Worker {
|
|
939
|
+
logger.info(f"Worker {client.id!s} failed to send heartbeat, setting state to missing.")
|
|
942
940
|
client.state = STATE_MISSING
|
|
943
941
|
client.user_classes_count = {}
|
|
944
942
|
if self._users_dispatcher is not None:
|
|
@@ -1023,7 +1021,7 @@ class MasterRunner(DistributedRunner):
|
|
|
1023
1021
|
elif msg.data != __version__ and msg.data != -1:
|
|
1024
1022
|
if msg.data[0:4] == __version__[0:4]:
|
|
1025
1023
|
logger.debug(
|
|
1026
|
-
f"A worker ({client_id}) running a different patch version ({
|
|
1024
|
+
f"A worker ({client_id}) running a different patch version ({msg.data!r}) connected, master version is {__version__!r}"
|
|
1027
1025
|
)
|
|
1028
1026
|
else:
|
|
1029
1027
|
logger.warning(
|
|
@@ -1113,7 +1111,7 @@ class MasterRunner(DistributedRunner):
|
|
|
1113
1111
|
c.heartbeat = HEARTBEAT_LIVENESS
|
|
1114
1112
|
client_state = msg.data["state"]
|
|
1115
1113
|
if c.state == STATE_MISSING:
|
|
1116
|
-
logger.info(f"Worker {
|
|
1114
|
+
logger.info(f"Worker {c.id!s} self-healed with heartbeat, setting state to {client_state}.")
|
|
1117
1115
|
if self._users_dispatcher is not None:
|
|
1118
1116
|
self._users_dispatcher.add_worker(worker_node=c)
|
|
1119
1117
|
if not self._users_dispatcher.dispatch_in_progress and self.state == STATE_RUNNING:
|
|
@@ -539,7 +539,7 @@ class StatsEntry:
|
|
|
539
539
|
# (which is what the response times cache is used for) uses an approximation of the
|
|
540
540
|
# last 10 seconds anyway, it should be fine to ignore this.
|
|
541
541
|
last_time = int(self.last_request_timestamp) if self.last_request_timestamp else None
|
|
542
|
-
if last_time and last_time > (old_last_request_timestamp and int(old_last_request_timestamp) or 0):
|
|
542
|
+
if last_time and last_time > ((old_last_request_timestamp and int(old_last_request_timestamp)) or 0):
|
|
543
543
|
self._cache_response_times(last_time)
|
|
544
544
|
|
|
545
545
|
def serialize(self) -> StatsEntryDict:
|
|
@@ -585,7 +585,7 @@ class StatsEntry:
|
|
|
585
585
|
+ str((STATS_NAME_WIDTH - STATS_TYPE_WIDTH) + 4)
|
|
586
586
|
+ "s %7d %12s |%7d %7d %7d%7d | %7.2f %11.2f"
|
|
587
587
|
) % (
|
|
588
|
-
(self.method and self.method + " " or ""),
|
|
588
|
+
((self.method and self.method + " ") or ""),
|
|
589
589
|
self.name,
|
|
590
590
|
self.num_requests,
|
|
591
591
|
"%d(%.2f%%)" % (self.num_failures, self.fail_ratio * 100),
|
|
@@ -661,12 +661,15 @@ class StatsEntry:
|
|
|
661
661
|
if not self.num_requests:
|
|
662
662
|
raise ValueError("Can't calculate percentile on url with no successful requests")
|
|
663
663
|
|
|
664
|
-
tpl = f"%-{
|
|
664
|
+
tpl = f"%-{STATS_TYPE_WIDTH!s}s %-{STATS_NAME_WIDTH!s}s %8d {' '.join(['%6d'] * len(PERCENTILES_TO_REPORT))}"
|
|
665
665
|
|
|
666
666
|
return tpl % (
|
|
667
|
-
(
|
|
668
|
-
|
|
669
|
-
|
|
667
|
+
(
|
|
668
|
+
self.method or "",
|
|
669
|
+
self.name,
|
|
670
|
+
*tuple(self.get_response_time_percentile(p) for p in PERCENTILES_TO_REPORT),
|
|
671
|
+
self.num_requests,
|
|
672
|
+
)
|
|
670
673
|
)
|
|
671
674
|
|
|
672
675
|
def _cache_response_times(self, t: int) -> None:
|
|
@@ -897,9 +900,9 @@ def get_percentile_stats_summary(stats: RequestStats) -> list[str]:
|
|
|
897
900
|
Percentile stats summary will be returned as list of string
|
|
898
901
|
"""
|
|
899
902
|
summary = ["Response time percentiles (approximated)"]
|
|
900
|
-
headers = ("Type", "Name"
|
|
903
|
+
headers = ("Type", "Name", *tuple(get_readable_percentiles(PERCENTILES_TO_REPORT)), "# reqs")
|
|
901
904
|
summary.append(
|
|
902
|
-
|
|
905
|
+
f"%-{STATS_TYPE_WIDTH!s}s %-{STATS_NAME_WIDTH!s}s %8s {' '.join(['%6s'] * len(PERCENTILES_TO_REPORT))}"
|
|
903
906
|
% headers
|
|
904
907
|
)
|
|
905
908
|
separator = (
|
|
@@ -1008,7 +1011,8 @@ class StatsCSV:
|
|
|
1008
1011
|
"Average Content Size",
|
|
1009
1012
|
"Requests/s",
|
|
1010
1013
|
"Failures/s",
|
|
1011
|
-
|
|
1014
|
+
*get_readable_percentiles(self.percentiles_to_report),
|
|
1015
|
+
]
|
|
1012
1016
|
|
|
1013
1017
|
self.failures_columns = [
|
|
1014
1018
|
"Method",
|
|
@@ -1190,8 +1194,8 @@ class StatsCSVFileWriter(StatsCSV):
|
|
|
1190
1194
|
|
|
1191
1195
|
def _stats_history_data_rows(self, csv_writer: CSVWriter, now: float) -> None:
|
|
1192
1196
|
"""
|
|
1193
|
-
Write CSV rows with the *current* stats. By default only includes the
|
|
1194
|
-
Aggregated stats entry, but if self.full_history is set to True, a row for each entry
|
|
1197
|
+
Write CSV rows with the *current* stats. By default, only includes the
|
|
1198
|
+
Aggregated stats entry, but if self.full_history is set to True, a row for each entry
|
|
1195
1199
|
will be included.
|
|
1196
1200
|
|
|
1197
1201
|
Note that this method differs from the other methods as it appends time-stamped data to the file, whereas the other methods overwrites the data.
|
|
@@ -24,10 +24,8 @@ def memoize(timeout, dynamic_timeout=False):
|
|
|
24
24
|
return cache["result"]
|
|
25
25
|
|
|
26
26
|
def clear_cache():
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
if "result" in cache:
|
|
30
|
-
del cache["result"]
|
|
27
|
+
cache.pop("time", None)
|
|
28
|
+
cache.pop("result", None)
|
|
31
29
|
|
|
32
30
|
wrapper.clear_cache = clear_cache
|
|
33
31
|
return wrapper
|
|
@@ -20,4 +20,4 @@ def format_duration(start_time, end_time):
|
|
|
20
20
|
|
|
21
21
|
parts = [f"{value} {label}{'s' if value != 1 else ''}" for value, label in time_parts if value > 0]
|
|
22
22
|
|
|
23
|
-
return " and ".join(filter(None, [", ".join(parts[:-1])
|
|
23
|
+
return " and ".join(filter(None, [", ".join(parts[:-1]), *parts[-1:]])) if parts else "0 seconds"
|
|
@@ -274,7 +274,7 @@ class WebUI:
|
|
|
274
274
|
err_msg = f"Invalid user_count value: {value!r} (must be an integer)"
|
|
275
275
|
logger.error(err_msg)
|
|
276
276
|
return jsonify({"success": False, "message": err_msg, "host": environment.host})
|
|
277
|
-
parsed_options_dict["
|
|
277
|
+
parsed_options_dict["num_users"] = user_count
|
|
278
278
|
case "spawn_rate":
|
|
279
279
|
try:
|
|
280
280
|
spawn_rate = float(value)
|
|
@@ -81,7 +81,7 @@ test = [
|
|
|
81
81
|
]
|
|
82
82
|
lint = [
|
|
83
83
|
"pre-commit>=4.5.0,<5.0.0",
|
|
84
|
-
"ruff==0.
|
|
84
|
+
"ruff==0.16.8",
|
|
85
85
|
"mypy>=1.13.0,<1.15.0",
|
|
86
86
|
"types-requests==2.32.4.20250809",
|
|
87
87
|
"typos>=1.50.1"
|
|
@@ -159,8 +159,8 @@ extend-exclude = [
|
|
|
159
159
|
"src/readthedocs-sphinx-search/",
|
|
160
160
|
"examples/grpc/hello_pb2*.py",
|
|
161
161
|
]
|
|
162
|
-
lint.ignore = ["E402", "E501", "E713", "E731", "E741", "UP031", "PERF203"]
|
|
163
|
-
lint.select = ["E", "F", "W", "UP", "FA102", "I001", "FURB", "PERF"]
|
|
162
|
+
lint.ignore = ["E402", "E501", "E713", "E731", "E741", "UP031", "PERF203", "RUF012", "RUF059", "RUF015"]
|
|
163
|
+
lint.select = ["E", "F", "W", "UP", "FA102", "I001", "FURB", "PERF", "RUF"]
|
|
164
164
|
lint.dummy-variable-rgx = "^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?)|resp)$"
|
|
165
165
|
|
|
166
166
|
[tool.ruff.lint.per-file-ignores]
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -36,28 +36,28 @@ from .user.wait_time import between, constant, constant_pacing, constant_through
|
|
|
36
36
|
events = Events()
|
|
37
37
|
|
|
38
38
|
__all__ = (
|
|
39
|
-
"
|
|
39
|
+
"FastHttpUser",
|
|
40
|
+
"HttpLocust",
|
|
41
|
+
"HttpUser",
|
|
42
|
+
"LoadTestShape",
|
|
43
|
+
"Locust",
|
|
40
44
|
"MarkovTaskSet",
|
|
41
|
-
"
|
|
42
|
-
"transitions",
|
|
43
|
-
"wait_time",
|
|
44
|
-
"task",
|
|
45
|
-
"tag",
|
|
45
|
+
"SequentialTaskSet",
|
|
46
46
|
"TaskSet",
|
|
47
|
-
"HttpUser",
|
|
48
|
-
"FastHttpUser",
|
|
49
47
|
"User",
|
|
48
|
+
"__version__",
|
|
50
49
|
"between",
|
|
51
50
|
"constant",
|
|
52
51
|
"constant_pacing",
|
|
53
52
|
"constant_throughput",
|
|
54
|
-
"poisson",
|
|
55
53
|
"events",
|
|
56
|
-
"
|
|
54
|
+
"poisson",
|
|
57
55
|
"run_single_user",
|
|
58
|
-
"
|
|
59
|
-
"
|
|
60
|
-
"
|
|
56
|
+
"tag",
|
|
57
|
+
"task",
|
|
58
|
+
"transition",
|
|
59
|
+
"transitions",
|
|
60
|
+
"wait_time",
|
|
61
61
|
)
|
|
62
62
|
|
|
63
63
|
# Used for raising a DeprecationWarning if old Locust/HttpLocust is used
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|