locust 2.26.1.dev26__tar.gz → 2.26.1.dev48__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.
Files changed (351) hide show
  1. {locust-2.26.1.dev26/locust.egg-info → locust-2.26.1.dev48}/PKG-INFO +1 -1
  2. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/docs/configuration.rst +7 -5
  3. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/_version.py +2 -2
  4. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/argument_parser.py +61 -150
  5. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/runners.py +3 -7
  6. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/test/test_main.py +70 -29
  7. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/test/test_parser.py +35 -57
  8. {locust-2.26.1.dev26 → locust-2.26.1.dev48/locust.egg-info}/PKG-INFO +1 -1
  9. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/.coveragerc +0 -0
  10. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/.dockerignore +0 -0
  11. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/.git-blame-ignore-revs +0 -0
  12. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/.gitattributes +0 -0
  13. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/.github/CONTRIBUTING.md +0 -0
  14. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/.github/ISSUE_TEMPLATE/bug.yml +0 -0
  15. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/.github/ISSUE_TEMPLATE/config.yml +0 -0
  16. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
  17. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/.github/workflows/stale.yml +0 -0
  18. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/.github/workflows/tests.yml +0 -0
  19. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/.gitignore +0 -0
  20. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/.pre-commit-config.yaml +0 -0
  21. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/.readthedocs.yaml +0 -0
  22. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/.vscode/extensions.json +0 -0
  23. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/.vscode/launch.json +0 -0
  24. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/.vscode/launch_locust.json +0 -0
  25. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/.vscode/settings.json +0 -0
  26. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/CHANGELOG.md +0 -0
  27. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/Dockerfile +0 -0
  28. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/LICENSE +0 -0
  29. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/MANIFEST.in +0 -0
  30. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/Makefile +0 -0
  31. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/README +0 -0
  32. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/README.md +0 -0
  33. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/SECURITY.md +0 -0
  34. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/Vagrantfile +0 -0
  35. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/benchmarks/dispatch.py +0 -0
  36. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/docs/_static/theme-overrides.css +0 -0
  37. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/docs/api.rst +0 -0
  38. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/docs/changelog.rst +0 -0
  39. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/docs/conf.py +0 -0
  40. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/docs/custom-load-shape.rst +0 -0
  41. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/docs/developing-locust.rst +0 -0
  42. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/docs/extending-locust.rst +0 -0
  43. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/docs/further-reading.rst +0 -0
  44. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/docs/history.rst +0 -0
  45. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/docs/images/extend_modern_web_ui_cache_stats.png +0 -0
  46. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/docs/images/locust_workers.png +0 -0
  47. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/docs/images/number_of_users.png +0 -0
  48. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/docs/images/response_times.png +0 -0
  49. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/docs/images/total_requests_per_second.png +0 -0
  50. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/docs/images/userclass_picker_example.png +0 -0
  51. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/docs/images/webui-running-statistics.png +0 -0
  52. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/docs/images/webui-splash-screenshot.png +0 -0
  53. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/docs/increase-performance.rst +0 -0
  54. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/docs/index.rst +0 -0
  55. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/docs/installation.rst +0 -0
  56. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/docs/logging.rst +0 -0
  57. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/docs/quickstart.rst +0 -0
  58. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/docs/requirements.txt +0 -0
  59. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/docs/retrieving-stats.rst +0 -0
  60. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/docs/running-distributed.rst +0 -0
  61. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/docs/running-in-debugger.rst +0 -0
  62. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/docs/running-in-docker.rst +0 -0
  63. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/docs/running-without-web-ui.rst +0 -0
  64. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/docs/tasksets.rst +0 -0
  65. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/docs/testing-other-systems.rst +0 -0
  66. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/docs/use-as-lib.rst +0 -0
  67. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/docs/what-is-locust.rst +0 -0
  68. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/docs/writing-a-locustfile.rst +0 -0
  69. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/examples/add_command_line_argument.py +0 -0
  70. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/examples/basic.py +0 -0
  71. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/examples/browse_docs_sequence_test.py +0 -0
  72. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/examples/browse_docs_test.py +0 -0
  73. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/examples/custom_messages.py +0 -0
  74. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/examples/custom_shape/double_wave.py +0 -0
  75. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/examples/custom_shape/stages.py +0 -0
  76. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/examples/custom_shape/staging_user_classes.py +0 -0
  77. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/examples/custom_shape/step_load.py +0 -0
  78. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/examples/custom_shape/wait_user_count.py +0 -0
  79. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/examples/custom_wait_function.py +0 -0
  80. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/examples/custom_xmlrpc_client/server.py +0 -0
  81. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/examples/custom_xmlrpc_client/xmlrpc_locustfile.py +0 -0
  82. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/examples/debugging.py +0 -0
  83. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/examples/debugging_advanced.py +0 -0
  84. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/examples/docker-compose/docker-compose.yml +0 -0
  85. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/examples/dynamic_user_credentials.py +0 -0
  86. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/examples/events.py +0 -0
  87. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/examples/extend_modern_web_ui.py +0 -0
  88. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/examples/extend_web_ui/extend.py +0 -0
  89. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/examples/extend_web_ui/static/custom-stats-table.css +0 -0
  90. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/examples/extend_web_ui/static/extend.js +0 -0
  91. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/examples/extend_web_ui/templates/extend.html +0 -0
  92. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/examples/fast_http_locust.py +0 -0
  93. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/examples/grpc/grpc_user.py +0 -0
  94. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/examples/grpc/hello.proto +0 -0
  95. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/examples/grpc/hello_pb2.py +0 -0
  96. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/examples/grpc/hello_pb2_grpc.py +0 -0
  97. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/examples/grpc/hello_server.py +0 -0
  98. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/examples/grpc/locustfile.py +0 -0
  99. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/examples/locustfile.py +0 -0
  100. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/examples/manual_stats_reporting.py +0 -0
  101. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/examples/multiple_hosts.py +0 -0
  102. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/examples/nested_inline_tasksets.py +0 -0
  103. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/examples/rest.py +0 -0
  104. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/examples/sdk_session_patching/session_patch_locustfile.py +0 -0
  105. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/examples/semaphore_wait.py +0 -0
  106. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/examples/stop_on_threshold.py +0 -0
  107. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/examples/terraform/aws/README.md +0 -0
  108. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/examples/terraform/aws/data_subnet.tf +0 -0
  109. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/examples/terraform/aws/main.tf +0 -0
  110. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/examples/terraform/aws/output.tf +0 -0
  111. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/examples/terraform/aws/plan/basic.py +0 -0
  112. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/examples/terraform/aws/provisioner.tf +0 -0
  113. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/examples/terraform/aws/variables.tf +0 -0
  114. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/examples/test_data_management.py +0 -0
  115. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/examples/use_as_lib.py +0 -0
  116. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/examples/vagrant/README.md +0 -0
  117. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/examples/vagrant/supervisord.conf +0 -0
  118. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/examples/web_ui_auth.py +0 -0
  119. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/examples/web_ui_cache_stats.py +0 -0
  120. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/examples/worker_index.py +0 -0
  121. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/generate_changelog.py +0 -0
  122. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/__init__.py +0 -0
  123. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/__main__.py +0 -0
  124. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/clients.py +0 -0
  125. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/contrib/__init__.py +0 -0
  126. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/contrib/fasthttp.py +0 -0
  127. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/debug.py +0 -0
  128. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/dispatch.py +0 -0
  129. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/env.py +0 -0
  130. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/event.py +0 -0
  131. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/exception.py +0 -0
  132. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/html.py +0 -0
  133. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/input_events.py +0 -0
  134. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/log.py +0 -0
  135. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/main.py +0 -0
  136. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/py.typed +0 -0
  137. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/rpc/__init__.py +0 -0
  138. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/rpc/protocol.py +0 -0
  139. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/rpc/zmqrpc.py +0 -0
  140. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/shape.py +0 -0
  141. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/static/chart.js +0 -0
  142. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/static/css/application.css +0 -0
  143. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/static/css/application.css.map +0 -0
  144. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/static/css/tables.css +0 -0
  145. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/static/css/tables.css.map +0 -0
  146. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/static/echarts.common.min.js +0 -0
  147. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/static/img/favicon.ico +0 -0
  148. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/static/img/logo.png +0 -0
  149. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/static/img/ui-screenshot-charts.png +0 -0
  150. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/static/img/ui-screenshot-start-test.png +0 -0
  151. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/static/img/ui-screenshot-stats.png +0 -0
  152. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/static/img/ui-screenshot-workers.png +0 -0
  153. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/static/jquery-1.11.3.min.js +0 -0
  154. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/static/jquery.jqote2.min.js +0 -0
  155. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/static/jquery.tools.min.js +0 -0
  156. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/static/locust.js +0 -0
  157. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/static/sass/_base.sass +0 -0
  158. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/static/sass/_mixins.sass +0 -0
  159. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/static/sass/application.sass +0 -0
  160. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/static/sass/tables.sass +0 -0
  161. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/static/tasks.js +0 -0
  162. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/static/vintage.js +0 -0
  163. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/stats.py +0 -0
  164. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/templates/index.html +0 -0
  165. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/templates/report.html +0 -0
  166. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/templates/stats_data.html +0 -0
  167. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/test/__init__.py +0 -0
  168. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/test/fake_module1_for_env_test.py +0 -0
  169. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/test/fake_module2_for_env_test.py +0 -0
  170. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/test/mock_locustfile.py +0 -0
  171. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/test/mock_logging.py +0 -0
  172. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/test/test_debugging.py +0 -0
  173. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/test/test_dispatch.py +0 -0
  174. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/test/test_env.py +0 -0
  175. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/test/test_fasthttp.py +0 -0
  176. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/test/test_http.py +0 -0
  177. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/test/test_interruptable_task.py +0 -0
  178. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/test/test_load_locustfile.py +0 -0
  179. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/test/test_locust_class.py +0 -0
  180. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/test/test_log.py +0 -0
  181. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/test/test_old_wait_api.py +0 -0
  182. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/test/test_runners.py +0 -0
  183. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/test/test_sequential_taskset.py +0 -0
  184. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/test/test_stats.py +0 -0
  185. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/test/test_tags.py +0 -0
  186. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/test/test_taskratio.py +0 -0
  187. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/test/test_users.py +0 -0
  188. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/test/test_util.py +0 -0
  189. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/test/test_wait_time.py +0 -0
  190. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/test/test_web.py +0 -0
  191. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/test/test_zmqrpc.py +0 -0
  192. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/test/testcases.py +0 -0
  193. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/test/util.py +0 -0
  194. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/user/__init__.py +0 -0
  195. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/user/inspectuser.py +0 -0
  196. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/user/sequential_taskset.py +0 -0
  197. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/user/task.py +0 -0
  198. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/user/users.py +0 -0
  199. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/user/wait_time.py +0 -0
  200. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/util/__init__.py +0 -0
  201. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/util/cache.py +0 -0
  202. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/util/deprecation.py +0 -0
  203. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/util/exception_handler.py +0 -0
  204. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/util/load_locustfile.py +0 -0
  205. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/util/rounding.py +0 -0
  206. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/util/timespan.py +0 -0
  207. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/web.py +0 -0
  208. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/webui/.eslintrc +0 -0
  209. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/webui/.gitignore +0 -0
  210. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/webui/.prettierrc +0 -0
  211. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/webui/auth.html +0 -0
  212. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/webui/dev.html +0 -0
  213. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/webui/dist/assets/favicon.ico +0 -0
  214. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/webui/dist/assets/index-941b6e82.js +0 -0
  215. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/webui/dist/assets/logo.png +0 -0
  216. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/webui/dist/auth.html +0 -0
  217. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/webui/dist/index.html +0 -0
  218. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/webui/dist/report.html +0 -0
  219. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/webui/index.html +0 -0
  220. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/webui/package.json +0 -0
  221. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/webui/public/assets/favicon.ico +0 -0
  222. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/webui/public/assets/logo.png +0 -0
  223. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/webui/public/report.html +0 -0
  224. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/webui/src/App.test.tsx +0 -0
  225. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/webui/src/App.tsx +0 -0
  226. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/webui/src/components/DataTable/DataTable.test.tsx +0 -0
  227. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/webui/src/components/DataTable/DataTable.tsx +0 -0
  228. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/webui/src/components/ExceptionsTable/ExceptionsTable.tsx +0 -0
  229. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/webui/src/components/FailuresTable/FailuresTable.tsx +0 -0
  230. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/webui/src/components/FallbackRender/FallbackRender.test.tsx +0 -0
  231. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/webui/src/components/FallbackRender/FallbackRender.tsx +0 -0
  232. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/webui/src/components/Form/Form.tsx +0 -0
  233. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/webui/src/components/Form/Select.tsx +0 -0
  234. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/webui/src/components/Form/tests/Form.test.tsx +0 -0
  235. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/webui/src/components/Form/tests/Select.test.tsx +0 -0
  236. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/webui/src/components/Layout/Footer/About.tsx +0 -0
  237. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/webui/src/components/Layout/Footer/Footer.tsx +0 -0
  238. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/webui/src/components/Layout/Layout.tsx +0 -0
  239. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/webui/src/components/Layout/Navbar/DarkLightToggle.tsx +0 -0
  240. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/webui/src/components/Layout/Navbar/Navbar.tsx +0 -0
  241. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/webui/src/components/Layout/Navbar/SwarmMonitor.test.tsx +0 -0
  242. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/webui/src/components/Layout/Navbar/SwarmMonitor.tsx +0 -0
  243. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/webui/src/components/LineChart/LineChart.test.tsx +0 -0
  244. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/webui/src/components/LineChart/LineChart.tsx +0 -0
  245. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/webui/src/components/LogViewer/LogViewer.tsx +0 -0
  246. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/webui/src/components/LogViewer/tests/LogViewer.test.tsx +0 -0
  247. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/webui/src/components/LogViewer/tests/useLogViewer.test.tsx +0 -0
  248. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/webui/src/components/LogViewer/useLogViewer.ts +0 -0
  249. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/webui/src/components/Modal/Modal.tsx +0 -0
  250. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/webui/src/components/Reports/Reports.test.tsx +0 -0
  251. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/webui/src/components/Reports/Reports.tsx +0 -0
  252. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/webui/src/components/ResponseTimeTable/ResponseTimeTable.test.tsx +0 -0
  253. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/webui/src/components/ResponseTimeTable/ResponseTimeTable.tsx +0 -0
  254. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/webui/src/components/StateButtons/EditButton.tsx +0 -0
  255. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/webui/src/components/StateButtons/NewTestButton.tsx +0 -0
  256. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/webui/src/components/StateButtons/ResetButton.tsx +0 -0
  257. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/webui/src/components/StateButtons/StateButtons.tsx +0 -0
  258. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/webui/src/components/StateButtons/StopButton.tsx +0 -0
  259. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/webui/src/components/StateButtons/tests/ResetButton.test.tsx +0 -0
  260. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/webui/src/components/StateButtons/tests/StateButtons.test.tsx +0 -0
  261. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/webui/src/components/StateButtons/tests/StopButton.test.tsx +0 -0
  262. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/webui/src/components/StatsTable/StatsTable.tsx +0 -0
  263. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/webui/src/components/SwarmCharts/SwarmCharts.tsx +0 -0
  264. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/webui/src/components/SwarmForm/SwarmCustomParameters.tsx +0 -0
  265. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/webui/src/components/SwarmForm/SwarmEditForm.tsx +0 -0
  266. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/webui/src/components/SwarmForm/SwarmForm.tsx +0 -0
  267. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/webui/src/components/SwarmForm/SwarmUserClassPicker.tsx +0 -0
  268. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/webui/src/components/SwarmForm/tests/SwarmCustomParameters.test.tsx +0 -0
  269. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/webui/src/components/SwarmForm/tests/SwarmEditForm.test.tsx +0 -0
  270. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/webui/src/components/SwarmForm/tests/SwarmForm.test.tsx +0 -0
  271. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/webui/src/components/SwarmForm/tests/SwarmUserClassPicker.test.tsx +0 -0
  272. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/webui/src/components/SwarmRatios/SwarmRatios.test.tsx +0 -0
  273. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/webui/src/components/SwarmRatios/SwarmRatios.tsx +0 -0
  274. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/webui/src/components/Table/Table.test.tsx +0 -0
  275. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/webui/src/components/Table/Table.tsx +0 -0
  276. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/webui/src/components/Tabs/Tabs.constants.tsx +0 -0
  277. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/webui/src/components/Tabs/Tabs.test.tsx +0 -0
  278. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/webui/src/components/Tabs/Tabs.tsx +0 -0
  279. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/webui/src/components/ViewColumnSelector/ViewColumnSelector.test.tsx +0 -0
  280. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/webui/src/components/ViewColumnSelector/ViewColumnSelector.tsx +0 -0
  281. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/webui/src/components/WorkersTable/WorkersTable.tsx +0 -0
  282. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/webui/src/constants/auth.ts +0 -0
  283. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/webui/src/constants/swarm.ts +0 -0
  284. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/webui/src/constants/theme.ts +0 -0
  285. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/webui/src/global.d.ts +0 -0
  286. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/webui/src/hooks/tests/useNotifications.test.tsx +0 -0
  287. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/webui/src/hooks/tests/useSelecteViewColumns.test.tsx +0 -0
  288. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/webui/src/hooks/tests/useSortByField.test.tsx +0 -0
  289. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/webui/src/hooks/tests/useSwarmUi.test.tsx +0 -0
  290. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/webui/src/hooks/useInterval.ts +0 -0
  291. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/webui/src/hooks/useNotifications.ts +0 -0
  292. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/webui/src/hooks/useSelectViewColumns.ts +0 -0
  293. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/webui/src/hooks/useSortByField.ts +0 -0
  294. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/webui/src/hooks/useSwarmUi.ts +0 -0
  295. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/webui/src/index.tsx +0 -0
  296. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/webui/src/pages/Auth.tsx +0 -0
  297. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/webui/src/pages/Dashboard.tsx +0 -0
  298. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/webui/src/pages/HtmlReport.tsx +0 -0
  299. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/webui/src/pages/tests/Auth.test.tsx +0 -0
  300. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/webui/src/pages/tests/Dashboard.test.tsx +0 -0
  301. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/webui/src/pages/tests/HtmlReport.test.tsx +0 -0
  302. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/webui/src/redux/api/swarm.ts +0 -0
  303. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/webui/src/redux/hooks.ts +0 -0
  304. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/webui/src/redux/slice/logViewer.slice.ts +0 -0
  305. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/webui/src/redux/slice/notification.slice.ts +0 -0
  306. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/webui/src/redux/slice/root.slice.ts +0 -0
  307. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/webui/src/redux/slice/swarm.slice.ts +0 -0
  308. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/webui/src/redux/slice/tests/ui.slice.test.ts +0 -0
  309. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/webui/src/redux/slice/theme.slice.ts +0 -0
  310. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/webui/src/redux/slice/ui.slice.ts +0 -0
  311. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/webui/src/redux/slice/url.slice.ts +0 -0
  312. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/webui/src/redux/store.ts +0 -0
  313. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/webui/src/redux/utils.ts +0 -0
  314. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/webui/src/styles/theme.ts +0 -0
  315. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/webui/src/test/constants.ts +0 -0
  316. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/webui/src/test/mocks/statsRequest.mock.ts +0 -0
  317. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/webui/src/test/mocks/swarmState.mock.ts +0 -0
  318. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/webui/src/test/setup.ts +0 -0
  319. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/webui/src/test/testUtils.tsx +0 -0
  320. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/webui/src/types/auth.types.ts +0 -0
  321. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/webui/src/types/swarm.types.ts +0 -0
  322. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/webui/src/types/tab.types.ts +0 -0
  323. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/webui/src/types/table.types.ts +0 -0
  324. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/webui/src/types/ui.types.ts +0 -0
  325. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/webui/src/utils/number.ts +0 -0
  326. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/webui/src/utils/object.ts +0 -0
  327. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/webui/src/utils/string.ts +0 -0
  328. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/webui/src/utils/tests/number.test.ts +0 -0
  329. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/webui/src/utils/tests/object.test.ts +0 -0
  330. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/webui/src/utils/tests/string.test.ts +0 -0
  331. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/webui/src/utils/tests/url.test.ts +0 -0
  332. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/webui/src/utils/url.ts +0 -0
  333. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/webui/tsconfig.json +0 -0
  334. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/webui/vite.config.ts +0 -0
  335. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/webui/vitest.config.ts +0 -0
  336. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust/webui/yarn.lock +0 -0
  337. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust.egg-info/SOURCES.txt +0 -0
  338. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust.egg-info/dependency_links.txt +0 -0
  339. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust.egg-info/entry_points.txt +0 -0
  340. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust.egg-info/not-zip-safe +0 -0
  341. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust.egg-info/requires.txt +0 -0
  342. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/locust.egg-info/top_level.txt +0 -0
  343. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/package.json +0 -0
  344. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/pyproject.toml +0 -0
  345. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/scripts/locustfile.py +0 -0
  346. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/scripts/run-disributed-headless.sh +0 -0
  347. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/scripts/run-disributed-web.sh +0 -0
  348. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/scripts/run-local-headless.sh +0 -0
  349. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/scripts/run-local-web.sh +0 -0
  350. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/setup.cfg +0 -0
  351. {locust-2.26.1.dev26 → locust-2.26.1.dev48}/tox.ini +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: locust
