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 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.24.2.dev24'
16
- __version_tuple__ = version_tuple = (2, 24, 2, 'dev24')
15
+ __version__ = version = '2.25.1.dev8'
16
+ __version_tuple__ = version_tuple = (2, 25, 1, 'dev8')
@@ -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 = 5
310
- """Parameter passed to FastHttpSession. Default 5, meaning 4 redirects."""
309
+ max_redirects: int = 30
310
+ """Parameter passed to FastHttpSession."""
311
311
 
312
- max_retries: int = 1
313
- """Parameter passed to FastHttpSession. Default 1, meaning zero retries."""
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
- # Normalize the weights so that the smallest weight will be equal to "target_min_weight".
370
- # The value "2" was experimentally determined because it gave a better distribution especially
371
- # when dealing with weights which are close to each others, e.g. 1.5, 2, 2.4, etc.
372
- target_min_weight = 2
373
-
374
- # 'Value' here means weight or fixed count
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
- round(target_min_weight * value / min(u[1] for u in users)),
412
+ user[0].__name__,
413
+ normalized_weight // greatest_common_divisor,
379
414
  )
380
- for user, value in users
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
@@ -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):
@@ -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 = 1 # max_redirects and max_retries are funny names, because they are actually max attempts
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.24.2.dev24
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.8
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.0.11
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
  [![PyPI](https://img.shields.io/pypi/v/locust.svg)](https://pypi.org/project/locust/)
48
- [![PyPI](https://img.shields.io/pypi/pyversions/locust.svg)](https://pypi.org/project/locust/)
47
+ ![Python Version from PEP 621 TOML](https://img.shields.io/python/required-version-toml?tomlFilePath=https%3A%2F%2Fraw.githubusercontent.com%2Flocustio%2Flocust%2Fmaster%2Fpyproject.toml&link=https%3A%2F%2Fpypi.org%2Fproject%2Flocust)
49
48
  [![Downloads](https://pepy.tech/badge/locust/week)](https://pepy.tech/project/locust)
50
49
  [![Build Status](https://github.com/locustio/locust/workflows/Tests/badge.svg)](https://github.com/locustio/locust/actions?query=workflow%3ATests)
51
50
  [![GitHub contributors](https://img.shields.io/github/contributors/locustio/locust.svg)](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=uqavFiqhmqv2Ybu1NxtHHdlstTyeofzNtIt8FDc8tVc,428
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=mn-xVqjLUzRtN91hEqWE2VnVvieQNo97fTVSdMwCDV8,18605
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=CcYgLLLJHH_NIE5cuk8dy3YE8ELLSmslhY96rBHzzWQ,26807
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=SdnPFdyW0eRj7Bp4mAI8JRkmcwah6Z_b6oaZ_D98QPE,166009
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=-UyGdz2Po1wOjcSHs2xPqBtMoJWMaaVrqbx6SaQNAac,30864
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.24.2.dev24.dist-info/LICENSE,sha256=78XGpIn3fHVBfaxlPNUfjVufSN7QsdhpJMRJHv2AFpo,1095
99
- locust-2.24.2.dev24.dist-info/METADATA,sha256=Nms4ipJkuKADRuyVj6YM86dkixKPP9VwU9MXfmNkKqE,7212
100
- locust-2.24.2.dev24.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
101
- locust-2.24.2.dev24.dist-info/entry_points.txt,sha256=RAdt8Ku-56m7bFjmdj-MBhbF6h4NX7tVODR9QNnOg0E,44
102
- locust-2.24.2.dev24.dist-info/top_level.txt,sha256=XSsjgPA8Ggf9TqKVbkwSqZFuPlZ085X13M9orDycE20,7
103
- locust-2.24.2.dev24.dist-info/RECORD,,
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,,