locust 2.30.1.dev14__tar.gz → 2.30.1.dev20__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 (45) hide show
  1. {locust-2.30.1.dev14 → locust-2.30.1.dev20}/PKG-INFO +1 -1
  2. {locust-2.30.1.dev14 → locust-2.30.1.dev20}/locust/_version.py +2 -2
  3. {locust-2.30.1.dev14 → locust-2.30.1.dev20}/locust/argument_parser.py +7 -0
  4. {locust-2.30.1.dev14 → locust-2.30.1.dev20}/locust/env.py +2 -0
  5. {locust-2.30.1.dev14 → locust-2.30.1.dev20}/locust/html.py +6 -18
  6. {locust-2.30.1.dev14 → locust-2.30.1.dev20}/locust/main.py +6 -1
  7. {locust-2.30.1.dev14 → locust-2.30.1.dev20}/locust/web.py +15 -7
  8. {locust-2.30.1.dev14 → locust-2.30.1.dev20}/pyproject.toml +1 -1
  9. {locust-2.30.1.dev14 → locust-2.30.1.dev20}/LICENSE +0 -0
  10. {locust-2.30.1.dev14 → locust-2.30.1.dev20}/README.md +0 -0
  11. {locust-2.30.1.dev14 → locust-2.30.1.dev20}/locust/__init__.py +0 -0
  12. {locust-2.30.1.dev14 → locust-2.30.1.dev20}/locust/__main__.py +0 -0
  13. {locust-2.30.1.dev14 → locust-2.30.1.dev20}/locust/clients.py +0 -0
  14. {locust-2.30.1.dev14 → locust-2.30.1.dev20}/locust/contrib/__init__.py +0 -0
  15. {locust-2.30.1.dev14 → locust-2.30.1.dev20}/locust/contrib/fasthttp.py +0 -0
  16. {locust-2.30.1.dev14 → locust-2.30.1.dev20}/locust/debug.py +0 -0
  17. {locust-2.30.1.dev14 → locust-2.30.1.dev20}/locust/dispatch.py +0 -0
  18. {locust-2.30.1.dev14 → locust-2.30.1.dev20}/locust/event.py +0 -0
  19. {locust-2.30.1.dev14 → locust-2.30.1.dev20}/locust/exception.py +0 -0
  20. {locust-2.30.1.dev14 → locust-2.30.1.dev20}/locust/input_events.py +0 -0
  21. {locust-2.30.1.dev14 → locust-2.30.1.dev20}/locust/log.py +0 -0
  22. {locust-2.30.1.dev14 → locust-2.30.1.dev20}/locust/py.typed +0 -0
  23. {locust-2.30.1.dev14 → locust-2.30.1.dev20}/locust/rpc/__init__.py +0 -0
  24. {locust-2.30.1.dev14 → locust-2.30.1.dev20}/locust/rpc/protocol.py +0 -0
  25. {locust-2.30.1.dev14 → locust-2.30.1.dev20}/locust/rpc/zmqrpc.py +0 -0
  26. {locust-2.30.1.dev14 → locust-2.30.1.dev20}/locust/runners.py +0 -0
  27. {locust-2.30.1.dev14 → locust-2.30.1.dev20}/locust/shape.py +0 -0
  28. {locust-2.30.1.dev14 → locust-2.30.1.dev20}/locust/stats.py +0 -0
  29. {locust-2.30.1.dev14 → locust-2.30.1.dev20}/locust/user/__init__.py +0 -0
  30. {locust-2.30.1.dev14 → locust-2.30.1.dev20}/locust/user/inspectuser.py +0 -0
  31. {locust-2.30.1.dev14 → locust-2.30.1.dev20}/locust/user/sequential_taskset.py +0 -0
  32. {locust-2.30.1.dev14 → locust-2.30.1.dev20}/locust/user/task.py +0 -0
  33. {locust-2.30.1.dev14 → locust-2.30.1.dev20}/locust/user/users.py +0 -0
  34. {locust-2.30.1.dev14 → locust-2.30.1.dev20}/locust/user/wait_time.py +0 -0
  35. {locust-2.30.1.dev14 → locust-2.30.1.dev20}/locust/util/__init__.py +0 -0
  36. {locust-2.30.1.dev14 → locust-2.30.1.dev20}/locust/util/cache.py +0 -0
  37. {locust-2.30.1.dev14 → locust-2.30.1.dev20}/locust/util/date.py +0 -0
  38. {locust-2.30.1.dev14 → locust-2.30.1.dev20}/locust/util/deprecation.py +0 -0
  39. {locust-2.30.1.dev14 → locust-2.30.1.dev20}/locust/util/directory.py +0 -0
  40. {locust-2.30.1.dev14 → locust-2.30.1.dev20}/locust/util/exception_handler.py +0 -0
  41. {locust-2.30.1.dev14 → locust-2.30.1.dev20}/locust/util/load_locustfile.py +0 -0
  42. {locust-2.30.1.dev14 → locust-2.30.1.dev20}/locust/util/rounding.py +0 -0
  43. {locust-2.30.1.dev14 → locust-2.30.1.dev20}/locust/util/timespan.py +0 -0
  44. {locust-2.30.1.dev14 → locust-2.30.1.dev20}/locust/util/url.py +0 -0
  45. {locust-2.30.1.dev14 → locust-2.30.1.dev20}/pre_build.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: locust
