locust-cloud 1.20.8.dev2__tar.gz → 1.20.8.dev3__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 (33) hide show
  1. {locust_cloud-1.20.8.dev2 → locust_cloud-1.20.8.dev3}/.github/workflows/daily-check.yml +3 -1
  2. {locust_cloud-1.20.8.dev2 → locust_cloud-1.20.8.dev3}/PKG-INFO +1 -1
  3. {locust_cloud-1.20.8.dev2 → locust_cloud-1.20.8.dev3}/locust_cloud/args.py +43 -1
  4. {locust_cloud-1.20.8.dev2 → locust_cloud-1.20.8.dev3}/locustfile.py +6 -1
  5. locust_cloud-1.20.8.dev3/testdata/extra-package/example/__init__.py +2 -0
  6. locust_cloud-1.20.8.dev3/testdata/extra-package/setup.py +8 -0
  7. {locust_cloud-1.20.8.dev2 → locust_cloud-1.20.8.dev3}/tests/args_test.py +8 -8
  8. {locust_cloud-1.20.8.dev2 → locust_cloud-1.20.8.dev3}/.github/workflows/tests.yml +0 -0
  9. {locust_cloud-1.20.8.dev2 → locust_cloud-1.20.8.dev3}/.gitignore +0 -0
  10. {locust_cloud-1.20.8.dev2 → locust_cloud-1.20.8.dev3}/.pre-commit-config.yaml +0 -0
  11. {locust_cloud-1.20.8.dev2 → locust_cloud-1.20.8.dev3}/.vscode/extensions.json +0 -0
  12. {locust_cloud-1.20.8.dev2 → locust_cloud-1.20.8.dev3}/.vscode/launch.json +0 -0
  13. {locust_cloud-1.20.8.dev2 → locust_cloud-1.20.8.dev3}/.vscode/settings.json +0 -0
  14. {locust_cloud-1.20.8.dev2 → locust_cloud-1.20.8.dev3}/LICENSE +0 -0
  15. {locust_cloud-1.20.8.dev2 → locust_cloud-1.20.8.dev3}/README.md +0 -0
  16. {locust_cloud-1.20.8.dev2 → locust_cloud-1.20.8.dev3}/locust_cloud/__init__.py +0 -0
  17. {locust_cloud-1.20.8.dev2 → locust_cloud-1.20.8.dev3}/locust_cloud/apisession.py +0 -0
  18. {locust_cloud-1.20.8.dev2 → locust_cloud-1.20.8.dev3}/locust_cloud/cloud.py +0 -0
  19. {locust_cloud-1.20.8.dev2 → locust_cloud-1.20.8.dev3}/locust_cloud/common.py +0 -0
  20. {locust_cloud-1.20.8.dev2 → locust_cloud-1.20.8.dev3}/locust_cloud/docs/.gitignore +0 -0
  21. {locust_cloud-1.20.8.dev2 → locust_cloud-1.20.8.dev3}/locust_cloud/docs/1-first-run.rst +0 -0
  22. {locust_cloud-1.20.8.dev2 → locust_cloud-1.20.8.dev3}/locust_cloud/docs/2-examples.rst +0 -0
  23. {locust_cloud-1.20.8.dev2 → locust_cloud-1.20.8.dev3}/locust_cloud/docs/images/locust-cloud-screenshot.png +0 -0
  24. {locust_cloud-1.20.8.dev2 → locust_cloud-1.20.8.dev3}/locust_cloud/docs/locust-cloud.rst +0 -0
  25. {locust_cloud-1.20.8.dev2 → locust_cloud-1.20.8.dev3}/locust_cloud/input_events.py +0 -0
  26. {locust_cloud-1.20.8.dev2 → locust_cloud-1.20.8.dev3}/locust_cloud/web_login.py +0 -0
  27. {locust_cloud-1.20.8.dev2 → locust_cloud-1.20.8.dev3}/locust_cloud/websocket.py +0 -0
  28. {locust_cloud-1.20.8.dev2 → locust_cloud-1.20.8.dev3}/pyproject.toml +0 -0
  29. {locust_cloud-1.20.8.dev2/testdata → locust_cloud-1.20.8.dev3/testdata/extra-files}/extra.txt +0 -0
  30. {locust_cloud-1.20.8.dev2 → locust_cloud-1.20.8.dev3}/tests/cloud_test.py +0 -0
  31. {locust_cloud-1.20.8.dev2 → locust_cloud-1.20.8.dev3}/tests/web_login_test.py +0 -0
  32. {locust_cloud-1.20.8.dev2 → locust_cloud-1.20.8.dev3}/tests/websocket_test.py +0 -0
  33. {locust_cloud-1.20.8.dev2 → locust_cloud-1.20.8.dev3}/uv.lock +0 -0
