locust 2.25.1.dev8__tar.gz → 2.26.0__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.26.0/.pre-commit-config.yaml +10 -0
- {locust-2.25.1.dev8/locust.egg-info → locust-2.26.0}/PKG-INFO +3 -3
- {locust-2.25.1.dev8 → locust-2.26.0}/README.md +1 -1
- {locust-2.25.1.dev8 → locust-2.26.0}/docs/changelog.rst +6 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/docs/developing-locust.rst +6 -4
- {locust-2.25.1.dev8 → locust-2.26.0}/docs/installation.rst +1 -1
- {locust-2.25.1.dev8 → locust-2.26.0}/examples/rest.py +5 -7
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/_version.py +2 -2
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/argument_parser.py +2 -3
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/clients.py +1 -1
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/contrib/fasthttp.py +3 -3
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/dispatch.py +3 -18
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/event.py +2 -1
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/html.py +1 -2
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/input_events.py +1 -2
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/main.py +8 -25
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/runners.py +1 -3
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/stats.py +5 -6
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/test/mock_logging.py +2 -3
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/test/test_debugging.py +1 -2
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/test/test_dispatch.py +7 -33
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/test/test_env.py +3 -3
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/test/test_fasthttp.py +9 -9
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/test/test_http.py +7 -7
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/test/test_interruptable_task.py +1 -2
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/test/test_locust_class.py +4 -4
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/test/test_main.py +7 -8
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/test/test_parser.py +9 -8
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/test/test_runners.py +34 -26
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/test/test_web.py +2 -6
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/test/testcases.py +2 -4
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/user/task.py +1 -2
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/web.py +1 -2
- {locust-2.25.1.dev8 → locust-2.26.0/locust.egg-info}/PKG-INFO +3 -3
- {locust-2.25.1.dev8 → locust-2.26.0}/locust.egg-info/SOURCES.txt +1 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust.egg-info/requires.txt +1 -1
- {locust-2.25.1.dev8 → locust-2.26.0}/pyproject.toml +2 -3
- {locust-2.25.1.dev8 → locust-2.26.0}/.coveragerc +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/.dockerignore +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/.git-blame-ignore-revs +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/.gitattributes +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/.github/CONTRIBUTING.md +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/.github/ISSUE_TEMPLATE/bug.yml +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/.github/workflows/stale.yml +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/.github/workflows/tests.yml +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/.gitignore +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/.readthedocs.yaml +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/.vscode/extensions.json +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/.vscode/launch.json +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/.vscode/launch_locust.json +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/.vscode/settings.json +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/CHANGELOG.md +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/Dockerfile +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/LICENSE +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/MANIFEST.in +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/Makefile +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/README +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/SECURITY.md +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/Vagrantfile +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/benchmarks/dispatch.py +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/docs/_static/theme-overrides.css +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/docs/api.rst +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/docs/conf.py +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/docs/configuration.rst +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/docs/custom-load-shape.rst +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/docs/extending-locust.rst +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/docs/further-reading.rst +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/docs/history.rst +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/docs/images/extend_modern_web_ui_cache_stats.png +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/docs/images/locust_workers.png +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/docs/images/number_of_users.png +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/docs/images/response_times.png +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/docs/images/total_requests_per_second.png +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/docs/images/userclass_picker_example.png +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/docs/images/webui-running-statistics.png +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/docs/images/webui-splash-screenshot.png +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/docs/increase-performance.rst +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/docs/index.rst +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/docs/logging.rst +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/docs/quickstart.rst +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/docs/requirements.txt +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/docs/retrieving-stats.rst +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/docs/running-cloud-integration.rst +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/docs/running-distributed.rst +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/docs/running-in-debugger.rst +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/docs/running-in-docker.rst +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/docs/running-without-web-ui.rst +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/docs/tasksets.rst +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/docs/testing-other-systems.rst +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/docs/use-as-lib.rst +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/docs/what-is-locust.rst +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/docs/writing-a-locustfile.rst +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/examples/add_command_line_argument.py +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/examples/basic.py +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/examples/browse_docs_sequence_test.py +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/examples/browse_docs_test.py +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/examples/custom_messages.py +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/examples/custom_shape/double_wave.py +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/examples/custom_shape/stages.py +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/examples/custom_shape/staging_user_classes.py +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/examples/custom_shape/step_load.py +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/examples/custom_shape/wait_user_count.py +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/examples/custom_wait_function.py +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/examples/custom_xmlrpc_client/server.py +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/examples/custom_xmlrpc_client/xmlrpc_locustfile.py +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/examples/debugging.py +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/examples/debugging_advanced.py +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/examples/docker-compose/docker-compose.yml +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/examples/dynamic_user_credentials.py +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/examples/events.py +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/examples/extend_modern_web_ui.py +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/examples/extend_web_ui/extend.py +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/examples/extend_web_ui/static/custom-stats-table.css +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/examples/extend_web_ui/static/extend.js +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/examples/extend_web_ui/templates/extend.html +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/examples/fast_http_locust.py +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/examples/grpc/grpc_user.py +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/examples/grpc/hello.proto +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/examples/grpc/hello_pb2.py +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/examples/grpc/hello_pb2_grpc.py +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/examples/grpc/hello_server.py +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/examples/grpc/locustfile.py +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/examples/locustfile.py +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/examples/manual_stats_reporting.py +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/examples/multiple_hosts.py +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/examples/nested_inline_tasksets.py +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/examples/sdk_session_patching/session_patch_locustfile.py +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/examples/semaphore_wait.py +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/examples/stop_on_threshold.py +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/examples/terraform/aws/README.md +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/examples/terraform/aws/data_subnet.tf +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/examples/terraform/aws/main.tf +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/examples/terraform/aws/output.tf +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/examples/terraform/aws/plan/basic.py +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/examples/terraform/aws/provisioner.tf +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/examples/terraform/aws/variables.tf +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/examples/test_data_management.py +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/examples/use_as_lib.py +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/examples/vagrant/README.md +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/examples/vagrant/supervisord.conf +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/examples/web_ui_auth.py +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/examples/web_ui_cache_stats.py +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/examples/worker_index.py +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/generate_changelog.py +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/__init__.py +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/__main__.py +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/contrib/__init__.py +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/debug.py +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/env.py +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/exception.py +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/log.py +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/py.typed +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/rpc/__init__.py +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/rpc/protocol.py +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/rpc/zmqrpc.py +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/shape.py +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/static/chart.js +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/static/css/application.css +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/static/css/application.css.map +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/static/css/tables.css +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/static/css/tables.css.map +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/static/echarts.common.min.js +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/static/img/favicon.ico +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/static/img/logo.png +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/static/img/ui-screenshot-charts.png +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/static/img/ui-screenshot-start-test.png +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/static/img/ui-screenshot-stats.png +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/static/img/ui-screenshot-workers.png +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/static/jquery-1.11.3.min.js +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/static/jquery.jqote2.min.js +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/static/jquery.tools.min.js +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/static/locust.js +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/static/sass/_base.sass +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/static/sass/_mixins.sass +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/static/sass/application.sass +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/static/sass/tables.sass +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/static/tasks.js +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/static/vintage.js +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/templates/index.html +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/templates/report.html +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/templates/stats_data.html +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/test/__init__.py +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/test/fake_module1_for_env_test.py +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/test/fake_module2_for_env_test.py +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/test/mock_locustfile.py +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/test/test_load_locustfile.py +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/test/test_log.py +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/test/test_old_wait_api.py +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/test/test_sequential_taskset.py +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/test/test_stats.py +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/test/test_tags.py +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/test/test_taskratio.py +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/test/test_users.py +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/test/test_util.py +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/test/test_wait_time.py +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/test/test_zmqrpc.py +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/test/util.py +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/user/__init__.py +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/user/inspectuser.py +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/user/sequential_taskset.py +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/user/users.py +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/user/wait_time.py +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/util/__init__.py +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/util/cache.py +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/util/deprecation.py +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/util/exception_handler.py +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/util/load_locustfile.py +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/util/rounding.py +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/util/timespan.py +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/webui/.eslintrc +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/webui/.gitignore +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/webui/.prettierrc +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/webui/auth.html +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/webui/dev.html +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/webui/dist/assets/favicon.ico +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/webui/dist/assets/index-941b6e82.js +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/webui/dist/assets/logo.png +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/webui/dist/auth.html +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/webui/dist/index.html +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/webui/dist/report.html +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/webui/index.html +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/webui/package.json +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/webui/public/assets/favicon.ico +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/webui/public/assets/logo.png +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/webui/public/report.html +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/webui/src/App.test.tsx +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/webui/src/App.tsx +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/webui/src/components/DataTable/DataTable.test.tsx +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/webui/src/components/DataTable/DataTable.tsx +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/webui/src/components/ExceptionsTable/ExceptionsTable.tsx +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/webui/src/components/FailuresTable/FailuresTable.tsx +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/webui/src/components/FallbackRender/FallbackRender.test.tsx +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/webui/src/components/FallbackRender/FallbackRender.tsx +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/webui/src/components/Form/Form.tsx +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/webui/src/components/Form/Select.tsx +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/webui/src/components/Form/tests/Form.test.tsx +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/webui/src/components/Form/tests/Select.test.tsx +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/webui/src/components/Layout/Footer/About.tsx +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/webui/src/components/Layout/Footer/Footer.tsx +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/webui/src/components/Layout/Layout.tsx +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/webui/src/components/Layout/Navbar/DarkLightToggle.tsx +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/webui/src/components/Layout/Navbar/Navbar.tsx +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/webui/src/components/Layout/Navbar/SwarmMonitor.test.tsx +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/webui/src/components/Layout/Navbar/SwarmMonitor.tsx +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/webui/src/components/LineChart/LineChart.test.tsx +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/webui/src/components/LineChart/LineChart.tsx +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/webui/src/components/LogViewer/LogViewer.tsx +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/webui/src/components/LogViewer/tests/LogViewer.test.tsx +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/webui/src/components/LogViewer/tests/useLogViewer.test.tsx +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/webui/src/components/LogViewer/useLogViewer.ts +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/webui/src/components/Modal/Modal.tsx +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/webui/src/components/Reports/Reports.test.tsx +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/webui/src/components/Reports/Reports.tsx +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/webui/src/components/ResponseTimeTable/ResponseTimeTable.test.tsx +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/webui/src/components/ResponseTimeTable/ResponseTimeTable.tsx +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/webui/src/components/StateButtons/EditButton.tsx +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/webui/src/components/StateButtons/NewTestButton.tsx +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/webui/src/components/StateButtons/ResetButton.tsx +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/webui/src/components/StateButtons/StateButtons.tsx +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/webui/src/components/StateButtons/StopButton.tsx +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/webui/src/components/StateButtons/tests/ResetButton.test.tsx +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/webui/src/components/StateButtons/tests/StateButtons.test.tsx +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/webui/src/components/StateButtons/tests/StopButton.test.tsx +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/webui/src/components/StatsTable/StatsTable.tsx +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/webui/src/components/SwarmCharts/SwarmCharts.tsx +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/webui/src/components/SwarmForm/SwarmCustomParameters.tsx +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/webui/src/components/SwarmForm/SwarmEditForm.tsx +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/webui/src/components/SwarmForm/SwarmForm.tsx +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/webui/src/components/SwarmForm/SwarmUserClassPicker.tsx +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/webui/src/components/SwarmForm/tests/SwarmCustomParameters.test.tsx +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/webui/src/components/SwarmForm/tests/SwarmEditForm.test.tsx +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/webui/src/components/SwarmForm/tests/SwarmForm.test.tsx +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/webui/src/components/SwarmForm/tests/SwarmUserClassPicker.test.tsx +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/webui/src/components/SwarmRatios/SwarmRatios.test.tsx +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/webui/src/components/SwarmRatios/SwarmRatios.tsx +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/webui/src/components/Table/Table.test.tsx +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/webui/src/components/Table/Table.tsx +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/webui/src/components/Tabs/Tabs.constants.tsx +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/webui/src/components/Tabs/Tabs.test.tsx +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/webui/src/components/Tabs/Tabs.tsx +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/webui/src/components/ViewColumnSelector/ViewColumnSelector.test.tsx +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/webui/src/components/ViewColumnSelector/ViewColumnSelector.tsx +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/webui/src/components/WorkersTable/WorkersTable.tsx +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/webui/src/constants/auth.ts +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/webui/src/constants/swarm.ts +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/webui/src/constants/theme.ts +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/webui/src/global.d.ts +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/webui/src/hooks/tests/useNotifications.test.tsx +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/webui/src/hooks/tests/useSelecteViewColumns.test.tsx +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/webui/src/hooks/tests/useSortByField.test.tsx +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/webui/src/hooks/tests/useSwarmUi.test.tsx +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/webui/src/hooks/useInterval.ts +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/webui/src/hooks/useNotifications.ts +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/webui/src/hooks/useSelectViewColumns.ts +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/webui/src/hooks/useSortByField.ts +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/webui/src/hooks/useSwarmUi.ts +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/webui/src/index.tsx +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/webui/src/pages/Auth.tsx +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/webui/src/pages/Dashboard.tsx +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/webui/src/pages/HtmlReport.tsx +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/webui/src/pages/tests/Auth.test.tsx +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/webui/src/pages/tests/Dashboard.test.tsx +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/webui/src/pages/tests/HtmlReport.test.tsx +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/webui/src/redux/api/swarm.ts +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/webui/src/redux/hooks.ts +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/webui/src/redux/slice/logViewer.slice.ts +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/webui/src/redux/slice/notification.slice.ts +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/webui/src/redux/slice/root.slice.ts +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/webui/src/redux/slice/swarm.slice.ts +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/webui/src/redux/slice/tests/ui.slice.test.ts +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/webui/src/redux/slice/theme.slice.ts +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/webui/src/redux/slice/ui.slice.ts +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/webui/src/redux/slice/url.slice.ts +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/webui/src/redux/store.ts +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/webui/src/redux/utils.ts +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/webui/src/styles/theme.ts +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/webui/src/test/constants.ts +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/webui/src/test/mocks/statsRequest.mock.ts +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/webui/src/test/mocks/swarmState.mock.ts +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/webui/src/test/setup.ts +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/webui/src/test/testUtils.tsx +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/webui/src/types/auth.types.ts +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/webui/src/types/swarm.types.ts +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/webui/src/types/tab.types.ts +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/webui/src/types/table.types.ts +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/webui/src/types/ui.types.ts +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/webui/src/utils/number.ts +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/webui/src/utils/object.ts +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/webui/src/utils/string.ts +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/webui/src/utils/tests/number.test.ts +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/webui/src/utils/tests/object.test.ts +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/webui/src/utils/tests/string.test.ts +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/webui/src/utils/tests/url.test.ts +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/webui/src/utils/url.ts +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/webui/tsconfig.json +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/webui/vite.config.ts +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/webui/vitest.config.ts +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust/webui/yarn.lock +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust.egg-info/dependency_links.txt +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust.egg-info/entry_points.txt +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust.egg-info/not-zip-safe +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/locust.egg-info/top_level.txt +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/package.json +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/scripts/locustfile.py +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/scripts/run-disributed-headless.sh +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/scripts/run-disributed-web.sh +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/scripts/run-local-headless.sh +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/scripts/run-local-web.sh +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/setup.cfg +0 -0
- {locust-2.25.1.dev8 → locust-2.26.0}/tox.ini +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: locust
|
3
|
-
Version: 2.
|
3
|
+
Version: 2.26.0
|
4
4
|
Summary: Developer friendly load testing framework
|
5
5
|
License: MIT
|
6
6
|
Project-URL: Homepage, https://github.com/locustio/locust
|
@@ -32,7 +32,7 @@ Requires-Dist: Werkzeug>=2.0.0
|
|
32
32
|
Requires-Dist: requests>=2.26.0
|
33
33
|
Requires-Dist: msgpack>=1.0.0
|
34
34
|
Requires-Dist: pyzmq>=25.0.0
|
35
|
-
Requires-Dist: geventhttpclient
|
35
|
+
Requires-Dist: geventhttpclient==2.2.1
|
36
36
|
Requires-Dist: ConfigArgParse>=1.5.5
|
37
37
|
Requires-Dist: tomli>=1.1.0; python_version < "3.11"
|
38
38
|
Requires-Dist: psutil>=5.9.1
|
@@ -44,7 +44,7 @@ Requires-Dist: pywin32; platform_system == "Windows"
|
|
44
44
|
# Locust
|
45
45
|
|
46
46
|
[](https://pypi.org/project/locust/)
|
47
|
-

|
48
48
|
[](https://pepy.tech/project/locust)
|
49
49
|
[](https://github.com/locustio/locust/actions?query=workflow%3ATests)
|
50
50
|
[](https://github.com/locustio/locust/graphs/contributors)
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# Locust
|
2
2
|
|
3
3
|
[](https://pypi.org/project/locust/)
|
4
|
-

|
5
5
|
[](https://pepy.tech/project/locust)
|
6
6
|
[](https://github.com/locustio/locust/actions?query=workflow%3ATests)
|
7
7
|
[](https://github.com/locustio/locust/graphs/contributors)
|
@@ -4,6 +4,12 @@ Changelog Highlights
|
|
4
4
|
|
5
5
|
For full details of the Locust changelog, please see https://github.com/locustio/locust/blob/master/CHANGELOG.md
|
6
6
|
|
7
|
+
2.26.0
|
8
|
+
======
|
9
|
+
* Drop support for Python 3.8
|
10
|
+
* Update geventhttpclient and adjust FastHttpUser max_retries / max_redirects (https://github.com/locustio/locust/pull/2676)
|
11
|
+
* Pin gevenhttpclient version (https://github.com/locustio/locust/pull/2682)
|
12
|
+
|
7
13
|
2.25.0
|
8
14
|
======
|
9
15
|
* Add functionality to run listener functions for `custom_messages` concurrently (https://github.com/locustio/locust/pull/2650)
|
@@ -20,7 +20,9 @@ Now the ``locust`` command will run *your* code with no need for reinstalling af
|
|
20
20
|
|
21
21
|
To contribute your changes, push to a branch in your repo and then `open a PR on github <https://github.com/locustio/locust/compare>`_.
|
22
22
|
|
23
|
-
|
23
|
+
If you install `pre-commit <https://pre-commit.com/>`_, linting and format checks/fixes will be automatically performed before each commit.
|
24
|
+
|
25
|
+
Before you open a pull request, make sure all the tests work. And if you are adding a feature, make sure it is documented (in ``docs/*.rst``).
|
24
26
|
|
25
27
|
Testing your changes
|
26
28
|
====================
|
@@ -32,10 +34,10 @@ We use `tox <https://tox.readthedocs.io/en/stable/>`_ to automate tests across m
|
|
32
34
|
$ pip3 install tox
|
33
35
|
$ tox
|
34
36
|
...
|
35
|
-
|
36
|
-
|
37
|
+
py39: install_deps> python -I -m pip install cryptography mock pyquery retry
|
38
|
+
py39: commands[0]> python3 -m pip install .
|
37
39
|
...
|
38
|
-
|
40
|
+
py39: commands[1]> python3 -m unittest discover
|
39
41
|
...
|
40
42
|
|
41
43
|
To only run a specific suite or specific test you can call `pytest <https://docs.pytest.org/>`_ directly:
|
@@ -3,7 +3,7 @@
|
|
3
3
|
Installation
|
4
4
|
============
|
5
5
|
|
6
|
-
0. `Install Python <https://docs.python-guide.org/starting/installation/>`_ (3.
|
6
|
+
0. `Install Python <https://docs.python-guide.org/starting/installation/>`_ (3.9 or later)
|
7
7
|
|
8
8
|
1. Install the package (check `the wiki <https://github.com/locustio/locust/wiki/Installation>`_ if the installation fails)
|
9
9
|
|
@@ -2,8 +2,8 @@ from locust import FastHttpUser, run_single_user, task
|
|
2
2
|
from locust.contrib.fasthttp import RestResponseContextManager
|
3
3
|
from locust.user.wait_time import constant
|
4
4
|
|
5
|
+
from collections.abc import Generator
|
5
6
|
from contextlib import contextmanager
|
6
|
-
from typing import Generator
|
7
7
|
|
8
8
|
|
9
9
|
class MyUser(FastHttpUser):
|
@@ -40,12 +40,10 @@ class MyUser(FastHttpUser):
|
|
40
40
|
# use a trailing comma to append the response text to the custom message
|
41
41
|
assert resp.js["data"]["foo"] == 2, "my custom error message with response text,"
|
42
42
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
# assert (foo := resp.js["foo"])
|
48
|
-
# print(f"the number {foo} is awesome")
|
43
|
+
with self.rest("", "/post", json={"foo": 1}) as resp:
|
44
|
+
# assign and assert in one line
|
45
|
+
assert (foo := resp.js["foo"])
|
46
|
+
print(f"the number {foo} is awesome")
|
49
47
|
|
50
48
|
# rest() catches most exceptions, so any programming mistakes you make automatically marks the request as a failure
|
51
49
|
# and stores the callstack in the failure message
|
@@ -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.26.0'
|
16
|
+
__version_tuple__ = version_tuple = (2, 26, 0)
|
@@ -80,8 +80,7 @@ class LocustTomlConfigParser(configargparse.TomlConfigParser):
|
|
80
80
|
result = OrderedDict()
|
81
81
|
|
82
82
|
for section in self.sections:
|
83
|
-
data
|
84
|
-
if data:
|
83
|
+
if data := configargparse.get_toml_section(config, section):
|
85
84
|
for key, value in data.items():
|
86
85
|
if isinstance(value, list):
|
87
86
|
result[key] = value
|
@@ -667,7 +666,7 @@ Typically ONLY these options (and --locustfile) need to be specified on workers,
|
|
667
666
|
nargs="*",
|
668
667
|
metavar="<tag>",
|
669
668
|
env_var="LOCUST_TAGS",
|
670
|
-
help="List of tags to include in the test, so only tasks with
|
669
|
+
help="List of tags to include in the test, so only tasks with at least one matching tag will be executed",
|
671
670
|
)
|
672
671
|
tag_group.add_argument(
|
673
672
|
"-E",
|
@@ -12,11 +12,12 @@ import socket
|
|
12
12
|
import time
|
13
13
|
import traceback
|
14
14
|
from base64 import b64encode
|
15
|
+
from collections.abc import Generator
|
15
16
|
from contextlib import contextmanager
|
16
17
|
from http.cookiejar import CookieJar
|
17
18
|
from json.decoder import JSONDecodeError
|
18
19
|
from ssl import SSLError
|
19
|
-
from typing import Any, Callable,
|
20
|
+
from typing import Any, Callable, cast
|
20
21
|
from urllib.parse import urlparse, urlunparse
|
21
22
|
|
22
23
|
import gevent
|
@@ -404,8 +405,7 @@ class FastHttpUser(User):
|
|
404
405
|
except Exception as e:
|
405
406
|
error_lines = []
|
406
407
|
for l in traceback.format_exc().split("\n"):
|
407
|
-
m
|
408
|
-
if m:
|
408
|
+
if m := self._callstack_regex.match(l):
|
409
409
|
filename = re.sub(r"/(home|Users/\w*)/", "~/", m.group(1))
|
410
410
|
error_lines.append(filename + ":" + m.group(2) + m.group(3))
|
411
411
|
short_resp = resp.text[:200] if resp.text else resp.text
|
@@ -1,14 +1,13 @@
|
|
1
1
|
from __future__ import annotations
|
2
2
|
|
3
3
|
import contextlib
|
4
|
-
import functools
|
5
4
|
import itertools
|
6
5
|
import math
|
7
|
-
import sys
|
8
6
|
import time
|
9
7
|
from collections import defaultdict
|
8
|
+
from collections.abc import Generator, Iterator
|
10
9
|
from operator import attrgetter
|
11
|
-
from typing import TYPE_CHECKING
|
10
|
+
from typing import TYPE_CHECKING
|
12
11
|
|
13
12
|
import gevent
|
14
13
|
from roundrobin import smooth
|
@@ -18,20 +17,6 @@ if TYPE_CHECKING:
|
|
18
17
|
from locust.runners import WorkerNode
|
19
18
|
|
20
19
|
|
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
|
-
|
35
20
|
# To profile line-by-line, uncomment the code below (i.e. `import line_profiler ...`) and
|
36
21
|
# place `@profile` on the functions/methods you wish to profile. Then, in the unit test you are
|
37
22
|
# running, use `from locust.dispatch import profile; profile.print_stats()` at the end of the unit test.
|
@@ -406,7 +391,7 @@ class UsersDispatcher(Iterator):
|
|
406
391
|
max_order_of_magnitude = _get_order_of_magnitude(min(abs(u[1]) for u in users))
|
407
392
|
weights = tuple(int(u[1] * max_order_of_magnitude) for u in users)
|
408
393
|
|
409
|
-
greatest_common_divisor =
|
394
|
+
greatest_common_divisor = math.gcd(*weights)
|
410
395
|
normalized_values = [
|
411
396
|
(
|
412
397
|
user[0].__name__,
|
@@ -3,8 +3,9 @@ from __future__ import annotations
|
|
3
3
|
import logging
|
4
4
|
import time
|
5
5
|
import traceback
|
6
|
+
from collections.abc import Generator
|
6
7
|
from contextlib import contextmanager
|
7
|
-
from typing import Any
|
8
|
+
from typing import Any
|
8
9
|
|
9
10
|
from . import log
|
10
11
|
from .exception import InterruptTaskSet, RescheduleTask, RescheduleTaskImmediately, StopUser
|
@@ -41,8 +41,7 @@ def get_html_report(
|
|
41
41
|
start_ts = stats.start_time
|
42
42
|
start_time = datetime.datetime.utcfromtimestamp(start_ts).strftime("%Y-%m-%d %H:%M:%S")
|
43
43
|
|
44
|
-
end_ts
|
45
|
-
if end_ts:
|
44
|
+
if end_ts := stats.last_request_timestamp:
|
46
45
|
end_time = datetime.datetime.utcfromtimestamp(end_ts).strftime("%Y-%m-%d %H:%M:%S")
|
47
46
|
else:
|
48
47
|
end_time = start_time
|
@@ -216,8 +216,7 @@ def main():
|
|
216
216
|
gc.collect() # avoid freezing garbage
|
217
217
|
gc.freeze() # move all objects to perm gen so ref counts dont get updated
|
218
218
|
for _ in range(options.processes):
|
219
|
-
child_pid
|
220
|
-
if child_pid:
|
219
|
+
if child_pid := gevent.fork():
|
221
220
|
children.append(child_pid)
|
222
221
|
logging.debug(f"Started child worker with pid #{child_pid}")
|
223
222
|
else:
|
@@ -250,12 +249,8 @@ def main():
|
|
250
249
|
# nothing more to do, just wait for the children to exit
|
251
250
|
for child_pid in children:
|
252
251
|
_, child_status = os.waitpid(child_pid, 0)
|
253
|
-
|
254
|
-
|
255
|
-
child_exit_code = os.waitstatus_to_exitcode(child_status)
|
256
|
-
exit_code = max(exit_code, child_exit_code)
|
257
|
-
except AttributeError:
|
258
|
-
pass # dammit python 3.8...
|
252
|
+
child_exit_code = os.waitstatus_to_exitcode(child_status)
|
253
|
+
exit_code = max(exit_code, child_exit_code)
|
259
254
|
sys.exit(exit_code)
|
260
255
|
else:
|
261
256
|
options.master = True
|
@@ -270,12 +265,8 @@ def main():
|
|
270
265
|
try:
|
271
266
|
_, child_status = os.waitpid(child_pid, os.WNOHANG)
|
272
267
|
children.remove(child_pid)
|
273
|
-
|
274
|
-
|
275
|
-
child_exit_code = os.waitstatus_to_exitcode(child_status)
|
276
|
-
exit_code = max(exit_code, child_exit_code)
|
277
|
-
except AttributeError:
|
278
|
-
pass # dammit python 3.8...
|
268
|
+
child_exit_code = os.waitstatus_to_exitcode(child_status)
|
269
|
+
exit_code = max(exit_code, child_exit_code)
|
279
270
|
except OSError as e:
|
280
271
|
if e.errno == errno.EINTR:
|
281
272
|
time.sleep(0.1)
|
@@ -291,12 +282,8 @@ def main():
|
|
291
282
|
pass # never mind, process was already dead
|
292
283
|
for child_pid in children:
|
293
284
|
_, child_status = os.waitpid(child_pid, 0)
|
294
|
-
|
295
|
-
|
296
|
-
child_exit_code = os.waitstatus_to_exitcode(child_status)
|
297
|
-
exit_code = max(exit_code, child_exit_code)
|
298
|
-
except AttributeError:
|
299
|
-
pass # dammit python 3.8...
|
285
|
+
child_exit_code = os.waitstatus_to_exitcode(child_status)
|
286
|
+
exit_code = max(exit_code, child_exit_code)
|
300
287
|
if exit_code > 1:
|
301
288
|
logging.error(f"Bad response code from worker children: {exit_code}")
|
302
289
|
# ensure master doesnt finish until output from workers has arrived
|
@@ -327,8 +314,7 @@ def main():
|
|
327
314
|
|
328
315
|
# make sure specified User exists
|
329
316
|
if options.user_classes:
|
330
|
-
missing
|
331
|
-
if missing:
|
317
|
+
if missing := set(options.user_classes) - set(user_classes.keys()):
|
332
318
|
logger.error(f"Unknown User(s): {', '.join(missing)}\n")
|
333
319
|
sys.exit(1)
|
334
320
|
else:
|
@@ -356,9 +342,6 @@ It's not high enough for load testing, and the OS didn't allow locust to increas
|
|
356
342
|
See https://github.com/locustio/locust/wiki/Installation#increasing-maximum-number-of-open-files-limit for more info."""
|
357
343
|
)
|
358
344
|
|
359
|
-
if sys.version_info < (3, 9):
|
360
|
-
logger.warning("Python 3.8 support is deprecated and will be removed soon")
|
361
|
-
|
362
345
|
# create locust Environment
|
363
346
|
locustfile_path = None if not locustfile else os.path.basename(locustfile)
|
364
347
|
|
@@ -14,7 +14,7 @@ import time
|
|
14
14
|
import traceback
|
15
15
|
from abc import abstractmethod
|
16
16
|
from collections import defaultdict
|
17
|
-
from collections.abc import MutableMapping
|
17
|
+
from collections.abc import Iterator, MutableMapping, ValuesView
|
18
18
|
from operator import (
|
19
19
|
itemgetter,
|
20
20
|
methodcaller,
|
@@ -24,10 +24,8 @@ from typing import (
|
|
24
24
|
TYPE_CHECKING,
|
25
25
|
Any,
|
26
26
|
Callable,
|
27
|
-
Iterator,
|
28
27
|
NoReturn,
|
29
28
|
TypedDict,
|
30
|
-
ValuesView,
|
31
29
|
cast,
|
32
30
|
)
|
33
31
|
from uuid import uuid4
|
@@ -10,6 +10,10 @@ import signal
|
|
10
10
|
import time
|
11
11
|
from abc import abstractmethod
|
12
12
|
from collections import OrderedDict, defaultdict, namedtuple
|
13
|
+
from collections import (
|
14
|
+
OrderedDict as OrderedDictType,
|
15
|
+
)
|
16
|
+
from collections.abc import Iterable
|
13
17
|
from copy import copy
|
14
18
|
from html import escape
|
15
19
|
from itertools import chain
|
@@ -19,16 +23,12 @@ from typing import (
|
|
19
23
|
TYPE_CHECKING,
|
20
24
|
Any,
|
21
25
|
Callable,
|
22
|
-
Iterable,
|
23
26
|
NoReturn,
|
24
27
|
Protocol,
|
25
28
|
TypedDict,
|
26
29
|
TypeVar,
|
27
30
|
cast,
|
28
31
|
)
|
29
|
-
from typing import (
|
30
|
-
OrderedDict as OrderedDictType,
|
31
|
-
)
|
32
32
|
|
33
33
|
import gevent
|
34
34
|
|
@@ -177,8 +177,7 @@ def diff_response_time_dicts(latest: dict[int, int], old: dict[int, int]) -> dic
|
|
177
177
|
"""
|
178
178
|
new = {}
|
179
179
|
for t in latest:
|
180
|
-
diff
|
181
|
-
if diff:
|
180
|
+
if diff := latest[t] - old.get(t, 0):
|
182
181
|
new[t] = diff
|
183
182
|
return new
|
184
183
|
|
@@ -1,11 +1,10 @@
|
|
1
1
|
from __future__ import annotations
|
2
2
|
|
3
3
|
import logging
|
4
|
-
|
5
|
-
from typing import List, Union, Dict
|
6
4
|
from types import TracebackType
|
5
|
+
from typing import Union
|
7
6
|
|
8
|
-
LogMessage =
|
7
|
+
LogMessage = list[Union[str, dict[str, TracebackType]]]
|
9
8
|
|
10
9
|
|
11
10
|
class MockedLoggingHandler(logging.Handler):
|
@@ -27,8 +27,7 @@ class TestDebugging(DebugTestCase):
|
|
27
27
|
pass
|
28
28
|
|
29
29
|
def _stop_user():
|
30
|
-
user
|
31
|
-
if user:
|
30
|
+
if user := getattr(debug._env, "single_user_instance", None):
|
32
31
|
user._state = LOCUST_STATE_STOPPING
|
33
32
|
|
34
33
|
t = Timer(1, _stop_user)
|
@@ -2167,9 +2167,7 @@ class TestLargeScale(unittest.TestCase):
|
|
2167
2167
|
dispatch_iteration_duration <= tol
|
2168
2168
|
for dispatch_iteration_duration in users_dispatcher.dispatch_iteration_durations
|
2169
2169
|
),
|
2170
|
-
"One or more dispatch took more than {:.0f}s to compute (max = {}ms)"
|
2171
|
-
tol * 1000, 1000 * max(users_dispatcher.dispatch_iteration_durations)
|
2172
|
-
),
|
2170
|
+
f"One or more dispatch took more than {tol * 1000:.0f}s to compute (max = {1000 * max(users_dispatcher.dispatch_iteration_durations)}ms)",
|
2173
2171
|
)
|
2174
2172
|
|
2175
2173
|
self.assertEqual(_user_count(all_dispatched_users[-1]), target_user_count)
|
@@ -2181,9 +2179,7 @@ class TestLargeScale(unittest.TestCase):
|
|
2181
2179
|
self.assertLessEqual(
|
2182
2180
|
max(user_count_on_workers) - min(user_count_on_workers),
|
2183
2181
|
1,
|
2184
|
-
"One or more workers have too much users compared to the other workers when user count is {}"
|
2185
|
-
_user_count(dispatch_users)
|
2186
|
-
),
|
2182
|
+
f"One or more workers have too much users compared to the other workers when user count is {_user_count(dispatch_users)}",
|
2187
2183
|
)
|
2188
2184
|
|
2189
2185
|
for i, dispatch_users in enumerate(all_dispatched_users):
|
@@ -2202,9 +2198,7 @@ class TestLargeScale(unittest.TestCase):
|
|
2202
2198
|
self.assertLessEqual(
|
2203
2199
|
error_percent,
|
2204
2200
|
tol,
|
2205
|
-
"Distribution for user class {} is off by more than {}% when user count is {}"
|
2206
|
-
user_class, tol, _user_count(dispatch_users)
|
2207
|
-
),
|
2201
|
+
f"Distribution for user class {user_class} is off by more than {tol}% when user count is {_user_count(dispatch_users)}",
|
2208
2202
|
)
|
2209
2203
|
|
2210
2204
|
def test_ramp_down_from_100_000_to_0_users_with_50_user_classes_and_1000_workers_and_5000_spawn_rate(self):
|
@@ -2236,9 +2230,7 @@ class TestLargeScale(unittest.TestCase):
|
|
2236
2230
|
dispatch_iteration_duration <= tol
|
2237
2231
|
for dispatch_iteration_duration in users_dispatcher.dispatch_iteration_durations
|
2238
2232
|
),
|
2239
|
-
"One or more dispatch took more than {:.0f}ms to compute (max = {}ms)"
|
2240
|
-
tol * 1000, 1000 * max(users_dispatcher.dispatch_iteration_durations)
|
2241
|
-
),
|
2233
|
+
f"One or more dispatch took more than {tol * 1000:.0f}ms to compute (max = {1000 * max(users_dispatcher.dispatch_iteration_durations)}ms)",
|
2242
2234
|
)
|
2243
2235
|
|
2244
2236
|
self.assertEqual(_user_count(all_dispatched_users[-1]), 0)
|
@@ -2250,9 +2242,7 @@ class TestLargeScale(unittest.TestCase):
|
|
2250
2242
|
self.assertLessEqual(
|
2251
2243
|
max(user_count_on_workers) - min(user_count_on_workers),
|
2252
2244
|
1,
|
2253
|
-
"One or more workers have too much users compared to the other workers when user count is {}"
|
2254
|
-
_user_count(dispatch_users)
|
2255
|
-
),
|
2245
|
+
f"One or more workers have too much users compared to the other workers when user count is {_user_count(dispatch_users)}",
|
2256
2246
|
)
|
2257
2247
|
|
2258
2248
|
for dispatch_users in all_dispatched_users[:-1]:
|
@@ -2267,9 +2257,7 @@ class TestLargeScale(unittest.TestCase):
|
|
2267
2257
|
self.assertLessEqual(
|
2268
2258
|
error_percent,
|
2269
2259
|
tol,
|
2270
|
-
"Distribution for user class {} is off by more than {}% when user count is {}"
|
2271
|
-
user_class, tol, _user_count(dispatch_users)
|
2272
|
-
),
|
2260
|
+
f"Distribution for user class {user_class} is off by more than {tol}% when user count is {_user_count(dispatch_users)}",
|
2273
2261
|
)
|
2274
2262
|
|
2275
2263
|
|
@@ -3448,9 +3436,7 @@ class TestRampUpUsersFromZeroWithFixed(unittest.TestCase):
|
|
3448
3436
|
self.target_user_count = target_user_count
|
3449
3437
|
|
3450
3438
|
def __str__(self):
|
3451
|
-
return "<RampUpCase fixed_counts={} weights={} target_user_count={}>"
|
3452
|
-
self.fixed_counts, self.weights, self.target_user_count
|
3453
|
-
)
|
3439
|
+
return f"<RampUpCase fixed_counts={self.fixed_counts} weights={self.weights} target_user_count={self.target_user_count}>"
|
3454
3440
|
|
3455
3441
|
def case_handler(self, cases: list[RampUpCase], expected: list[dict[str, int]], user_classes: list[type[User]]):
|
3456
3442
|
self.assertEqual(len(cases), len(expected))
|
@@ -3734,8 +3720,6 @@ class TestRampUpDifferentUsers(unittest.TestCase):
|
|
3734
3720
|
|
3735
3721
|
worker_node1 = WorkerNode("1")
|
3736
3722
|
|
3737
|
-
sleep_time = 0.2
|
3738
|
-
|
3739
3723
|
user_dispatcher = UsersDispatcher(worker_nodes=[worker_node1], user_classes=[User1, User2, User3])
|
3740
3724
|
|
3741
3725
|
user_dispatcher.new_dispatch(target_user_count=3, spawn_rate=3)
|
@@ -3761,8 +3745,6 @@ class TestRampUpDifferentUsers(unittest.TestCase):
|
|
3761
3745
|
|
3762
3746
|
worker_node1 = WorkerNode("1")
|
3763
3747
|
|
3764
|
-
sleep_time = 0.2
|
3765
|
-
|
3766
3748
|
user_dispatcher = UsersDispatcher(worker_nodes=[worker_node1], user_classes=[User1, User2, User3])
|
3767
3749
|
|
3768
3750
|
user_dispatcher.new_dispatch(target_user_count=10, spawn_rate=10, user_classes=[User2])
|
@@ -3780,8 +3762,6 @@ class TestRampUpDifferentUsers(unittest.TestCase):
|
|
3780
3762
|
|
3781
3763
|
worker_node1 = WorkerNode("1")
|
3782
3764
|
|
3783
|
-
sleep_time = 0.2
|
3784
|
-
|
3785
3765
|
user_dispatcher = UsersDispatcher(worker_nodes=[worker_node1], user_classes=[User1, User2, User3])
|
3786
3766
|
|
3787
3767
|
user_dispatcher.new_dispatch(target_user_count=10, spawn_rate=10, user_classes=[User2])
|
@@ -3802,8 +3782,6 @@ class TestRampUpDifferentUsers(unittest.TestCase):
|
|
3802
3782
|
|
3803
3783
|
worker_node1 = WorkerNode("1")
|
3804
3784
|
|
3805
|
-
sleep_time = 0.2
|
3806
|
-
|
3807
3785
|
user_dispatcher = UsersDispatcher(worker_nodes=[worker_node1], user_classes=[User1, User2, User3])
|
3808
3786
|
|
3809
3787
|
user_dispatcher.new_dispatch(target_user_count=10, spawn_rate=10, user_classes=[User2])
|
@@ -3826,8 +3804,6 @@ class TestRampUpDifferentUsers(unittest.TestCase):
|
|
3826
3804
|
worker_node2 = WorkerNode("2")
|
3827
3805
|
worker_node3 = WorkerNode("3")
|
3828
3806
|
|
3829
|
-
sleep_time = 0.2
|
3830
|
-
|
3831
3807
|
user_dispatcher = UsersDispatcher(
|
3832
3808
|
worker_nodes=[worker_node1, worker_node2, worker_node3], user_classes=[User1, User2, User3]
|
3833
3809
|
)
|
@@ -3886,8 +3862,6 @@ class TestRampUpDifferentUsers(unittest.TestCase):
|
|
3886
3862
|
worker_node2 = WorkerNode("2")
|
3887
3863
|
worker_node3 = WorkerNode("3")
|
3888
3864
|
|
3889
|
-
sleep_time = 0.2
|
3890
|
-
|
3891
3865
|
user_dispatcher = UsersDispatcher(
|
3892
3866
|
worker_nodes=[worker_node1, worker_node2, worker_node3], user_classes=[User1, User2, User3]
|
3893
3867
|
)
|
@@ -36,7 +36,7 @@ class TestEnvironment(LocustTestCase):
|
|
36
36
|
|
37
37
|
def test_user_classes_with_same_name_is_error(self):
|
38
38
|
with self.assertRaises(ValueError) as e:
|
39
|
-
|
39
|
+
Environment(user_classes=[MyUserWithSameName1, MyUserWithSameName2])
|
40
40
|
|
41
41
|
self.assertEqual(
|
42
42
|
e.exception.args[0],
|
@@ -186,7 +186,7 @@ class TestEnvironment(LocustTestCase):
|
|
186
186
|
pass
|
187
187
|
|
188
188
|
with self.assertRaises(ValueError) as e:
|
189
|
-
|
189
|
+
Environment(user_classes=[MyUser1, MyUser2])
|
190
190
|
|
191
191
|
self.assertEqual(
|
192
192
|
e.exception.args[0],
|
@@ -269,7 +269,7 @@ class TestEnvironment(LocustTestCase):
|
|
269
269
|
available_user_classes={"User1": MyUser1, "User2": MyUser2},
|
270
270
|
available_user_tasks={"User1": MyUser1.tasks, "User2": MyUser2.tasks},
|
271
271
|
)
|
272
|
-
|
272
|
+
worker_env.create_worker_runner("127.0.0.1", master.server.port)
|
273
273
|
|
274
274
|
master_env.update_user_class({"user_class_name": "User1", "host": "http://localhost", "tasks": ["my_task_2"]})
|
275
275
|
|