3
- Version: 2.26.1.dev26
3
+ Version: 2.26.1.dev48
4
4
  Summary: Developer friendly load testing framework
5
5
  License: MIT
6
6
  Project-URL: Homepage, https://github.com/locustio/locust
@@ -114,8 +114,7 @@ See :ref:`running-without-web-ui`
114
114
  Using multiple Locustfiles at once
115
115
  ==================================
116
116
 
117
- The ``-f/--locustfile`` option accepts a single directory of locustfiles as an option. Locust will recursively
118
- search the directory for ``*.py`` files, ignoring files that start with "_".
117
+ ``-f/--locustfile`` accepts multiple, comma-separated locustfiles.
119
118
 
120
119
  Example:
121
120
 
@@ -132,20 +131,23 @@ With the following file structure:
132
131
 
133
132
  .. code-block:: console
134
133
 
135
- $ locust -f locustfiles
134
+ $ locust -f locustfiles/locustfile1.py,locustfiles/locustfile2.py,locustfiles/more_files/locustfile3.py
136
135
 
137
136
  Locust will use ``locustfile1.py``, ``locustfile2.py`` & ``more_files/locustfile3.py``
138
137
 
139
- Additionally, ``-f/--locustfile`` accepts multiple, comma-separated locustfiles.
138
+ Additionally, ``-f/--locustfile`` accepts directories as an option. Locust will recursively
139
+ search specified directories for ``*.py`` files, ignoring files that start with "_".
140
140
 