@@ -35,11 +35,13 @@ jobs:
35
35
  # any local changes would make hatch-vcs set a "local version" (+dev0...), so we ignore any uv.lock updates:
36
36
  - run: git update-index --assume-unchanged uv.lock
37
37
  - run: uv run locust-cloud --help
38
- - run: uv run locust-cloud --image-tag master --profile status-checker --mock-server --autostart --autoquit 0 --run-time 1m --loglevel DEBUG --extra-files testdata |& tee output.txt
38
+ - run: uv run locust-cloud --image-tag master --profile status-checker --mock-server --autostart --autoquit 0 --run-time 1m --loglevel DEBUG --extra-files testdata/extra-files --extra-packages testdata/extra-package |& tee output.txt
39
39
  # check ok exit
40
40
  - run: grep -m 1 '(exit code 0)' output.txt
41
41
  # check extra files specified were available
42
42
  - run: "grep -m 1 -- '--extra-files verification: pineapple' output.txt"
43
+ # check extra package were successfully installed
44
+ - run: "grep -m 1 -- 'Hello from the example package!' output.txt"
43
45
  # check for errors
44
46
  - run: bash -ec "! grep Traceback output.txt"
45
47
  - run: bash -ec "! grep ERROR output.txt"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: locust-cloud
3
- Version: 1.20.8.dev2
3
+ Version: 1.20.8.dev3
4
4
  Summary: Locust Cloud
5
5
  Project-URL: homepage, https://locust.cloud
6
6
  Project-URL: repository, https://github.com/locustcloud/locust-cloud
@@ -4,7 +4,9 @@ import gzip
4
4
  import io
5
5
  import os
6
6
  import pathlib
7
+ import shutil
7
8
  import sys
9
+ import tempfile
8
10
 
9
11
  if sys.version_info >= (3, 11):
10
12
  import tomllib
@@ -113,6 +115,39 @@ def transfer_encoded_args_files(paths: list[pathlib.Path], to_file: str | None)
113
115
  return transfer_encode(f"{to_file}.zip", buffer)
114
116
 
115
117
 
118
+ def flat_transfer_encoded_args_files(paths: list[pathlib.Path], to_file: str | None) -> dict[str, str]:
119
+ buffer = io.BytesIO()
120
+
121
+ with tempfile.TemporaryDirectory() as tmpdir:
122
+ tmp_path = pathlib.Path(tmpdir)
123
+
124
+ for src in paths:
125
+ src_path = pathlib.Path(src)
126
+ dest_path = tmp_path / src_path.name
127
+
128
+ if src_path.is_file():
129
+ shutil.copy(src_path, dest_path)
130
+ elif src_path.is_dir():
131
+ shutil.copytree(src_path, dest_path)
132
+ else:
133
+ print(f"Warning: {src} is not a valid file or directory")
134
+
135
+ # Create the zip archive
136
+ with ZipFile(buffer, "w") as zf:
137
+ for item in tmp_path.iterdir():
138
+ if item.is_file():
139
+ zf.write(item, arcname=item.name)
140
+ elif item.is_dir():
141
+ for root, _, files in os.walk(item):
142
+ for file in files:
143
+ file_path = pathlib.Path(root) / file
144
+ arcname = file_path.relative_to(tmp_path)
145
+ zf.write(file_path, arcname)
146
+
147
+ buffer.seek(0)
148
+ return transfer_encode(f"{to_file}.zip", buffer)
149
+
150
+
116
151
  class MergeToTransferEncodedZip(argparse.Action):
117
152
  def __call__(self, parser, namespace, values, option_string=None):
118
153
  paths = cast(list[pathlib.Path], values)
@@ -120,6 +155,13 @@ class MergeToTransferEncodedZip(argparse.Action):
120
155
  setattr(namespace, self.dest, value)
121
156
 
122
157
 
158
+ class MergeToTransferEncodedZipFlat(MergeToTransferEncodedZip):
159
+ def __call__(self, parser, namespace, values, option_string=None):
160
+ paths = cast(list[pathlib.Path], values)
161
+ value = flat_transfer_encoded_args_files(paths, option_string.lstrip("-"))
162
+ setattr(namespace, self.dest, value)
163
+
164
+
123
165
  cloud_parser = configargparse.ArgumentParser(add_help=False)
