locust 2.40.1.dev3__tar.gz → 2.40.2.dev5__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.40.1.dev3 → locust-2.40.2.dev5}/PKG-INFO +1 -1
- {locust-2.40.1.dev3 → locust-2.40.2.dev5}/locust/_version.py +2 -2
- {locust-2.40.1.dev3 → locust-2.40.2.dev5}/locust/clients.py +56 -38
- {locust-2.40.1.dev3 → locust-2.40.2.dev5}/pyproject.toml +3 -3
- locust-2.40.1.dev3/locust/pytestplugin.py → locust-2.40.2.dev5/pytest_locust/plugin.py +1 -1
- {locust-2.40.1.dev3 → locust-2.40.2.dev5}/.gitignore +0 -0
- {locust-2.40.1.dev3 → locust-2.40.2.dev5}/LICENSE +0 -0
- {locust-2.40.1.dev3 → locust-2.40.2.dev5}/README.md +0 -0
- {locust-2.40.1.dev3 → locust-2.40.2.dev5}/hatch_build.py +0 -0
- {locust-2.40.1.dev3 → locust-2.40.2.dev5}/locust/__init__.py +0 -0
- {locust-2.40.1.dev3 → locust-2.40.2.dev5}/locust/__main__.py +0 -0
- {locust-2.40.1.dev3 → locust-2.40.2.dev5}/locust/argument_parser.py +0 -0
- {locust-2.40.1.dev3 → locust-2.40.2.dev5}/locust/contrib/__init__.py +0 -0
- {locust-2.40.1.dev3 → locust-2.40.2.dev5}/locust/contrib/fasthttp.py +0 -0
- {locust-2.40.1.dev3 → locust-2.40.2.dev5}/locust/contrib/milvus.py +0 -0
- {locust-2.40.1.dev3 → locust-2.40.2.dev5}/locust/contrib/mongodb.py +0 -0
- {locust-2.40.1.dev3 → locust-2.40.2.dev5}/locust/contrib/oai.py +0 -0
- {locust-2.40.1.dev3 → locust-2.40.2.dev5}/locust/contrib/postgres.py +0 -0
- {locust-2.40.1.dev3 → locust-2.40.2.dev5}/locust/contrib/socketio.py +0 -0
- {locust-2.40.1.dev3 → locust-2.40.2.dev5}/locust/debug.py +0 -0
- {locust-2.40.1.dev3 → locust-2.40.2.dev5}/locust/dispatch.py +0 -0
- {locust-2.40.1.dev3 → locust-2.40.2.dev5}/locust/env.py +0 -0
- {locust-2.40.1.dev3 → locust-2.40.2.dev5}/locust/event.py +0 -0
- {locust-2.40.1.dev3 → locust-2.40.2.dev5}/locust/exception.py +0 -0
- {locust-2.40.1.dev3 → locust-2.40.2.dev5}/locust/html.py +0 -0
- {locust-2.40.1.dev3 → locust-2.40.2.dev5}/locust/input_events.py +0 -0
- {locust-2.40.1.dev3 → locust-2.40.2.dev5}/locust/log.py +0 -0
- {locust-2.40.1.dev3 → locust-2.40.2.dev5}/locust/main.py +0 -0
- {locust-2.40.1.dev3 → locust-2.40.2.dev5}/locust/py.typed +0 -0
- {locust-2.40.1.dev3 → locust-2.40.2.dev5}/locust/rpc/__init__.py +0 -0
- {locust-2.40.1.dev3 → locust-2.40.2.dev5}/locust/rpc/protocol.py +0 -0
- {locust-2.40.1.dev3 → locust-2.40.2.dev5}/locust/rpc/zmqrpc.py +0 -0
- {locust-2.40.1.dev3 → locust-2.40.2.dev5}/locust/runners.py +0 -0
- {locust-2.40.1.dev3 → locust-2.40.2.dev5}/locust/shape.py +0 -0
- {locust-2.40.1.dev3 → locust-2.40.2.dev5}/locust/stats.py +0 -0
- {locust-2.40.1.dev3 → locust-2.40.2.dev5}/locust/user/__init__.py +0 -0
- {locust-2.40.1.dev3 → locust-2.40.2.dev5}/locust/user/inspectuser.py +0 -0
- {locust-2.40.1.dev3 → locust-2.40.2.dev5}/locust/user/markov_taskset.py +0 -0
- {locust-2.40.1.dev3 → locust-2.40.2.dev5}/locust/user/sequential_taskset.py +0 -0
- {locust-2.40.1.dev3 → locust-2.40.2.dev5}/locust/user/task.py +0 -0
- {locust-2.40.1.dev3 → locust-2.40.2.dev5}/locust/user/users.py +0 -0
- {locust-2.40.1.dev3 → locust-2.40.2.dev5}/locust/user/wait_time.py +0 -0
- {locust-2.40.1.dev3 → locust-2.40.2.dev5}/locust/util/__init__.py +0 -0
- {locust-2.40.1.dev3 → locust-2.40.2.dev5}/locust/util/cache.py +0 -0
- {locust-2.40.1.dev3 → locust-2.40.2.dev5}/locust/util/date.py +0 -0
- {locust-2.40.1.dev3 → locust-2.40.2.dev5}/locust/util/deprecation.py +0 -0
- {locust-2.40.1.dev3 → locust-2.40.2.dev5}/locust/util/directory.py +0 -0
- {locust-2.40.1.dev3 → locust-2.40.2.dev5}/locust/util/exception_handler.py +0 -0
- {locust-2.40.1.dev3 → locust-2.40.2.dev5}/locust/util/load_locustfile.py +0 -0
- {locust-2.40.1.dev3 → locust-2.40.2.dev5}/locust/util/rounding.py +0 -0
- {locust-2.40.1.dev3 → locust-2.40.2.dev5}/locust/util/timespan.py +0 -0
- {locust-2.40.1.dev3 → locust-2.40.2.dev5}/locust/util/url.py +0 -0
- {locust-2.40.1.dev3 → locust-2.40.2.dev5}/locust/web.py +0 -0
- {locust-2.40.1.dev3 → locust-2.40.2.dev5}/locust/webui/dist/assets/favicon-dark.png +0 -0
- {locust-2.40.1.dev3 → locust-2.40.2.dev5}/locust/webui/dist/assets/favicon-light.png +0 -0
- {locust-2.40.1.dev3 → locust-2.40.2.dev5}/locust/webui/dist/assets/graphs-dark.png +0 -0
- {locust-2.40.1.dev3 → locust-2.40.2.dev5}/locust/webui/dist/assets/graphs-light.png +0 -0
- {locust-2.40.1.dev3 → locust-2.40.2.dev5}/locust/webui/dist/assets/index-BjqxSg7R.js +0 -0
- {locust-2.40.1.dev3 → locust-2.40.2.dev5}/locust/webui/dist/assets/terminal.gif +0 -0
- {locust-2.40.1.dev3 → locust-2.40.2.dev5}/locust/webui/dist/assets/testruns-dark.png +0 -0
- {locust-2.40.1.dev3 → locust-2.40.2.dev5}/locust/webui/dist/assets/testruns-light.png +0 -0
- {locust-2.40.1.dev3 → locust-2.40.2.dev5}/locust/webui/dist/auth.html +0 -0
- {locust-2.40.1.dev3 → locust-2.40.2.dev5}/locust/webui/dist/index.html +0 -0
- {locust-2.40.1.dev3 → locust-2.40.2.dev5}/locust/webui/dist/report.html +0 -0
@@ -28,7 +28,7 @@ version_tuple: VERSION_TUPLE
|
|
28
28
|
commit_id: COMMIT_ID
|
29
29
|
__commit_id__: COMMIT_ID
|
30
30
|
|
31
|
-
__version__ = version = '2.40.
|
32
|
-
__version_tuple__ = version_tuple = (2, 40,
|
31
|
+
__version__ = version = '2.40.2.dev5'
|
32
|
+
__version_tuple__ = version_tuple = (2, 40, 2, 'dev5')
|
33
33
|
|
34
34
|
__commit_id__ = commit_id = None
|
@@ -1,9 +1,11 @@
|
|
1
1
|
from __future__ import annotations
|
2
2
|
|
3
|
+
from locust.event import EventHook
|
4
|
+
|
3
5
|
import re
|
4
6
|
import time
|
5
7
|
from contextlib import contextmanager
|
6
|
-
from typing import TYPE_CHECKING
|
8
|
+
from typing import TYPE_CHECKING, cast
|
7
9
|
from urllib.parse import urlparse, urlunparse
|
8
10
|
|
9
11
|
import requests
|
@@ -53,15 +55,6 @@ if TYPE_CHECKING:
|
|
53
55
|
absolute_http_url_regexp = re.compile(r"^https?://", re.I)
|
54
56
|
|
55
57
|
|
56
|
-
class LocustResponse(Response):
|
57
|
-
error: Exception | None = None
|
58
|
-
|
59
|
-
def raise_for_status(self) -> None:
|
60
|
-
if self.error:
|
61
|
-
raise self.error
|
62
|
-
Response.raise_for_status(self)
|
63
|
-
|
64
|
-
|
65
58
|
class HttpSession(requests.Session):
|
66
59
|
"""
|
67
60
|
Class for performing web requests and holding (session-) cookies between requests (in order
|
@@ -142,7 +135,7 @@ class HttpSession(requests.Session):
|
|
142
135
|
data: Any = None,
|
143
136
|
json: Any = None,
|
144
137
|
**kwargs: Unpack[RequestKwargs],
|
145
|
-
):
|
138
|
+
) -> ResponseContextManager:
|
146
139
|
"""
|
147
140
|
Constructs and sends a :py:class:`requests.Request`.
|
148
141
|
Returns :py:class:`requests.Response` object.
|
@@ -222,14 +215,14 @@ class HttpSession(requests.Session):
|
|
222
215
|
else:
|
223
216
|
request_meta["response_length"] = len(response.content or b"")
|
224
217
|
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
218
|
+
rcm = ResponseContextManager.wrap_response(
|
219
|
+
response, request_event=self.request_event, request_meta=request_meta, catch_response=catch_response
|
220
|
+
)
|
221
|
+
if not catch_response: # if not using with-block, report the request immediately
|
222
|
+
rcm.__exit__(None, None, None)
|
223
|
+
return rcm
|
231
224
|
|
232
|
-
def _send_request_safe_mode(self, method, url, **kwargs) -> Response
|
225
|
+
def _send_request_safe_mode(self, method, url, **kwargs) -> Response:
|
233
226
|
"""
|
234
227
|
Send an HTTP request, and catch any exception that might occur due to connection problems.
|
235
228
|
|
@@ -240,15 +233,11 @@ class HttpSession(requests.Session):
|
|
240
233
|
except (MissingSchema, InvalidSchema, InvalidURL):
|
241
234
|
raise
|
242
235
|
except RequestException as e:
|
243
|
-
|
244
|
-
r.error = e
|
245
|
-
r.status_code = 0
|
246
|
-
r.request = e.request # type: ignore
|
247
|
-
return r
|
236
|
+
return ResponseContextManager(e)
|
248
237
|
|
249
238
|
def get(
|
250
239
|
self, url: str | bytes, *, data: Any = None, json: Any = None, **kwargs: Unpack[RESTKwargs]
|
251
|
-
) -> ResponseContextManager
|
240
|
+
) -> ResponseContextManager:
|
252
241
|
"""Sends a GET request"""
|
253
242
|
kwargs.setdefault("allow_redirects", True)
|
254
243
|
return self.request("GET", url, data=data, json=json, **kwargs)
|
@@ -260,7 +249,7 @@ class HttpSession(requests.Session):
|
|
260
249
|
data: Any = None,
|
261
250
|
json: Any = None,
|
262
251
|
**kwargs: Unpack[RESTKwargs],
|
263
|
-
) -> ResponseContextManager
|
252
|
+
) -> ResponseContextManager:
|
264
253
|
"""Sends a OPTIONS request"""
|
265
254
|
kwargs.setdefault("allow_redirects", True)
|
266
255
|
return self.request("OPTIONS", url, data=data, json=json, **kwargs)
|
@@ -272,7 +261,7 @@ class HttpSession(requests.Session):
|
|
272
261
|
data: Any = None,
|
273
262
|
json: Any = None,
|
274
263
|
**kwargs: Unpack[RESTKwargs],
|
275
|
-
) -> ResponseContextManager
|
264
|
+
) -> ResponseContextManager:
|
276
265
|
"""Sends a HEAD request"""
|
277
266
|
kwargs.setdefault("allow_redirects", False)
|
278
267
|
return self.request("HEAD", url, data=data, json=json, **kwargs)
|
@@ -283,7 +272,7 @@ class HttpSession(requests.Session):
|
|
283
272
|
data: Any = None,
|
284
273
|
json: Any = None,
|
285
274
|
**kwargs: Unpack[RESTKwargs],
|
286
|
-
) -> ResponseContextManager
|
275
|
+
) -> ResponseContextManager:
|
287
276
|
"""Sends a POST request"""
|
288
277
|
return self.request("POST", url, data=data, json=json, **kwargs)
|
289
278
|
|
@@ -294,7 +283,7 @@ class HttpSession(requests.Session):
|
|
294
283
|
*,
|
295
284
|
json: Any = None,
|
296
285
|
**kwargs: Unpack[RESTKwargs],
|
297
|
-
) -> ResponseContextManager
|
286
|
+
) -> ResponseContextManager:
|
298
287
|
"""Sends a PUT request"""
|
299
288
|
return self.request("PUT", url, data=data, json=json, **kwargs)
|
300
289
|
|
@@ -305,7 +294,7 @@ class HttpSession(requests.Session):
|
|
305
294
|
*,
|
306
295
|
json: Any = None,
|
307
296
|
**kwargs: Unpack[RESTKwargs],
|
308
|
-
) -> ResponseContextManager
|
297
|
+
) -> ResponseContextManager:
|
309
298
|
"""Sends a PATCH request"""
|
310
299
|
return self.request("PATCH", url, data=data, json=json, **kwargs)
|
311
300
|
|
@@ -316,12 +305,12 @@ class HttpSession(requests.Session):
|
|
316
305
|
data: Any = None,
|
317
306
|
json: Any = None,
|
318
307
|
**kwargs: Unpack[RESTKwargs],
|
319
|
-
) -> ResponseContextManager
|
308
|
+
) -> ResponseContextManager:
|
320
309
|
"""Sends a DELETE request"""
|
321
310
|
return self.request("DELETE", url, data=data, json=json, **kwargs)
|
322
311
|
|
323
312
|
|
324
|
-
class ResponseContextManager(
|
313
|
+
class ResponseContextManager(Response):
|
325
314
|
"""
|
326
315
|
A Response class that also acts as a context manager that provides the ability to manually
|
327
316
|
control if an HTTP request should be marked as successful or a failure in Locust's statistics
|
@@ -331,17 +320,46 @@ class ResponseContextManager(LocustResponse):
|
|
331
320
|
:py:meth:`failure <locust.clients.ResponseContextManager.failure>`.
|
332
321
|
"""
|
333
322
|
|
334
|
-
|
335
|
-
|
323
|
+
error: Exception | None = None
|
324
|
+
_manual_result: bool | Exception | None
|
325
|
+
_entered: bool
|
326
|
+
_request_event: EventHook
|
327
|
+
request_meta: Mapping[str, Any]
|
328
|
+
_catch_response: bool
|
336
329
|
|
337
|
-
def
|
338
|
-
|
339
|
-
|
340
|
-
self
|
341
|
-
|
330
|
+
def raise_for_status(self) -> None:
|
331
|
+
if self.error:
|
332
|
+
raise self.error
|
333
|
+
Response.raise_for_status(self)
|
334
|
+
|
335
|
+
def __init__(self, error: RequestException):
|
336
|
+
"""
|
337
|
+
Direct instantiation is only used for errors caught when trying to send the request
|
338
|
+
Normally instances of this class are created from using wrap_response() on a Response object
|
339
|
+
"""
|
340
|
+
super().__init__()
|
341
|
+
self.error = error
|
342
|
+
self.status_code = 0
|
343
|
+
self.request = error.request # type: ignore
|
344
|
+
|
345
|
+
@classmethod
|
346
|
+
def wrap_response(
|
347
|
+
cls, response: Response, request_event: EventHook, request_meta: Mapping[str, Any], catch_response: bool
|
348
|
+
) -> ResponseContextManager:
|
349
|
+
"""Modify a Response object in-place, for efficiency reasons"""
|
350
|
+
response.__class__ = ResponseContextManager
|
351
|
+
response = cast(ResponseContextManager, response)
|
352
|
+
response._entered = False
|
353
|
+
response._manual_result = None
|
354
|
+
response._request_event = request_event
|
355
|
+
response._catch_response = catch_response
|
356
|
+
response.request_meta = request_meta
|
357
|
+
return response
|
342
358
|
|
343
359
|
def __enter__(self):
|
344
360
|
self._entered = True
|
361
|
+
if not self._catch_response:
|
362
|
+
raise LocustError("In order to use a with-block for requests, you must also pass catch_response=True")
|
345
363
|
return self
|
346
364
|
|
347
365
|
def __exit__(self, exc, value, traceback): # type: ignore[override]
|
@@ -120,12 +120,12 @@ source = "vcs"
|
|
120
120
|
version-file = "locust/_version.py"
|
121
121
|
|
122
122
|
[tool.hatch.build.targets.sdist]
|
123
|
-
include = ["locust"]
|
123
|
+
include = ["locust", "pytest_locust"]
|
124
124
|
exclude = ["locust/webui/*", "locust/test", "locust/build"]
|
125
125
|
artifacts = ["locust/webui/dist"]
|
126
126
|
|
127
127
|
[tool.hatch.build.targets.wheel]
|
128
|
-
include = ["locust"]
|
128
|
+
include = ["locust", "pytest_locust"]
|
129
129
|
artifacts = ["locust/webui/dist"]
|
130
130
|
|
131
131
|
[tool.hatch.version.raw-options]
|
@@ -265,4 +265,4 @@ python = ["3.12"]
|
|
265
265
|
build = ["sphinx-build -b html docs/ docs/_build/"]
|
266
266
|
|
267
267
|
[project.entry-points.pytest11]
|
268
|
-
locust = "
|
268
|
+
locust = "pytest_locust.plugin"
|
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
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|