locust 2.22.1.dev65__py3-none-any.whl → 2.23.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
locust/_version.py CHANGED
@@ -12,5 +12,5 @@ __version__: str
12
12
  __version_tuple__: VERSION_TUPLE
13
13
  version_tuple: VERSION_TUPLE
14
14
 
15
- __version__ = version = '2.22.1.dev65'
16
- __version_tuple__ = version_tuple = (2, 22, 1, 'dev65')
15
+ __version__ = version = '2.23.0'
16
+ __version_tuple__ = version_tuple = (2, 23, 0)
locust/argument_parser.py CHANGED
@@ -4,17 +4,20 @@ import locust
4
4
  from locust import runners
5
5
  from locust.rpc import Message, zmqrpc
6
6
 
7
+ import atexit
7
8
  import os
8
9
  import platform
9
10
  import socket
10
11
  import sys
12
+ import tempfile
11
13
  import textwrap
12
14
  from typing import Any, NamedTuple
15
+ from urllib.parse import urlparse
13
16
  from uuid import uuid4
14
17
 
15
18
  import configargparse
16
19
  import gevent
17
- from gevent.event import Event
20
+ import requests
18
21
 
19
22
  version = locust.__version__
20
23
 
@@ -66,7 +69,7 @@ def _is_package(path):
66
69
  return os.path.isdir(path) and os.path.exists(os.path.join(path, "__init__.py"))
67
70
 
68
71
 
69
- def find_locustfile(locustfile):
72
+ def find_locustfile(locustfile: str) -> str | None:
70
73
  """
71
74
  Attempt to locate a locustfile, either explicitly or by searching parent dirs.
72
75
  """
@@ -97,7 +100,8 @@ def find_locustfile(locustfile):
97
100
  # we've reached the root path which has been checked this iteration
98
101
  break
99
102
  path = parent_path
100
- # Implicit 'return None' if nothing was found
103
+
104
+ return None
101
105
 
102
106
 
103
107
  def find_locustfiles(locustfiles: list[str], is_directory: bool) -> list[str]:
@@ -141,6 +145,34 @@ def find_locustfiles(locustfiles: list[str], is_directory: bool) -> list[str]:
141
145
  return file_paths
142
146
 
143
147
 
148
+ def is_url(url: str) -> bool:
149
+ try:
150
+ result = urlparse(url)
151
+ if result.scheme == "https" or result.scheme == "http":
152
+ return True
153
+ else:
154
+ return False
155
+ except ValueError:
156
+ return False
157
+
158
+
159
+ def download_file_from_url(url: str) -> str:
160
+ try:
161
+ response = requests.get(url)
162
+ except requests.exceptions.RequestException as e:
163
+ sys.stderr.write(f"Failed to get locustfile from: {url}. Exception: {e}")
164
+ sys.exit(1)
165
+
166
+ with open(os.path.join(tempfile.gettempdir(), url.rsplit("/", 1)[-1]), "w") as locustfile:
167
+ locustfile.write(response.text)
168
+
169
+ def exit_handler():
170
+ os.remove(locustfile.name)
171
+
172
+ atexit.register(exit_handler)
173
+ return locustfile.name
174
+
175
+
144
176
  def get_empty_argument_parser(add_help=True, default_config_files=DEFAULT_CONFIG_FILES) -> LocustArgumentParser:
145
177
  parser = LocustArgumentParser(
146
178
  default_config_files=default_config_files,
@@ -279,7 +311,9 @@ def parse_locustfile_option(args=None) -> list[str]:
279
311
  return [filename]
280
312
 
281
313
  # Comma separated string to list
282
- locustfile_as_list = [locustfile.strip() for locustfile in options.locustfile.split(",")]
314
+ locustfile_as_list = [
315
+ download_file_from_url(f) if is_url(f.strip()) else f.strip() for f in options.locustfile.split(",")
316
+ ]
283
317
 
284
318
  # Checking if the locustfile is a single file, multiple files or a directory
285
319
  if locustfile_is_directory(locustfile_as_list):
@@ -298,8 +332,8 @@ def parse_locustfile_option(args=None) -> list[str]:
298
332
  locustfile = None
299
333
  else:
300
334
  # Is a single file
301
- locustfile = find_locustfile(options.locustfile)
302
- locustfiles = [locustfile]
335
+ locustfile = find_locustfile(locustfile_as_list[0])
336
+ locustfiles = []
303
337
 
304
338
  if not locustfile:
305
339
  if options.help or options.version:
@@ -317,6 +351,8 @@ def parse_locustfile_option(args=None) -> list[str]:
317
351
  f"Could not find '{user_friendly_locustfile_name}'. {note_about_file_endings}See --help for available options.\n"
318
352
  )
319
353
  sys.exit(1)
354
+ else:
355
+ locustfiles.append(locustfile)
320
356
 
321
357
  return locustfiles
322
358
 
@@ -1,10 +1,12 @@
1
1
  from locust import main
2
- from locust.argument_parser import parse_options
2
+ from locust.argument_parser import parse_locustfile_option, parse_options
3
3
  from locust.main import create_environment
4
4
  from locust.user import HttpUser, TaskSet, User
5
5
  from locust.util.load_locustfile import is_user_class
6
6
 
7
+ import filecmp
7
8
  import os
9
+ import pathlib
8
10
  import textwrap
9
11
 
10
12
  from .mock_locustfile import MOCK_LOCUSTFILE_CONTENT, mock_locustfile
@@ -209,3 +211,18 @@ class TestLoadLocustfile(LocustTestCase):
209
211
  ]
210
212
  )
211
213
  self.assertEqual("my_locust_file.py", options.locustfile)
214
+
215
+ def test_locustfile_from_url(self):
216
+ locustfiles = parse_locustfile_option(
217
+ args=[
218
+ "-f",
219
+ "https://raw.githubusercontent.com/locustio/locust/master/examples/basic.py",
220
+ ]
221
+ )
222
+ self.assertEqual(len(locustfiles), 1)
223
+ self.assertTrue(
224
+ filecmp.cmp(
225
+ locustfiles[0],
226
+ f"{os.getcwd()}/examples/basic.py",
227
+ )
228
+ )