3
- Version: 2.30.1.dev14
3
+ Version: 2.30.1.dev20
4
4
  Summary: Developer-friendly load testing framework
5
5
  Home-page: https://locust.io/
6
6
  License: MIT
@@ -14,7 +14,7 @@ __version_tuple__: VERSION_TUPLE
14
14
  version_tuple: VERSION_TUPLE
15
15
 
16
16
 
17
- __version__ = "2.30.1.dev14"
17
+ __version__ = "2.30.1.dev20"
18
18
  version = __version__
19
- __version_tuple__ = (2, 30, 1, "dev14")
19
+ __version_tuple__ = (2, 30, 1, "dev20")
20
20
  version_tuple = __version_tuple__
@@ -496,6 +496,13 @@ def setup_parser_arguments(parser):
496
496
  help="Enable select boxes in the web interface to choose from all available User classes and Shape classes",
497
497
  env_var="LOCUST_USERCLASS_PICKER",
498
498
  )
499
+ web_ui_group.add_argument(
500
+ "--build-path",
501
+ type=str,
502
+ default="",
503
+ help=configargparse.SUPPRESS,
504
+ env_var="LOCUST_BUILD_PATH",
505
+ )
499
506
  web_ui_group.add_argument(
500
507
  "--legacy-ui",
501
508
  default=False,
@@ -171,6 +171,7 @@ class Environment:
171
171
  stats_csv_writer: StatsCSV | None = None,
172
172
  delayed_start=False,
173
173
  userclass_picker_is_active=False,
174
+ build_path: str | None = None,
174
175
  ) -> WebUI:
