# Buggy code
def __init__(
    self,
    hook: "FrameworkHook",
    id: Union[int, str] = 0,
    data: Union[List, tuple] = None,
    is_client_worker: bool = False,
    log_msgs: bool = False,
    verbose: bool = False,
    auto_add: bool = True,
    message_pending_time: Union[int, float] = 0,
):
    """Initializes a BaseWorker."""
    super().__init__()
    self.hook = hook

    self.object_store = ObjectStore(owner=self)

    self.id = id
    self.is_client_worker = is_client_worker
    self.log_msgs = log_msgs
    self.verbose = verbose
    self.auto_add = auto_add
    self._message_pending_time = message_pending_time
    self.msg_history = list()

    # For performance, we cache all possible message types
    self._message_router = {
        TensorCommandMessage: self.execute_tensor_command,
        PlanCommandMessage: self.execute_plan_command,
        WorkerCommandMessage: self.execute_worker_command,
        ObjectMessage: self.handle_object_msg,
        ObjectRequestMessage: self.respond_to_obj_req,
        ForceObjectDeleteMessage: self.handle_delete_object_msg,  # FIXME: there is no ObjectDeleteMessage
        ForceObjectDeleteMessage: self.handle_force_delete_object_msg,
        IsNoneMessage: self.is_object_none,
        GetShapeMessage: self.handle_get_shape_message,
        SearchMessage: self.respond_to_search,
    }

    self._plan_command_router = {
        codes.PLAN_CMDS.FETCH_PLAN: self._fetch_plan_remote,
        codes.PLAN_CMDS.FETCH_PROTOCOL: self._fetch_protocol_remote,
    }

    self.load_data(data)

    # Declare workers as appropriate
    self._known_workers = {}
    if auto_add:
        if hook is not None and hook.local_worker is not None:
            known_workers = self.hook.local_worker._known_workers
            if self.id in known_workers:
                if isinstance(known_workers[self.id], type(self)):
                    # If a worker with this id already exists and it has the
                    # same type as the one being created, we copy all the attributes
                    # of the existing worker to this one.
                    self.__dict__.update(known_workers[self.id].__dict__)
                else:
                    raise RuntimeError(
                        "Worker initialized with the same id and different types."
                    )
            else:
                hook.local_worker.add_worker(self)
                for worker_id, worker in hook.local_worker._known_workers.items():
                    if worker_id not in self._known_workers:
                        self.add_worker(worker)
                    if self.id not in worker._known_workers:
                        worker.add_worker(self)
        else:
            # Make the local worker aware of itself
            # self is the to-be-created local worker
            self.add_worker(self)

    if hook is None:
        self.framework = None
    else:
        # TODO[jvmancuso]: avoid branching here if possible, maybe by changing code in
        #     execute_tensor_command or command_guard to not expect an attribute named "torch"
        #     (#2530)
        self.framework = hook.framework
        if hasattr(hook, "torch"):
            self.torch = self.framework
            self.remote = Remote(self, "torch")
        elif hasattr(hook, "tensorflow"):
            self.tensorflow = self.framework
            self.remote = Remote(self, "tensorflow")

    # storage object for crypto primitives
    self.crypto_store = PrimitiveStorage(owner=self)


# Traceback (AttributeError)
Traceback (most recent call last):
File "/home/juanmixp/Documentos/PySyft/fii.py", line 12, in <module>
y = (x @ x).get().float_prec()
File "/home/juanmixp/Documentos/PySyft/syft/generic/frameworks/hook/hook.py", line 466, in overloaded_native_method
response = method(*new_args, **new_kwargs)
File "/home/juanmixp/Documentos/PySyft/syft/frameworks/torch/tensors/interpreters/precision.py", line 432, in matmul
response = getattr(new_self, "matmul")(*new_args, **new_kwargs)
File "/home/juanmixp/Documentos/PySyft/syft/frameworks/torch/tensors/interpreters/additive_shared.py", line 646, in matmul
return self._private_mul(other, "matmul")
File "/home/juanmixp/Documentos/PySyft/syft/frameworks/torch/tensors/interpreters/additive_shared.py", line 536, in _private_mul
shares = spdz.spdz_mul(cmd, self, other, self.crypto_provider, self.field, self.dtype)
File "/home/juanmixp/Documentos/PySyft/syft/frameworks/torch/mpc/spdz.py", line 40, in spdz_mul
delta = delta.reconstruct()
File "/home/juanmixp/Documentos/PySyft/syft/frameworks/torch/tensors/interpreters/additive_shared.py", line 321, in reconstruct
pointer = ptr_to_sh.remote_get()
File "/home/juanmixp/Documentos/PySyft/syft/generic/pointers/pointer_tensor.py", line 304, in remote_get
self.owner.send_command(message=("mid_get", self, (), {}), recipient=self.location)
File "/home/juanmixp/Documentos/PySyft/syft/workers/base.py", line 637, in send_command
ret_val = self.send_msg(message, location=recipient)
File "/home/juanmixp/Documentos/PySyft/syft/workers/base.py", line 290, in send_msg
bin_response = self._send_msg(bin_message, location)
File "/home/juanmixp/Documentos/PySyft/syft/workers/virtual.py", line 15, in _send_msg
return location._recv_msg(message)
File "/home/juanmixp/Documentos/PySyft/syft/workers/virtual.py", line 19, in _recv_msg
return self.recv_msg(message)
File "/home/juanmixp/Documentos/PySyft/syft/workers/base.py", line 326, in recv_msg
response = self._message_router[type(msg)](msg)
File "/home/juanmixp/Documentos/PySyft/syft/workers/base.py", line 468, in execute_tensor_command
return self.execute_computation_action(cmd.action)
File "/home/juanmixp/Documentos/PySyft/syft/workers/base.py", line 510, in execute_computation_action
response = getattr(_self, op_name)(*args_, **kwargs_)
File "/home/juanmixp/Documentos/PySyft/syft/frameworks/torch/tensors/interpreters/native.py", line 604, in mid_get
self.child.mid_get()
File "/home/juanmixp/Documentos/PySyft/syft/generic/object.py", line 112, in mid_get
tensor = self.get()
File "/home/juanmixp/Documentos/PySyft/syft/frameworks/torch/tensors/interpreters/additive_shared.py", line 240, in get
shares.append(share.get())
File "/home/juanmixp/Documentos/PySyft/syft/generic/pointers/pointer_tensor.py", line 334, in get
tensor = ObjectPointer.get(self, user=user, reason=reason, deregister_ptr=deregister_ptr)
File "/home/juanmixp/Documentos/PySyft/syft/generic/pointers/object_pointer.py", line 269, in get
obj = self.owner.request_obj(self.id_at_location, self.location, user, reason)
File "/home/juanmixp/Documentos/PySyft/syft/workers/base.py", line 750, in request_obj
obj = self.send_msg(ObjectRequestMessage(obj_id, user, reason), location)
File "/home/juanmixp/Documentos/PySyft/syft/workers/base.py", line 284, in send_msg
print(f"worker {self} sending {message} to {location}")
File "/home/juanmixp/Documentos/PySyft/syft/messaging/message.py", line 303, in __str__
return f"({type(self).__name__} {(self.obj_id, self.user, self.reason)})"
AttributeError: 'ObjectRequestMessage' object has no attribute 'obj_id'

