locust 2.24.2.dev24__py3-none-any.whl → 2.25.1.dev8__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 +2 -2
- locust/contrib/fasthttp.py +4 -4
- locust/dispatch.py +44 -9
- locust/test/test_dispatch.py +69 -0
- locust/test/test_fasthttp.py +1 -1
- {locust-2.24.2.dev24.dist-info → locust-2.25.1.dev8.dist-info}/METADATA +4 -5
- {locust-2.24.2.dev24.dist-info → locust-2.25.1.dev8.dist-info}/RECORD +11 -11
- {locust-2.24.2.dev24.dist-info → locust-2.25.1.dev8.dist-info}/LICENSE +0 -0
- {locust-2.24.2.dev24.dist-info → locust-2.25.1.dev8.dist-info}/WHEEL +0 -0
- {locust-2.24.2.dev24.dist-info → locust-2.25.1.dev8.dist-info}/entry_points.txt +0 -0
- {locust-2.24.2.dev24.dist-info → locust-2.25.1.dev8.dist-info}/top_level.txt +0 -0
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.
|
16
|
-
__version_tuple__ = version_tuple = (2,
|
15
|
+
__version__ = version = '2.25.1.dev8'
|
16
|
+
__version_tuple__ = version_tuple = (2, 25, 1, 'dev8')
|
locust/contrib/fasthttp.py
CHANGED
@@ -306,11 +306,11 @@ class FastHttpUser(User):
|
|
306
306
|
connection_timeout: float = 60.0
|
307
307
|
"""Parameter passed to FastHttpSession"""
|
308
308
|
|
309
|
-
max_redirects: int =
|
310
|
-
"""Parameter passed to FastHttpSession.
|
309
|
+
max_redirects: int = 30
|
310
|
+
"""Parameter passed to FastHttpSession."""
|
311
311
|
|
312
|
-
max_retries: int =
|
313
|
-
"""Parameter passed to FastHttpSession.
|
312
|
+
max_retries: int = 0
|
313
|
+
"""Parameter passed to FastHttpSession."""
|
314
314
|
|
315
315
|
insecure: bool = True
|
316
316
|
"""Parameter passed to FastHttpSession. Default True, meaning no SSL verification."""
|
locust/dispatch.py
CHANGED
@@ -1,8 +1,10 @@
|
|
1
1
|
from __future__ import annotations
|
2
2
|
|
3
3
|
import contextlib
|
4
|
+
import functools
|
4
5
|
import itertools
|
5
6
|
import math
|
7
|
+
import sys
|
6
8
|
import time
|
7
9
|
from collections import defaultdict
|
8
10
|
from operator import attrgetter
|
@@ -16,6 +18,20 @@ if TYPE_CHECKING:
|
|
16
18
|
from locust.runners import WorkerNode
|
17
19
|
|
18
20
|
|
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
|
+
|
19
35
|
# To profile line-by-line, uncomment the code below (i.e. `import line_profiler ...`) and
|
20
36
|
# place `@profile` on the functions/methods you wish to profile. Then, in the unit test you are
|
21
37
|
# running, use `from locust.dispatch import profile; profile.print_stats()` at the end of the unit test.
|
@@ -366,18 +382,37 @@ class UsersDispatcher(Iterator):
|
|
366
382
|
if not users:
|
367
383
|
return itertools.cycle([None])
|
368
384
|
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
385
|
+
def _get_order_of_magnitude(n: float) -> int:
|
386
|
+
"""Get how many times we need to multiply `n` to get an integer-like number.
|
387
|
+
For example:
|
388
|
+
0.1 would return 10,
|
389
|
+
0.04 would return 100,
|
390
|
+
0.0007 would return 10000.
|
391
|
+
"""
|
392
|
+
if n <= 0:
|
393
|
+
raise ValueError("To get the order of magnitude, the number must be greater than 0.")
|
394
|
+
|
395
|
+
counter = 0
|
396
|
+
while n < 1:
|
397
|
+
n *= 10
|
398
|
+
counter += 1
|
399
|
+
return 10**counter
|
400
|
+
|
401
|
+
# Get maximum order of magnitude to "normalize the weights".
|
402
|
+
# "Normalizing the weights" is to multiply all weights by the same number so that
|
403
|
+
# they become integers. Then we can find the largest common divisor of all the
|
404
|
+
# weights, divide them by it and get the smallest possible numbers with the same
|
405
|
+
# ratio as the numbers originally had.
|
406
|
+
max_order_of_magnitude = _get_order_of_magnitude(min(abs(u[1]) for u in users))
|
407
|
+
weights = tuple(int(u[1] * max_order_of_magnitude) for u in users)
|
408
|
+
|
409
|
+
greatest_common_divisor = compatible_math_gcd(*weights)
|
375
410
|
normalized_values = [
|
376
411
|
(
|
377
|
-
user.__name__,
|
378
|
-
|
412
|
+
user[0].__name__,
|
413
|
+
normalized_weight // greatest_common_divisor,
|
379
414
|
)
|
380
|
-
for user,
|
415
|
+
for user, normalized_weight in zip(users, weights)
|
381
416
|
]
|
382
417
|
generation_length_to_get_proper_distribution = sum(
|
383
418
|
normalized_val[1] for normalized_val in normalized_values
|
locust/test/test_dispatch.py
CHANGED
@@ -847,6 +847,75 @@ class TestRampUpUsersFromZero(unittest.TestCase):
|
|
847
847
|
delta = time.perf_counter() - ts
|
848
848
|
self.assertTrue(0 <= delta <= _TOLERANCE, delta)
|
849
849
|
|
850
|
+
def test_implementation_of_dispatch_distribution_with_gcd(self):
|
851
|
+
class User1(User):
|
852
|
+
weight = 4
|
853
|
+
|
854
|
+
class User2(User):
|
855
|
+
weight = 5
|
856
|
+
|
857
|
+
user_classes = [User1, User2]
|
858
|
+
worker_node1 = WorkerNode("1")
|
859
|
+
|
860
|
+
sleep_time = 0.2 # Speed-up test
|
861
|
+
|
862
|
+
users_dispatcher = UsersDispatcher(worker_nodes=[worker_node1], user_classes=user_classes)
|
863
|
+
users_dispatcher.new_dispatch(target_user_count=9, spawn_rate=9)
|
864
|
+
|
865
|
+
users_dispatcher._wait_between_dispatch = sleep_time
|
866
|
+
|
867
|
+
ts = time.perf_counter()
|
868
|
+
self.assertDictEqual(
|
869
|
+
next(users_dispatcher),
|
870
|
+
{
|
871
|
+
"1": {"User1": 4, "User2": 5},
|
872
|
+
},
|
873
|
+
)
|
874
|
+
delta = time.perf_counter() - ts
|
875
|
+
self.assertTrue(0 <= delta <= _TOLERANCE, delta)
|
876
|
+
|
877
|
+
ts = time.perf_counter()
|
878
|
+
self.assertRaises(StopIteration, lambda: next(users_dispatcher))
|
879
|
+
delta = time.perf_counter() - ts
|
880
|
+
self.assertTrue(0 <= delta <= _TOLERANCE, delta)
|
881
|
+
|
882
|
+
def test_implementation_of_dispatch_distribution_with_gcd_float_weight(self):
|
883
|
+
class User1(User):
|
884
|
+
weight = 0.8
|
885
|
+
|
886
|
+
class User2(User):
|
887
|
+
weight = 1
|
888
|
+
|
889
|
+
normalized_weights_to_min_int = 5 # User1: 0.8 * 5 = 4; User2: 1 * 5 = 5
|
890
|
+
|
891
|
+
user_classes = [User1, User2]
|
892
|
+
worker_node1 = WorkerNode("1")
|
893
|
+
|
894
|
+
sleep_time = 0.2 # Speed-up test
|
895
|
+
|
896
|
+
users_dispatcher = UsersDispatcher(worker_nodes=[worker_node1], user_classes=user_classes)
|
897
|
+
users_dispatcher.new_dispatch(target_user_count=18, spawn_rate=18)
|
898
|
+
|
899
|
+
users_dispatcher._wait_between_dispatch = sleep_time
|
900
|
+
|
901
|
+
ts = time.perf_counter()
|
902
|
+
self.assertDictEqual(
|
903
|
+
next(users_dispatcher),
|
904
|
+
{
|
905
|
+
"1": {
|
906
|
+
"User1": int(normalized_weights_to_min_int * User1.weight * 2),
|
907
|
+
"User2": int(normalized_weights_to_min_int * User2.weight * 2),
|
908
|
+
},
|
909
|
+
},
|
910
|
+
)
|
911
|
+
delta = time.perf_counter() - ts
|
912
|
+
self.assertTrue(0 <= delta <= _TOLERANCE, delta)
|
913
|
+
|
914
|
+
ts = time.perf_counter()
|
915
|
+
self.assertRaises(StopIteration, lambda: next(users_dispatcher))
|
916
|
+
delta = time.perf_counter() - ts
|
917
|
+
self.assertTrue(0 <= delta <= _TOLERANCE, delta)
|
918
|
+
|
850
919
|
|
851
920
|
class TestWaitBetweenDispatch(unittest.TestCase):
|
852
921
|
def test_wait_between_dispatch(self):
|
locust/test/test_fasthttp.py
CHANGED
@@ -506,7 +506,7 @@ class TestFastHttpUserClass(WebserverTestCase):
|
|
506
506
|
|
507
507
|
def test_max_redirect_setting(self):
|
508
508
|
class MyUser(FastHttpUser):
|
509
|
-
max_redirects =
|
509
|
+
max_redirects = 0
|
510
510
|
host = "http://127.0.0.1:%i" % self.port
|
511
511
|
|
512
512
|
l = MyUser(self.environment)
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: locust
|
3
|
-
Version: 2.
|
3
|
+
Version: 2.25.1.dev8
|
4
4
|
Summary: Developer friendly load testing framework
|
5
5
|
License: MIT
|
6
6
|
Project-URL: Homepage, https://github.com/locustio/locust
|
@@ -14,7 +14,6 @@ Classifier: License :: OSI Approved :: MIT License
|
|
14
14
|
Classifier: Operating System :: OS Independent
|
15
15
|
Classifier: Programming Language :: Python
|
16
16
|
Classifier: Programming Language :: Python :: 3
|
17
|
-
Classifier: Programming Language :: Python :: 3.8
|
18
17
|
Classifier: Programming Language :: Python :: 3.9
|
19
18
|
Classifier: Programming Language :: Python :: 3.10
|
20
19
|
Classifier: Programming Language :: Python :: 3.11
|
@@ -24,7 +23,7 @@ Classifier: Intended Audience :: System Administrators
|
|
24
23
|
Classifier: Topic :: Software Development :: Testing
|
25
24
|
Classifier: Topic :: Software Development :: Testing :: Traffic Generation
|
26
25
|
Classifier: Topic :: System :: Distributed Computing
|
27
|
-
Requires-Python: >=3.
|
26
|
+
Requires-Python: >=3.9
|
28
27
|
Description-Content-Type: text/markdown
|
29
28
|
License-File: LICENSE
|
30
29
|
Requires-Dist: gevent >=22.10.2
|
@@ -33,7 +32,7 @@ Requires-Dist: Werkzeug >=2.0.0
|
|
33
32
|
Requires-Dist: requests >=2.26.0
|
34
33
|
Requires-Dist: msgpack >=1.0.0
|
35
34
|
Requires-Dist: pyzmq >=25.0.0
|
36
|
-
Requires-Dist: geventhttpclient >=2.
|
35
|
+
Requires-Dist: geventhttpclient >=2.2.1
|
37
36
|
Requires-Dist: ConfigArgParse >=1.5.5
|
38
37
|
Requires-Dist: psutil >=5.9.1
|
39
38
|
Requires-Dist: Flask-Login >=0.6.3
|
@@ -45,7 +44,7 @@ Requires-Dist: tomli >=1.1.0 ; python_version < "3.11"
|
|
45
44
|
# Locust
|
46
45
|
|
47
46
|
[](https://pypi.org/project/locust/)
|
48
|
-
|
47
|
+

|
49
48
|
[](https://pepy.tech/project/locust)
|
50
49
|
[](https://github.com/locustio/locust/actions?query=workflow%3ATests)
|
51
50
|
[](https://github.com/locustio/locust/graphs/contributors)
|
@@ -1,10 +1,10 @@
|
|
1
1
|
locust/__init__.py,sha256=g6oA-Ba_hs3gLWVf5MKJ1mvfltI8MFnDWG8qslqm8yg,1402
|
2
2
|
locust/__main__.py,sha256=vBQ82334kX06ImDbFlPFgiBRiLIinwNk3z8Khs6hd74,31
|
3
|
-
locust/_version.py,sha256=
|
3
|
+
locust/_version.py,sha256=W2iy6zTQVMHHk-IWLxYUWz82mKJaHowf07jlAUmqwRc,426
|
4
4
|
locust/argument_parser.py,sha256=W0X5t-9BFq1DtOBgTBbMoDYBIXfWEqUD7CZ5Rn-i6LQ,32016
|
5
5
|
locust/clients.py,sha256=o3G9welWb-zhgDUM5TKnMVFMJckr_m0FI8Dxn3OtBUA,14810
|
6
6
|
locust/debug.py,sha256=We6Z9W0btkKSc7PxWmrZx-xMynvOOsKhG6jmDgQin0g,5134
|
7
|
-
locust/dispatch.py,sha256=
|
7
|
+
locust/dispatch.py,sha256=sPtRRer_dJVOaLaIvVriIf4gLduvCcRf11O-E7ohzSc,20101
|
8
8
|
locust/env.py,sha256=nd6ui1bv6n-kkLkP3r61ZkskDY627dsKOAkYHhtOW7o,12472
|
9
9
|
locust/event.py,sha256=Dip3aRKyd4MhAkfd5nPYmWcGKtQEX8NH1mHT74INZT4,7713
|
10
10
|
locust/exception.py,sha256=jGgJ32ubuf4pWdlaVOkbh2Y0LlG0_DHi-lv3ib8ppOE,1791
|
@@ -18,7 +18,7 @@ locust/shape.py,sha256=t-lwBS8LOjWcKXNL7j2U3zroIXJ1b0fazUwpRYQOKXw,1973
|
|
18
18
|
locust/stats.py,sha256=BXvAybKiqI6QF5THdnk-fWkL-FiZKwrAm2W8KzkTchg,46118
|
19
19
|
locust/web.py,sha256=DVcx53VXApAc6kFfG7so2_kB_qqcw7ojKpBd-dJoijU,28267
|
20
20
|
locust/contrib/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
21
|
-
locust/contrib/fasthttp.py,sha256=
|
21
|
+
locust/contrib/fasthttp.py,sha256=OZtYHt0HEIRaiundpHC5w-J3xCG8NckrONXTS9UQQr8,26743
|
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
|
@@ -53,9 +53,9 @@ locust/test/fake_module2_for_env_test.py,sha256=dzGYWCr1SSkd8Yyo68paUNrCNW7YY_Qg
|
|
53
53
|
locust/test/mock_locustfile.py,sha256=N9sGjW-BmJ-J_x-5bEOR82VQ0DhR1hki313BHPOWq4g,1273
|
54
54
|
locust/test/mock_logging.py,sha256=dvfXaY2eb0ZHx7Bjn7R69BarnRq9uu0z4HD8hCiRNmU,819
|
55
55
|
locust/test/test_debugging.py,sha256=w5Lx6h101novinKjTJJDg5AqqY28U2Wg1W4hgCk6Sx8,1069
|
56
|
-
locust/test/test_dispatch.py,sha256=
|
56
|
+
locust/test/test_dispatch.py,sha256=IVfoBTErABqpRs9B1_D5IP9BrfSBz9qToLiN03Kt9B4,168304
|
57
57
|
locust/test/test_env.py,sha256=ggyx7ZbS7sZPae2wb6JzrvA0p0H7c9HhcBVJn7u1HTw,8956
|
58
|
-
locust/test/test_fasthttp.py,sha256
|
58
|
+
locust/test/test_fasthttp.py,sha256=AHuuAg0d88w7_QUjoNf3ZSHz38WYf5rY95_eEFZ0vH8,30775
|
59
59
|
locust/test/test_http.py,sha256=R23BWBNLjU3OOWCAgIAW8F9H5kqtBx43gPaXC-hhM2g,12570
|
60
60
|
locust/test/test_interruptable_task.py,sha256=HqStHxtdZPT7WtytBiqTpKeNPg9upXzV7UI4QgFdUoU,1408
|
61
61
|
locust/test/test_load_locustfile.py,sha256=v-muHoM-CYu8t7DXm4AQtFP2q8RYfnTTUBqj7uVqhig,8494
|
@@ -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.
|
99
|
-
locust-2.
|
100
|
-
locust-2.
|
101
|
-
locust-2.
|
102
|
-
locust-2.
|
103
|
-
locust-2.
|
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,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|