141
141
  Example:
142
142
 
143
143
  .. code-block:: console
144
144
 
145
- $ locust -f locustfiles/locustfile1.py,locustfiles/locustfile2.py,locustfiles/more_files/locustfile3.py
145
+ $ locust -f locustfiles
146
146
 
147
147
  Locust will use ``locustfile1.py``, ``locustfile2.py`` & ``more_files/locustfile3.py``
148
148
 
149
+
150
+
149
151
  You can also use ``-f/--locustfile`` for web urls. This will download the file and use it as any normal locustfile.
150
152
 
151
153
  Example:
@@ -12,5 +12,5 @@ __version__: str
12
12
  __version_tuple__: VERSION_TUPLE
13
13
  version_tuple: VERSION_TUPLE
14
14
 
15
- __version__ = version = '2.26.1.dev26'
16
- __version_tuple__ = version_tuple = (2, 26, 1, 'dev26')
15
+ __version__ = version = '2.26.1.dev48'
16
+ __version_tuple__ = version_tuple = (2, 26, 1, 'dev48')
@@ -93,90 +93,54 @@ class LocustTomlConfigParser(configargparse.TomlConfigParser):
93
93
  return result
94
94
 
95
95
 
96
- def _is_package(path):
96
+ def parse_locustfile_paths(paths: list[str]) -> list[str]:
97
97
  """
98
- Is the given path a Python package?
99
- """
100
- return os.path.isdir(path) and os.path.exists(os.path.join(path, "__init__.py"))
101
-
102
-
103
- def find_locustfile(locustfile: str) -> str | None:
104
- """
105
- Attempt to locate a locustfile, either explicitly or by searching parent dirs.
106
- """
107
- # Obtain env value
108
- names = [locustfile]
109
- # Create .py version if necessary
110
- if not names[0].endswith(".py"):
111
- names.append(names[0] + ".py")
112
- # Does the name contain path elements?
113
- if os.path.dirname(names[0]):
114
- # If so, expand home-directory markers and test for existence
115
- for name in names:
116
- expanded = os.path.expanduser(name)
117
- if os.path.exists(expanded):
118
- if name.endswith(".py") or _is_package(expanded):
119
- return os.path.abspath(expanded)
120
- else:
121
- # Otherwise, start in cwd and work downwards towards filesystem root
122
- path = os.path.abspath(".")
123
- while True:
124
- for name in names:
125
- joined = os.path.join(path, name)
126
- if os.path.exists(joined):
127
- if name.endswith(".py") or _is_package(joined):
128
- return os.path.abspath(joined)
129
- parent_path = os.path.dirname(path)
130
- if parent_path == path:
131
- # we've reached the root path which has been checked this iteration
132
- break
133
- path = parent_path
134
-
135
- return None
136
-
98
+ Returns a list of relative file paths.
137
99
 