124
166
  cloud_parser.add_argument(
125
167
  "--login",
@@ -176,7 +218,7 @@ cloud_parser.add_argument(
176
218
  )
177
219
  cloud_parser.add_argument(
178
220
  "--extra-packages",
179
- action=MergeToTransferEncodedZip,
221
+ action=MergeToTransferEncodedZipFlat,
180
222
  nargs="*",
181
223
  type=valid_extra_packages_path,
182
224
  help="A list of extra packages to upload. Space-separated whl/tar.gz files or directory packages to be installed when running locust.",
@@ -23,10 +23,15 @@ class MyUser(FastHttpUser):
23
23
  resp.failure("orderId missing")
24
24
 
25
25
 
26
- extra = pathlib.Path("testdata/extra.txt")
26
+ extra = pathlib.Path("testdata/extra-files/extra.txt")
27
27
  if extra.exists():
28
28
  print("--extra-files verification:", extra.read_text())
29
29
 
30
30
 
31
+ import example # type: ignore
32
+
33
+ example.hello()
34
+
35
+
31
36
  if __name__ == "__main__":
32
37
  run_single_user(MyUser)
@@ -0,0 +1,2 @@
1
+ def hello():
2
+ print("Hello from the example package!")
@@ -0,0 +1,8 @@
1
+ from setuptools import find_packages, setup
2
+
3
+ setup(
4
+ name="example",
5
+ version="0.1",
6
+ packages=find_packages(),
7
+ install_requires=[],
8
+ )
@@ -59,12 +59,12 @@ def test_transfer_encoded_file():
59
59
 
60
60
 
61
61
  def test_expanded():
62
- result = list(expanded([pathlib.Path("locustfile.py"), pathlib.Path("testdata")]))
63
- assert result == [pathlib.Path("locustfile.py"), pathlib.Path("testdata/extra.txt")]
62
+ result = list(expanded([pathlib.Path("locustfile.py"), pathlib.Path("testdata/extra-files")]))
63
+ assert result == [pathlib.Path("locustfile.py"), pathlib.Path("testdata/extra-files/extra.txt")]
64
64
 
65
65
 
66
66
  def test_transfer_encoded_args_files():
67
- result = transfer_encoded_args_files([pathlib.Path("testdata").resolve()], "extra-files")
67
+ result = transfer_encoded_args_files([pathlib.Path("testdata/extra-files").resolve()], "extra-files")
68
68
  assert result["filename"] == "extra-files.zip"
69
69
 
70
70
  buffer = pipe(
@@ -76,7 +76,7 @@ def test_transfer_encoded_args_files():
76
76
  )
77
77
 
78
78
  with ZipFile(buffer) as zf:
79
- assert zf.namelist() == ["testdata/extra.txt"]
79
+ assert zf.namelist() == ["testdata/extra-files/extra.txt"]
80
80
 
81
81
 
82
82
  def test_parser_locustfile(capsys):
@@ -86,8 +86,8 @@ def test_parser_locustfile(capsys):
86
86
  expected = "error: argument -f/--locustfile: File not found: does-not-exist"
87
87
  assert expected in capsys.readouterr().err
88
88
 
89
- options, _ = combined_cloud_parser.parse_known_args("locust-cloud --locustfile testdata/extra.txt")
90
- assert options.locustfile == transfer_encoded_file("testdata/extra.txt")
89
+ options, _ = combined_cloud_parser.parse_known_args("locust-cloud --locustfile testdata/extra-files/extra.txt")
90
+ assert options.locustfile == transfer_encoded_file("testdata/extra-files/extra.txt")
91
91
 
92
92
 
93
93
  def test_parser_extra_files(capsys):
@@ -103,7 +103,7 @@ def test_parser_extra_files(capsys):
103
103
  expected = "error: argument --extra-files: File not found: does-not-exist"
104
104
  assert expected in capsys.readouterr().err
105
105
 
106
- options, _ = combined_cloud_parser.parse_known_args("locust-cloud --extra-files testdata")
106
+ options, _ = combined_cloud_parser.parse_known_args("locust-cloud --extra-files testdata/extra-files")
107
107
  assert options.extra_files["filename"] == "extra-files.zip"
108
108
  buffer = pipe(
109
109
  options.extra_files["data"],
@@ -114,7 +114,7 @@ def test_parser_extra_files(capsys):
114
114
  )
115
115
 
116
116
  with ZipFile(buffer) as zf:
117
- assert zf.namelist() == ["testdata/extra.txt"]
117
+ assert zf.namelist() == ["testdata/extra-files/extra.txt"]
118
118
 
119
119
 
120
120
  def test_parser_loglevel(capsys):