175
176
  """
176
177
  Creates a :class:`WebUI <locust.web.WebUI>` instance for this Environment and start running the web server
@@ -197,6 +198,7 @@ class Environment:
197
198
  stats_csv_writer=stats_csv_writer,
198
199
  delayed_start=delayed_start,
199
200
  userclass_picker_is_active=userclass_picker_is_active,
201
+ build_path=build_path,
200
202
  )
201
203
  return self.web_ui
202
204
 
@@ -5,7 +5,8 @@ from html import escape
5
5
  from itertools import chain
6
6
  from json import dumps
7
7
 
8
- from jinja2 import Environment, FileSystemLoader
8
+ from jinja2 import Environment as JinjaEnvironment
9
+ from jinja2 import FileSystemLoader
9
10
 
10
11
  from . import stats as stats_module
11
12
  from .runners import STATE_STOPPED, STATE_STOPPING, MasterRunner
@@ -14,13 +15,11 @@ from .user.inspectuser import get_ratio
14
15
  from .util.date import format_utc_timestamp
15
16
 
16
17
  PERCENTILES_FOR_HTML_REPORT = [0.50, 0.6, 0.7, 0.8, 0.9, 0.95, 0.99, 1.0]
17
- ROOT_PATH = os.path.dirname(os.path.abspath(__file__))
18
- BUILD_PATH = os.path.join(ROOT_PATH, "webui", "dist")
19
- STATIC_PATH = os.path.join(BUILD_PATH, "assets")
18
+ DEFAULT_BUILD_PATH = os.path.join(os.path.dirname(os.path.abspath(__file__)), "webui", "dist")
20
19
 
21
20
 
22
- def render_template(file, **kwargs):
23
- env = Environment(loader=FileSystemLoader(BUILD_PATH), extensions=["jinja2.ext.do"])
21
+ def render_template_from(file, build_path=DEFAULT_BUILD_PATH, **kwargs):
22
+ env = JinjaEnvironment(loader=FileSystemLoader(build_path))
24
23
  template = env.get_template(file)
25
24
  return template.render(**kwargs)
26
25
 
@@ -56,16 +55,6 @@ def get_html_report(
56
55
  update_stats_history(environment.runner)
57
56
  history = stats.history
58
57
 
59
- static_js = []
60
- js_files = [os.path.basename(filepath) for filepath in glob.glob(os.path.join(STATIC_PATH, "*.js"))]
61
-
62
- for js_file in js_files:
63
- path = os.path.join(STATIC_PATH, js_file)
64
- static_js.append("// " + js_file + "\n")
65
- with open(path, encoding="utf8") as f:
66
- static_js.append(f.read())
67
- static_js.extend(["", ""])
68
-
69
58
  is_distributed = isinstance(environment.runner, MasterRunner)
70
59
  user_spawned = (
71
60
  environment.runner.reported_user_classes_count if is_distributed else environment.runner.user_classes_count
@@ -79,7 +68,7 @@ def get_html_report(
79
68
  "total": get_ratio(environment.user_classes, user_spawned, True),
80
69
  }
81
70
 
82
- return render_template(
71
+ return render_template_from(
83
72
  "report.html",
84
73
  template_args={
85
74
  "is_report": True,
@@ -107,5 +96,4 @@ def get_html_report(
107
96
  "percentiles_to_chart": stats_module.PERCENTILES_TO_CHART,
108
97
  },
109
98
  theme=theme,
110
- static_js="\n".join(static_js),
111
99
  )
@@ -36,11 +36,15 @@ from .user.inspectuser import print_task_ratio, print_task_ratio_json
36
36
  from .util.load_locustfile import load_locustfile
37
37
  from .util.timespan import parse_timespan
38
38
 
39
+ # import external plugins if installed to allow for registering custom arguments etc
39
40
  try:
40
- # import locust_plugins if it is installed, to allow it to register custom arguments etc
41
41
  import locust_plugins # pyright: ignore[reportMissingImports]
42
42
  except ModuleNotFoundError:
43
43
  pass
44
+ try:
45
+ import locust_cloud # pyright: ignore[reportMissingImports]
46
+ except ModuleNotFoundError:
47
+ pass
44
48
 
45
49
  version = locust.__version__
46
50
 
@@ -482,6 +486,7 @@ See https://github.com/locustio/locust/wiki/Installation#increasing-maximum-numb
482
486
  stats_csv_writer=stats_csv_writer,
483
487
  delayed_start=True,
484
488
  userclass_picker_is_active=options.class_picker,
489
+ build_path=options.build_path,
485
490
  )
486
491
  else:
487
492
  web_ui = None
@@ -33,12 +33,13 @@ from gevent import pywsgi
33
33
  from . import __version__ as version
34
34
  from . import argument_parser
35
35
  from . import stats as stats_module
36
- from .html import BUILD_PATH, ROOT_PATH, STATIC_PATH, get_html_report
36
+ from .html import DEFAULT_BUILD_PATH, get_html_report, render_template_from
37
37
  from .log import get_logs, greenlet_exception_logger
38
38
  from .runners import STATE_MISSING, STATE_RUNNING, MasterRunner
39
39
  from .stats import StatsCSV, StatsCSVFileWriter, StatsErrorDict, sort_stats
40
40
  from .user.inspectuser import get_ratio
41
41
  from .util.cache import memoize
42
+ from .util.date import format_utc_timestamp
42
43
  from .util.timespan import parse_timespan
43
44
 
44
45
  if TYPE_CHECKING:
@@ -96,6 +97,7 @@ class WebUI:
96
97
  stats_csv_writer: StatsCSV | None = None,
97
98
  delayed_start=False,
98
99
  userclass_picker_is_active=False,
100
+ build_path: str | None = None,
99
101
  ):
100
102
  """
