locust 2.40.1.dev3__py3-none-any.whl → 2.40.2.dev5__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
@@ -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.1.dev3'
32
- __version_tuple__ = version_tuple = (2, 40, 1, 'dev3')
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
locust/clients.py CHANGED
@@ -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
- if catch_response:
226
- return ResponseContextManager(response, request_event=self.request_event, request_meta=request_meta)
227
- else:
228
- with ResponseContextManager(response, request_event=self.request_event, request_meta=request_meta):
229
- pass
230
- return response
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 | LocustResponse:
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
- r = LocustResponse()
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 | Response | LocustResponse:
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 | Response | LocustResponse:
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 | Response | LocustResponse:
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 | Response | LocustResponse:
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 | Response | LocustResponse:
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 | Response | LocustResponse:
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 | Response | LocustResponse:
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(LocustResponse):
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
- _manual_result: bool | Exception | None = None
335
- _entered = False
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 __init__(self, response, request_event, request_meta):
338
- # copy data from response to this object
339
- self.__dict__ = response.__dict__
340
- self._request_event = request_event
341
- self.request_meta = request_meta
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]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: locust
3
- Version: 2.40.1.dev3
3
+ Version: 2.40.2.dev5
4
4
  Summary: Developer-friendly load testing framework
5
5
  Project-URL: homepage, https://locust.io/
6
6
  Project-URL: repository, https://github.com/locustio/locust
@@ -1,8 +1,8 @@
1
1
  locust/__init__.py,sha256=HadpgGidiyCDPSKwkxrk1Qw6eB7dTmftNJVftuJzAiw,1876
2
2
  locust/__main__.py,sha256=vBQ82334kX06ImDbFlPFgiBRiLIinwNk3z8Khs6hd74,31
3
- locust/_version.py,sha256=oRunfbK94kezAV4ZFEs-1TWETR02ruzZx0kctOeYEBg,719
3
+ locust/_version.py,sha256=1ziw0TRdohsNerhSJZwgmEBdG3mVsgT4vcWEPXrc0Ug,719
4
4
  locust/argument_parser.py,sha256=t6mAoK9u13DxC9UH-alVqS6fFABFTyNWSJG89yQ4QQQ,33056
5
- locust/clients.py,sha256=CeyTYgKuASZS6QKc71T4V3bqYPGlJr3Ef_i6qP07gTQ,19498
5
+ locust/clients.py,sha256=Gj1rD73_G7G7f6bi0plDiN-GIDPTBng8pBY21cFozQc,20219
6
6
  locust/debug.py,sha256=7CCm8bIg44uGH2wqBlo1rXBzV2VzwPicLxLewz8r5CQ,5099
7
7
  locust/dispatch.py,sha256=prdwtb9EoN4A9klgiKgWuwQmvFB8hEuFHOK6ot62AJI,16202
8
8
  locust/env.py,sha256=PypNHmEFBhGBk9dU6pZ2cL5L0TThYejaGWW16RO3ZNQ,13203
@@ -13,7 +13,6 @@ locust/input_events.py,sha256=lqLDB2Ax-OQ7-vtYNkGjySjfaWVobBzqf0GxRwjcLcQ,3323
13
13
  locust/log.py,sha256=5E2ZUOa3V4sfCqa-470Gle1Ik9L5nxYitsjEB9tRwE0,3455
14
14
  locust/main.py,sha256=rcUD3MnBnFqeXC41fjGkh4p9POLGWglgPvRAfHKtEnc,28896
15
15
  locust/py.typed,sha256=gkWLl8yD4mIZnNYYAIRM8g9VarLvWmTAFeUfEbxJLBw,65
16
- locust/pytestplugin.py,sha256=yV_TQtxVI8gHe0J4sjZNMCOp43EO-XyMVjn0cyfkquw,1457
17
16
  locust/runners.py,sha256=niYmGsfOpxMfVmTXGod4MYTefpaZ2wirFlhqxRw5mq4,70617
18
17
  locust/shape.py,sha256=t-lwBS8LOjWcKXNL7j2U3zroIXJ1b0fazUwpRYQOKXw,1973
19
18
  locust/stats.py,sha256=qyoSKT0i7RunLDj5pMGqizK1Sp8bcqUsXwh2m4_DpR8,47203
@@ -56,8 +55,9 @@ locust/webui/dist/assets/index-BjqxSg7R.js,sha256=3JyrKWfAg8LlTy2bxAJh73c6njNPhN
56
55
  locust/webui/dist/assets/terminal.gif,sha256=iw80LO2u0dnf4wpGfFJZauBeKTcSpw9iUfISXT2nEF4,75302
57
56
  locust/webui/dist/assets/testruns-dark.png,sha256=G4p2VZSBuuqF4neqUaPSshIp5OKQJ_Bvb69Luj6XuVs,125231
58
57
  locust/webui/dist/assets/testruns-light.png,sha256=JinGDiiBPOkhpfF-XCbmQqhRInqItrjrBTLKt5MlqVI,130301
59
- locust-2.40.1.dev3.dist-info/METADATA,sha256=k8EhqThhdEJje-cyNV0eJZANJgWLCG6ERKtTILMUPrY,9598
60
- locust-2.40.1.dev3.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
61
- locust-2.40.1.dev3.dist-info/entry_points.txt,sha256=k0386Xi0vBR3OVIqeGNYz7cz8QUGJ3iLmQ0WQU91ogw,85
62
- locust-2.40.1.dev3.dist-info/licenses/LICENSE,sha256=5hnz-Vpj0Z3kSCQl0LzV2hT1TLc4LHcbpBp3Cy-EuyM,1110
63
- locust-2.40.1.dev3.dist-info/RECORD,,
58
+ pytest_locust/plugin.py,sha256=WAyiRHLynXegbbX2DxIutPKO4PQRT6JdBFA7zbbaJgM,1469
59
+ locust-2.40.2.dev5.dist-info/METADATA,sha256=Q1gtnoXRRbFrtKhkxCHE42T1M8Cx74NiVmP-fHioo24,9598
60
+ locust-2.40.2.dev5.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
61
+ locust-2.40.2.dev5.dist-info/entry_points.txt,sha256=0uIHcQ71R1qaWhM_sd8uBUCCJgp7gJfGHUVMnJeZfcY,86
62
+ locust-2.40.2.dev5.dist-info/licenses/LICENSE,sha256=5hnz-Vpj0Z3kSCQl0LzV2hT1TLc4LHcbpBp3Cy-EuyM,1110
63
+ locust-2.40.2.dev5.dist-info/RECORD,,
@@ -2,4 +2,4 @@
2
2
  locust = locust.main:main
3
3
 
4
4
  [pytest11]
5
- locust = locust.pytestplugin
5
+ locust = pytest_locust.plugin
@@ -1,4 +1,4 @@
1
- # This is used in pytest-based, see examples/test_pytest.py
1
+ # This is used in pytest style locustfiles, see examples/test_pytest.py
2
2
  from typing import TYPE_CHECKING
3
3
 
4
4
  import pytest