138
- def find_locustfiles(locustfiles: list[str], is_directory: bool) -> list[str]:
139
- """
140
- Returns a list of relative file paths for the Locustfile Picker. If is_directory is True,
141
- locustfiles is expected to have a single index which is a directory that will be searched for
142
- locustfiles.
100
+ Args:
101
+ paths (list[str]): paths taken from the -f command
143
102
 
144
- Ignores files that start with _
103
+ Returns:
104
+ list[str]: Parsed locust file paths
145
105
  """
146
- file_paths = []
147
-
148
- if is_directory:
149
- locustdir = locustfiles[0]
150
-
151
- if len(locustfiles) != 1:
152
- sys.stderr.write(f"Multiple values passed in for directory: {locustfiles}\n")
153
- sys.exit(1)
154
-
155
- if not os.path.exists(locustdir):
156
- sys.stderr.write(f"Could not find directory '{locustdir}'\n")
157
- sys.exit(1)
158
-
159
- if not os.path.isdir(locustdir):
160
- sys.stderr.write(f"'{locustdir} is not a directory\n")
106
+ # Parse each path and unpack the returned lists as a single list
107
+ return [parsed for path in paths for parsed in _parse_locustfile_path(path)]
108
+
109
+
110
+ def _parse_locustfile_path(path: str) -> list[str]:
111
+ parsed_paths = []
112
+ if is_url(path):
113
+ # Download the file and use the new path as locustfile
114
+ parsed_paths.append(download_locustfile_from_url(path))
115
+ elif os.path.isdir(path):
116
+ # Find all .py files in directory tree
117
+ for root, _dirs, fs in os.walk(path):
118
+ parsed_paths.extend(
119
+ [
120
+ os.path.abspath(os.path.join(root, f))
121
+ for f in fs
122
+ if os.path.isfile(os.path.join(root, f)) and f.endswith(".py") and not f.startswith("_")
123
+ ]
124
+ )
125
+ if not parsed_paths:
126
+ sys.stderr.write(f"Could not find any locustfiles in directory '{path}'")
161
127
  sys.exit(1)