101
103
  Create WebUI instance and start running the web server in a separate greenlet (self.greenlet)
@@ -124,14 +126,11 @@ class WebUI:
124
126
  self.app = app
125
127
  app.jinja_env.add_extension("jinja2.ext.do")
126
128
  app.debug = True
127
- app.root_path = ROOT_PATH
128
- self.webui_build_path = BUILD_PATH
129
129
  self.greenlet: gevent.Greenlet | None = None
130
130
  self._swarm_greenlet: gevent.Greenlet | None = None
131
131
  self.template_args = {}
132
132
  self.auth_args = {}
133
- self.app.template_folder = BUILD_PATH
134
- self.app.static_folder = STATIC_PATH
133
+ self.app.template_folder = build_path or DEFAULT_BUILD_PATH
135
134
  self.app.static_url_path = "/assets/"
136
135
  # ensures static js files work on Windows
137
136
  mimetypes.add_type("application/javascript", ".js")
@@ -158,7 +157,13 @@ class WebUI:
158
157
 
159
158
  @app.route("/assets/<path:path>")
160
159
  def send_assets(path):
161
- return send_from_directory(os.path.join(self.webui_build_path, "assets"), path)
160
+ directory = (
161
+ os.path.join(self.app.template_folder, "assets")
162
+ if os.path.exists(os.path.join(app.template_folder, "assets", path))
163
+ else os.path.join(DEFAULT_BUILD_PATH, "assets")
164
+ )
165
+
166
+ return send_from_directory(directory, path)
162
167
 
163
168
  @app.route("/")
164
169
  @self.auth_required_if_enabled
@@ -499,7 +504,7 @@ class WebUI:
499
504
  if not self.web_login:
500
505
  return redirect(url_for("index"))
501
506
 
502
- return render_template(
507
+ return render_template_from(
503
508
  "auth.html",
504
509
  auth_args=self.auth_args,
505
510
  )
@@ -613,6 +618,8 @@ class WebUI:
613
618
  else None
614
619
  )
615
620
 
621
+ start_time = format_utc_timestamp(stats.start_time)
622
+
616
623
  self.template_args = {
617
624
  "locustfile": self.environment.locustfile,
618
625
  "state": self.environment.runner.state,
@@ -630,6 +637,7 @@ class WebUI:
630
637
  and not (self.userclass_picker_is_active or self.environment.shape_class.use_common_options)
631
638
  ),
632
639
  "stats_history_enabled": options and options.stats_history_enabled,
640
+ "start_time": start_time,
633
641
  "tasks": dumps({}),
634
642
  "extra_options": extra_options,
635
643
  "run_time": options and options.run_time,
@@ -5,7 +5,7 @@ build-backend = "poetry_dynamic_versioning.backend"
5
5
  [tool.poetry]
6
6
  name = "locust"
7
7
  description = "Developer-friendly load testing framework"
8
- version = "2.30.1.dev14"
8
+ version = "2.30.1.dev20"
9
9
  license = "MIT"
10
10
  readme = "README.md"
11
11
  authors = ["Jonatan Heyman", "Lars Holmberg"]
File without changes
File without changes