locust 2.19.2.dev35__py3-none-any.whl → 2.19.2.dev47__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.19.2.dev35'
16
- __version_tuple__ = version_tuple = (2, 19, 2, 'dev35')
15
+ __version__ = version = '2.19.2.dev47'
16
+ __version_tuple__ = version_tuple = (2, 19, 2, 'dev47')
locust/rpc/protocol.py CHANGED
@@ -1,4 +1,30 @@
1
1
  import msgpack
2
+ import datetime
3
+ from typing import Type
4
+
5
+ try:
6
+ from bson import ObjectId # type: ignore
7
+ except ImportError:
8
+
9
+ class ObjectId: # type: ignore
10
+ def __init__(self, s):
11
+ raise Exception("You need to install pymongo or at least bson to be able to send/receive ObjectIds")
12
+
13
+
14
+ def decode(obj):
15
+ if "__datetime__" in obj:
16
+ obj = datetime.datetime.strptime(obj["as_str"], "%Y%m%dT%H:%M:%S.%f")
17
+ elif "__ObjectId__" in obj:
18
+ obj = ObjectId(obj["as_str"])
19
+ return obj
20
+
21
+
22
+ def encode(obj):
23
+ if isinstance(obj, datetime.datetime):
24
+ return {"__datetime__": True, "as_str": obj.strftime("%Y%m%dT%H:%M:%S.%f")}
25
+ elif isinstance(obj, ObjectId):
26
+ return {"__ObjectId__": True, "as_str": str(obj)}
27
+ return obj
2
28
 
3
29
 
4
30
  class Message:
@@ -11,9 +37,9 @@ class Message:
11
37
  return f"<Message {self.type}:{self.node_id}>"
12
38
 
13
39
  def serialize(self):
14
- return msgpack.dumps((self.type, self.data, self.node_id))
40
+ return msgpack.dumps((self.type, self.data, self.node_id), default=encode)
15
41
 
16
42
  @classmethod
17
43
  def unserialize(cls, data):
18
- msg = cls(*msgpack.loads(data, raw=False, strict_map_key=False))
44
+ msg = cls(*msgpack.loads(data, raw=False, strict_map_key=False, object_hook=decode))
19
45
  return msg
locust/runners.py CHANGED
@@ -37,6 +37,7 @@ import greenlet
37
37
  import psutil
38
38
  from gevent.event import Event
39
39
  from gevent.pool import Group
40
+ import inspect
40
41
 
41
42
  from . import User
42
43
  from locust import __version__
@@ -380,7 +381,11 @@ class Runner:
380
381
  """
381
382
  if self.state == STATE_STOPPED:
382
383
  return
383
- logger.debug("Stopping all users")
384
+ try:
385
+ caller = inspect.getframeinfo(inspect.stack()[1][0])
386
+ logger.debug(f"Stopping all users (called from {caller.filename}:{caller.lineno})")
387
+ except Exception:
388
+ logger.debug("Stopping all users (couldnt determine where stop() was called from)")
384
389
  self.environment.events.test_stopping.fire(environment=self.environment)
385
390
  self.final_user_classes_count = {**self.user_classes_count}
386
391
  self.update_state(STATE_CLEANUP)
@@ -1104,7 +1109,11 @@ class MasterRunner(DistributedRunner):
1104
1109
  logger.debug(
1105
1110
  f"Received {msg.type} message from worker {msg.node_id} (index {self.get_worker_index(msg.node_id)})"
1106
1111
  )
1107
- self.custom_messages[msg.type](environment=self.environment, msg=msg)
1112
+ try:
1113
+ self.custom_messages[msg.type](environment=self.environment, msg=msg)
1114
+ except Exception:
1115
+ logging.error(f"Uncaught exception in handler for {msg.type}\n{traceback.format_exc()}")
1116
+
1108
1117
  else:
1109
1118
  logger.warning(
1110
1119
  f"Unknown message type received from worker {msg.node_id} (index {self.get_worker_index(msg.node_id)}): {msg.type}"
locust/web.py CHANGED
@@ -227,8 +227,14 @@ class WebUI:
227
227
  return jsonify({"success": False, "message": err_msg, "host": environment.host})
228
228
  elif key in parsed_options_dict:
229
229
  # update the value in environment.parsed_options, but dont change the type.
230
- # This won't work for parameters that are None
231
- parsed_options_dict[key] = type(parsed_options_dict[key])(value)
230
+ parsed_options_value = parsed_options_dict[key]
231
+
232
+ if isinstance(parsed_options_value, bool):
233
+ parsed_options_dict[key] = value == "true"
234
+ elif parsed_options_value is None:
235
+ parsed_options_dict[key] = parsed_options_value
236
+ else:
237
+ parsed_options_dict[key] = type(parsed_options_dict[key])(value)
232
238
 
233
239
  if environment.shape_class and environment.runner is not None:
234
240
  environment.runner.start_shape()