162
-
163
- for root, dirs, files in os.walk(locustdir):
164
- for file in files:
165
- if not file.startswith("_") and file.endswith(".py"):
166
- file_path = os.path.join(root, file)
167
- file_paths.append(file_path)
168
128
  else:
169
- for file_path in locustfiles:
170
- if not file_path.endswith(".py"):
171
- sys.stderr.write(f"Invalid file '{file_path}'. File should have '.py' extension\n")
172
- sys.exit(1)
173
-
174
- file_paths.append(file_path)
129
+ # If file exists add the abspath
130
+ if os.path.exists(path) and path.endswith(".py"):
131
+ parsed_paths.append(os.path.abspath(path))
132
+ else:
133
+ note_about_file_endings = "Ensure your locustfile ends with '.py' or is a directory with locustfiles. "
134
+ sys.stderr.write(f"Could not find '{path}'. {note_about_file_endings}See --help for available options.\n")
135
+ sys.exit(1)
175
136
 
176
- return file_paths
137
+ return parsed_paths
177
138
 
178
139
 
179
140
  def is_url(url: str) -> bool:
141
+ """
142
+ Check if path is an url
143
+ """
180
144
  try:
181
145
  result = urlparse(url)
182
146
  if result.scheme == "https" or result.scheme == "http":
@@ -188,6 +152,10 @@ def is_url(url: str) -> bool:
188
152
 
189
153
 
190
154
  def download_locustfile_from_url(url: str) -> str:
155
+ """
156
+ Attempt to download and save locustfile from url.
157
+ Returns path to downloaded file.
158
+ """
191
159
  try:
192
160
  response = requests.get(url)
193
161
  # Check if response is valid python code
@@ -244,7 +212,7 @@ See documentation for more details, including how to set options using a file or
244
212
  "-f",
245
213
  "--locustfile",
246
214
  metavar="<filename>",
247
- default="locustfile",
215
+ default="locustfile.py",
248
216
  help="The Python file or module that contains your test, e.g. 'my_test.py'. Accepts multiple comma-separated .py files, a package name/directory or a url to a remote locustfile. Defaults to 'locustfile'.",
249
217
  env_var="LOCUST_LOCUSTFILE",
250
218
  )
@@ -314,7 +282,7 @@ def parse_locustfile_option(args=None) -> list[str]:
314
282
  parser
315
283
 
316
284
  Returns:
317
- Locustfiles (List): List of locustfile paths
285
+ parsed_paths (List): List of locustfile paths
318
286
  """
319
287
  parser = get_empty_argument_parser(add_help=False)
320
288
  parser.add_argument(
@@ -354,6 +322,10 @@ def parse_locustfile_option(args=None) -> list[str]:
354
322
 
355
323
  options, _ = parser.parse_known_args(args=args)
356
324
 
325
+ if options.help or options.version:
326
+ # if --help or --version is specified we'll call parse_options which will print the help/version message
327
+ parse_options(args=args)
328
+
357
329
  if options.locustfile == "-":
358
330
  if not options.worker:
359
331
  sys.stderr.write(
@@ -364,51 +336,21 @@ def parse_locustfile_option(args=None) -> list[str]:
364
336
  filename = download_locustfile_from_master(options.master_host, options.master_port)
365
337
  return [filename]
366
338
 
367
- # Comma separated string to list
368
- locustfile_as_list = [
369
- download_locustfile_from_url(f) if is_url(f.strip()) else f.strip() for f in options.locustfile.split(",")
370
- ]
339
+ locustfile_list = [f.strip() for f in options.locustfile.split(",")]
340
+ parsed_paths = parse_locustfile_paths(locustfile_list)
371
341
 
372
- # Checking if the locustfile is a single file, multiple files or a directory
373
- if locustfile_is_directory(locustfile_as_list):
374
- locustfiles = find_locustfiles(locustfile_as_list, is_directory=True)
375
- locustfile = None
342
+ if not parsed_paths:
343
+ note_about_file_endings = ""
344
+ user_friendly_locustfile_name = options.locustfile
376
345
 
377
- if not locustfiles:
378
- sys.stderr.write(
379
- f"Could not find any locustfiles in directory '{locustfile_as_list[0]}'. See --help for available options.\n"
380
- )
381
- sys.exit(1)
382
- else:
383
- if len(locustfile_as_list) > 1:
384
- # Is multiple files
385
- locustfiles = find_locustfiles(locustfile_as_list, is_directory=False)
386
- locustfile = None
387
- else:
388
- # Is a single file
389
- locustfile = find_locustfile(locustfile_as_list[0])
390
- locustfiles = []
391
-
392
- if not locustfile:
393
- if options.help or options.version:
394
- # if --help or --version is specified we'll call parse_options which will print the help/version message
395
- parse_options(args=args)
396
- note_about_file_endings = ""
397
- user_friendly_locustfile_name = options.locustfile
398
- if options.locustfile == "locustfile":
399
- user_friendly_locustfile_name = "locustfile.py"
400
- elif not options.locustfile.endswith(".py"):
401
- note_about_file_endings = (
402
- "Ensure your locustfile ends with '.py' or is a directory with locustfiles. "
403
- )
404
- sys.stderr.write(
405
- f"Could not find '{user_friendly_locustfile_name}'. {note_about_file_endings}See --help for available options.\n"
406
- )
407
- sys.exit(1)
408
- else:
409
- locustfiles.append(locustfile)
410
-
411
- return locustfiles
346
+ if not options.locustfile.endswith(".py"):
347
+ note_about_file_endings = "Ensure your locustfile ends with '.py' or is a directory with parsed_paths. "
348
+ sys.stderr.write(
349
+ f"Could not find '{user_friendly_locustfile_name}'. {note_about_file_endings}See --help for available options.\n"
350
+ )
351
+ sys.exit(1)
352
+
353
+ return parsed_paths
412
354
 
413
355
 
414
356
  def setup_parser_arguments(parser):
@@ -857,34 +799,3 @@ def ui_extra_args_dict(args=None) -> dict[str, dict[str, Any]]:
857
799
  }
858
800
 
859
801
  return extra_args
860
-
861
-
862
- def locustfile_is_directory(locustfiles: list[str]) -> bool:
863
- """
864
- If a user passes in a locustfile without a file extension and there is a directory with the same name,
865
- this function defaults to using the file and will raise a warning.
866
- In this example, foobar.py will be used:
867
- ├── src/
868
- │ ├── foobar.py
869
- ├── foobar/
870
- │ ├── locustfile.py
871
-
872
- locust -f foobar
873
- """
874
- if len(locustfiles) > 1:
875
- return False
876
-
877
- locustfile = locustfiles[0]
878
-
879
- # Checking if the locustfile could be both a file and a directory
880
- if not locustfile.endswith(".py"):
881
- if os.path.isfile(locustfile) and os.path.isdir(locustfile):
882
- msg = f"WARNING: Using {locustfile}.py instead of directory {os.path.abspath(locustfile)}\n"
883
- sys.stderr.write(msg)
884
-
885
- return False
886
-
887
- if os.path.isdir(locustfile):
888
- return True
889
-
890
- return False
@@ -1032,23 +1032,19 @@ class MasterRunner(DistributedRunner):
1032
1032
  elif msg.type == "locustfile":
1033
1033
  logging.debug("Worker requested locust file")
1034
1034
  assert self.environment.parsed_options
1035
- filename = (
1036
- "locustfile.py"
1037
- if self.environment.parsed_options.locustfile == "locustfile"
1038
- else self.environment.parsed_options.locustfile
1039
- )
1035
+ filename = self.environment.parsed_options.locustfile
1040
1036
  try:
1041
1037
  with open(filename) as f:
1042
1038
  file_contents = f.read()
1043
1039
  except Exception as e:
1044
1040
  logger.error(
1045
- f"--locustfile must be a plain filename (not a module name) for file distribution to work {e}"
1041
+ f"--locustfile must be a full path to a single locustfile for file distribution to work {e}"
1046
1042
  )
1047
1043
  self.send_message(
1048
1044
  "locustfile",
1049
1045
  client_id=client_id,
1050
1046
  data={
1051
- "error": f"locustfile parameter on master must be a plain filename (not a module name) (was '{filename}')"
1047
+ "error": f"locustfile must be a full path to a single locustfile for file distribution to work (was '{filename}')"
1052
1048
  },
1053
1049
  )
1054
1050
  else:
@@ -1026,6 +1026,32 @@ class StandaloneIntegrationTests(ProcessIntegrationTest):
1026
1026
  self.assertIn("Shutting down (exit code 0)", output)
1027
1027
  self.assertEqual(0, proc.returncode)
1028
1028
 
1029
+ def test_with_package_as_locustfile(self):
1030
+ with TemporaryDirectory() as temp_dir:
1031
+ with open(f"{temp_dir}/__init__.py", mode="w"):
1032
+ with mock_locustfile(dir=temp_dir):
1033
+ proc = subprocess.Popen(
1034
+ [
1035
+ "locust",
1036
+ "-f",
1037
+ temp_dir,
1038
+ "--headless",
1039
+ "--exit-code-on-error",
1040
+ "0",
1041
+ "--run-time",
1042
+ "2",
1043
+ ],
1044
+ stdout=PIPE,
1045
+ stderr=PIPE,
1046
+ text=True,
1047
+ )
1048
+ stdout, stderr = proc.communicate()
1049
+ self.assertIn("Starting Locust", stderr)
1050
+ self.assertIn("All users spawned:", stderr)
1051
+ self.assertIn('"UserSubclass": 1', stderr)
1052
+ self.assertIn("Shutting down (exit code 0)", stderr)
1053
+ self.assertEqual(0, proc.returncode)
1054
+
1029
1055
  def test_command_line_user_selection(self):
1030
1056
  LOCUSTFILE_CONTENT = textwrap.dedent(
1031
1057
  """