# Fixed code
def __init__(
    self,
    hook: "FrameworkHook",
    id: Union[int, str] = 0,
    data: Union[List, tuple] = None,
    is_client_worker: bool = False,
    log_msgs: bool = False,
    verbose: bool = None,
    auto_add: bool = True,
    message_pending_time: Union[int, float] = 0,
):
    """Initializes a BaseWorker."""
    super().__init__()
    self.hook = hook

    self.object_store = ObjectStore(owner=self)

    self.id = id
    self.is_client_worker = is_client_worker
    self.log_msgs = log_msgs
    if verbose is None:
        self.verbose = hook.verbose if hasattr(hook, "verbose") else False
    else:
        self.verbose = verbose

    if isinstance(hook, sy.TorchHook) and hasattr(hook, "_syft_workers"):
        hook._syft_workers.add(self)

    self.auto_add = auto_add
    self._message_pending_time = message_pending_time
    self.msg_history = list()

    # For performance, we cache all possible message types
    self._message_router = {
        TensorCommandMessage: self.execute_tensor_command,
        PlanCommandMessage: self.execute_plan_command,
        WorkerCommandMessage: self.execute_worker_command,
        ObjectMessage: self.handle_object_msg,
        ObjectRequestMessage: self.respond_to_obj_req,
        ForceObjectDeleteMessage: self.handle_delete_object_msg,  # FIXME: there is no ObjectDeleteMessage
        ForceObjectDeleteMessage: self.handle_force_delete_object_msg,
        IsNoneMessage: self.is_object_none,
        GetShapeMessage: self.handle_get_shape_message,
        SearchMessage: self.respond_to_search,
    }

    self._plan_command_router = {
        codes.PLAN_CMDS.FETCH_PLAN: self._fetch_plan_remote,
        codes.PLAN_CMDS.FETCH_PROTOCOL: self._fetch_protocol_remote,
    }

    self.load_data(data)

    # Declare workers as appropriate
    self._known_workers = {}
    if auto_add:
        if hook is not None and hook.local_worker is not None:
            known_workers = self.hook.local_worker._known_workers
            if self.id in known_workers:
                if isinstance(known_workers[self.id], type(self)):
                    # If a worker with this id already exists and it has the
                    # same type as the one being created, we copy all the attributes
                    # of the existing worker to this one.
                    self.__dict__.update(known_workers[self.id].__dict__)
                else:
                    raise RuntimeError(
                        "Worker initialized with the same id and different types."
                    )
            else:
                hook.local_worker.add_worker(self)
                for worker_id, worker in hook.local_worker._known_workers.items():
                    if worker_id not in self._known_workers:
                        self.add_worker(worker)
                    if self.id not in worker._known_workers:
                        worker.add_worker(self)
        else:
            # Make the local worker aware of itself
            # self is the to-be-created local worker
            self.add_worker(self)

    if hook is None:
        self.framework = None
    else:
        # TODO[jvmancuso]: avoid branching here if possible, maybe by changing code in
        #     execute_tensor_command or command_guard to not expect an attribute named "torch"
        #     (#2530)
        self.framework = hook.framework
        if hasattr(hook, "torch"):
            self.torch = self.framework
            self.remote = Remote(self, "torch")
        elif hasattr(hook, "tensorflow"):
            self.tensorflow = self.framework
            self.remote = Remote(self, "tensorflow")

    # storage object for crypto primitives
    self.crypto_store = PrimitiveStorage(owner=self)