@@ -1132,7 +1158,7 @@ class StandaloneIntegrationTests(ProcessIntegrationTest):
1132
1158
  stderr=PIPE,
1133
1159
  text=True,
1134
1160
  )
1135
- gevent.sleep(1)
1161
+ gevent.sleep(2)
1136
1162
  proc.send_signal(signal.SIGTERM)
1137
1163
  stdout, stderr = proc.communicate()
1138
1164
 
@@ -1801,34 +1827,49 @@ class SecondUser(HttpUser):
1801
1827
  """
1802
1828
  )
1803
1829
  with mock_locustfile(content=LOCUSTFILE_CONTENT) as mocked:
1804
- proc = subprocess.Popen(
1805
- [
1806
- "locust",
1807
- "-f",
1808
- mocked.file_path[:-3], # remove ".py"
1809
- "--headless",
1810
- "--master",
1811
- ],
1812
- stderr=STDOUT,
1813
- stdout=PIPE,
1814
- text=True,
1815
- )
1816
- proc_worker = subprocess.Popen(
1817
- [
1818
- "locust",
1819
- "-f",
1820
- "-",
1821
- "--worker",
1822
- ],
1823
- stderr=STDOUT,
1824
- stdout=PIPE,
1825
- text=True,
1826
- )
1827
- stdout = proc_worker.communicate()[0]
1828
- self.assertIn("Got error from master: locustfile parameter on master must be a plain filename", stdout)
1829
- proc.kill()
1830
- master_stdout = proc.communicate()[0]
1831
- self.assertIn("--locustfile must be a plain filename (not a module name) for file distribut", master_stdout)
1830
+ with mock_locustfile() as mocked2:
1831
+ proc = subprocess.Popen(
1832
+ [
1833
+ "locust",
1834
+ "-f",
1835
+ f"{mocked.file_path}, {mocked2.file_path}",
1836
+ "--headless",
1837
+ "--master",
1838
+ "-L",
1839
+ "debug",
1840
+ ],
1841
+ stderr=STDOUT,
1842
+ stdout=PIPE,
1843
+ text=True,
1844
+ )
1845
+ proc_worker = subprocess.Popen(
1846
+ [
1847
+ "locust",
1848
+ "-f",
1849
+ "-",
1850
+ "--worker",
1851
+ ],
1852
+ stderr=STDOUT,
1853
+ stdout=PIPE,
1854
+ text=True,
1855
+ )
1856
+
1857
+ try:
1858
+ stdout = proc_worker.communicate(timeout=5)[0]
1859
+ self.assertIn(
1860
+ "Got error from master: locustfile must be a full path to a single locustfile for file distribution to work",
1861
+ stdout,
1862
+ )
1863
+ proc.kill()
1864
+ master_stdout = proc.communicate()[0]
1865
+ self.assertIn(
1866
+ "--locustfile must be a full path to a single locustfile for file distribution", master_stdout
1867
+ )
1868
+ except Exception:
1869
+ proc.kill()
1870
+ proc_worker.kill()
1871
+ stdout, worker_stderr = proc_worker.communicate()
1872
+ assert False, f"worker never finished: {stdout}"
1832
1873
 
1833
1874
  def test_json_schema(self):
1834
1875
  LOCUSTFILE_CONTENT = textwrap.dedent(
@@ -1,9 +1,8 @@
1
1
  import locust
2
2
  from locust.argument_parser import (
3
- find_locustfiles,
4
3
  get_parser,
5
- locustfile_is_directory,
6
4
  parse_locustfile_option,
5
+ parse_locustfile_paths,
7
6
  parse_options,
8
7
  ui_extra_args_dict,
9
8
  )
@@ -91,6 +90,7 @@ class TestArgumentParser(LocustTestCase):
91
90
  super().setUp()
92
91
  self.parent_dir = TemporaryDirectory()
93
92
  self.child_dir = TemporaryDirectory(dir=self.parent_dir.name)
93
+ self.child_dir2 = TemporaryDirectory(dir=self.parent_dir.name)
94
94
 
95
95
  def tearDown(self):
96
96
  super().tearDown()
@@ -257,6 +257,33 @@ class TestArgumentParser(LocustTestCase):
257
257
  ]
258
258
  )
259
259
 
260
+ def test_parse_locustfile_and_directory(self):
261
+ with mock_locustfile(filename_prefix="mock_locustfile1", dir=self.parent_dir.name) as mock_locustfile1:
262
+ with mock_locustfile(filename_prefix="mock_locustfile2", dir=self.parent_dir.name) as mock_locustfile2:
263
+ with mock_locustfile(filename_prefix="mock_locustfile3", dir=self.child_dir.name) as mock_locustfile3:
264
+ locustfiles = parse_locustfile_option(
265
+ args=[
266
+ "-f",
267
+ f"{mock_locustfile1.file_path},{self.child_dir.name}",
268
+ ]
269
+ )
270
+ self.assertIn(mock_locustfile1.file_path, locustfiles)
271
+ self.assertNotIn(mock_locustfile2.file_path, locustfiles)
272
+ self.assertIn(mock_locustfile3.file_path, locustfiles)
273
+
274
+ def test_parse_multiple_directories(self):
275
+ with mock_locustfile(filename_prefix="mock_locustfile1", dir=self.child_dir.name) as mock_locustfile1:
276
+ with mock_locustfile(filename_prefix="mock_locustfile2", dir=self.child_dir2.name) as mock_locustfile2:
277
+ locustfiles = parse_locustfile_option(
278
+ args=[
279
+ "-f",
280
+ f"{self.child_dir.name},{self.child_dir2.name}",
281
+ ]
282
+ )
283
+
284
+ self.assertIn(mock_locustfile1.file_path, locustfiles)
285
+ self.assertIn(mock_locustfile2.file_path, locustfiles)
286
+
260
287
  def test_parse_locustfile_invalid_directory_error(self):
261
288
  with mock.patch("sys.stderr", new=StringIO()):
262
289
  with self.assertRaises(SystemExit):
@@ -377,7 +404,7 @@ class TestFindLocustfiles(LocustTestCase):
377
404
  with mock_locustfile(dir=self.parent_dir1.name) as mocked1:
378
405
  with mock_locustfile(dir=self.child_dir.name) as mocked2:
379
406
  with mock_locustfile(dir=self.child_dir.name) as mocked3:
380
- locustfiles = find_locustfiles([self.parent_dir1.name], True)
407
+ locustfiles = parse_locustfile_paths([self.parent_dir1.name])
381
408
 
382
409
  self.assertIn(mocked1.file_path, locustfiles)
383
410
  self.assertIn(mocked2.file_path, locustfiles)
@@ -387,13 +414,13 @@ class TestFindLocustfiles(LocustTestCase):
387
414
  def test_find_locustfiles_error_if_directory_doesnt_exist(self):
388
415
  with mock.patch("sys.stderr", new=StringIO()):
389
416
  with self.assertRaises(SystemExit):
390
- find_locustfiles(["some_directory"], True)
417
+ parse_locustfile_paths(["some_directory"])
391
418
 
392
419
  def test_find_locustfiles_ignores_invalid_files_in_directory(self):
393
420
  with NamedTemporaryFile(suffix=".py", prefix="_", dir=self.parent_dir1.name) as invalid_file1:
394
421
  with NamedTemporaryFile(suffix=".txt", prefix="", dir=self.parent_dir1.name) as invalid_file2:
395
422
  with mock_locustfile(filename_prefix="mock_locustfile1", dir=self.parent_dir1.name) as mock_locustfile1:
396
- locustfiles = find_locustfiles([self.parent_dir1.name], True)
423
+ locustfiles = parse_locustfile_paths([self.parent_dir1.name])
397
424
 
398
425
  self.assertIn(mock_locustfile1.file_path, locustfiles)
399
426
  self.assertNotIn(invalid_file1.name, locustfiles)
@@ -403,7 +430,7 @@ class TestFindLocustfiles(LocustTestCase):
403
430
  def test_find_locustfiles_with_multiple_locustfiles(self):
404
431
  with mock_locustfile() as mocked1:
405
432
  with mock_locustfile() as mocked2:
406
- locustfiles = find_locustfiles([mocked1.file_path, mocked2.file_path], False)
433
+ locustfiles = parse_locustfile_paths([mocked1.file_path, mocked2.file_path])
407
434
 
408
435
  self.assertIn(mocked1.file_path, locustfiles)
409
436
  self.assertIn(mocked2.file_path, locustfiles)
@@ -415,58 +442,9 @@ class TestFindLocustfiles(LocustTestCase):
415
442
  with mock_locustfile() as valid_file:
416
443
  with self.assertRaises(SystemExit):
417
444
  invalid_file = NamedTemporaryFile(suffix=".txt")
418
- find_locustfiles([valid_file.file_path, invalid_file.name], False)
419
-
420
- def test_find_locustfiles_error_if_invalid_directory(self):
421
- with mock.patch("sys.stderr", new=StringIO()):
422
- with mock_locustfile() as valid_file:
423
- with self.assertRaises(SystemExit):
424
- find_locustfiles([valid_file.file_path], True)
445
+ parse_locustfile_paths([valid_file.file_path, invalid_file.name])
425
446
 
426
447
  def test_find_locustfiles_error_if_multiple_values_for_directory(self):
427
448
  with mock.patch("sys.stderr", new=StringIO()):
428
449
  with self.assertRaises(SystemExit):
429
- find_locustfiles([self.parent_dir1.name, self.parent_dir2.name], True)
430
-
431
-
432
- class TestLocustfileIsDirectory(LocustTestCase):
433
- def setUp(self):
434
- super().setUp()
435
- self.random_prefix = "locust/test/foobar_" + str(randint(1000, 9999))
436
- self.mock_filename = self.random_prefix + ".py"
437
-
438
- self.mock_locustfile = open(self.mock_filename, "w")
439
- self.mock_locustfile.close()
440
- self.mock_dir = os.mkdir(self.random_prefix)
441
-
442
- def tearDown(self):
443
- super().tearDown()
444
- os.remove(self.mock_filename)
445
- os.rmdir(self.random_prefix)
446
-
447
- def test_locustfile_is_directory_single_locustfile(self):
448
- with mock_locustfile() as mocked:
449
- is_dir = locustfile_is_directory([mocked.file_path])
450
- assert not is_dir
451
-
452
- def test_locustfile_is_directory_single_locustfile_without_file_extension(self):
453
- prefix_name = "foobar"
454
- with NamedTemporaryFile(prefix=prefix_name, suffix=".py"):
455
- is_dir = locustfile_is_directory([prefix_name])
456
- assert not is_dir
457
-
458
- def test_locustfile_is_directory_multiple_locustfiles(self):
459
- with mock_locustfile() as mocked1:
460
- with mock_locustfile() as mocked2:
461
- is_dir = locustfile_is_directory([mocked1.file_path, mocked2.file_path])
462
- assert not is_dir
463
-
464
- def test_locustfile_is_directory_true_if_directory(self):
465
- with TemporaryDirectory() as mocked_dir:
466
- is_dir = locustfile_is_directory([mocked_dir])
467
- assert is_dir
468
-
469
- def test_locustfile_is_directory_false_if_file_and_directory_share_the_same_name(self):
470
- """See locustfile_is_directory docstring of an example of this usecase"""
471
- is_dir = locustfile_is_directory([self.random_prefix, self.mock_filename])
472
- assert not is_dir
450
+ parse_locustfile_paths([self.parent_dir1.name, self.parent_dir2.name])
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: locust
3
- Version: 2.26.1.dev26
3
+ Version: 2.26.1.dev48
4
4
  Summary: Developer friendly load testing framework
5
5
  License: MIT
6
6
  Project-URL: Homepage, https://github.com/locustio/locust
File without changes
File without changes