We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Cosmetic space to add for TensorsNotCollocatedException
**Describe the bug**
Cosmetic spacing, just 1, missing for TensorsNotCollocatedException

**To Reproduce**
1. initiate two tensors, one send to remote worker, one locate
2. add two tensors
2. get TensorsNotCollocatedException

```
bob = sy.VirtualWorker(hook, id="bob")
x = torch.tensor([1,2,3,4,5]).send(bob)
y = torch.tensor([1,1,1,1,1])
z = x+y
```

**Expected behavior**
" involving two tensors where one tensor is actually locatedon another machine (is a PointerTensor). Call .get() on the PointerTensor or .send("

becomes 
" involving two tensors where one tensor is actually located on another machine (is a PointerTensor). Call .get() on the PointerTensor or .send("

`locatedon` becomes `located on`


**Screenshots**
[screenshot of error message](https://github.com/theoptips/udacity_project_submission/blob/master/Screen%20Shot%202019-06-28%20at%202.50.34%20PM.png)



[exception.py with proposed change](https://github.com/theoptips/PySyft/blob/dev/syft/exceptions.py)
[commit message with proposed change explained](https://github.com/theoptips/PySyft/commit/533da84afa6ac4071a58754e97c21ce1ca7056aa)
[exception.py changed line highlighted](https://github.com/theoptips/PySyft/commit/4b68c3c6fbe0c18cdf87dfe6ddc3c2071a71f1cc)

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `syft/exceptions.py`
Content:
```
1 """Specific Pysyft exceptions."""
2 
3 import syft as sy
4 import torch
5 from tblib import Traceback
6 import traceback
7 from six import reraise
8 from typing import Tuple
9 
10 
11 class PureTorchTensorFoundError(BaseException):
12     """Exception raised for errors in the input.
13     This error is used in a recursive analysis of the args provided as an
14     input of a function, to break the recursion if a TorchTensor is found
15     as it means that _probably_ all the tensors are pure torch tensor and
16     the function can be applied natively on this input.
17 
18     Attributes:
19         expression -- input expression in which the error occurred
20         message -- explanation of the error
21     """
22 
23     pass
24 
25 
26 class RemoteObjectFoundError(BaseException):
27     """Exception raised for errors in the input.
28     This error is used in a context similar to PureTorchTensorFoundError but
29     to indicate that a Pointer to a remote tensor was found  in the input
30     and thus that the command should be send elsewhere. The pointer retrieved
31     by the error gives the location where the command should be sent.
32 
33     Attributes:
34         expression -- input expression in which the error occurred
35         message -- explanation of the error
36     """
37 
38     def __init__(self, pointer):
39         self.pointer = pointer
40 
41 
42 class InvalidTensorForRemoteGet(Exception):
43     """Raised when a chain of pointer tensors is not provided for `remote_get`."""
44 
45     def __init__(self, tensor: object):
46         message = "Tensor does not have attribute child. You remote get should be called on a chain of pointer tensors, instead you called it on {}.".format(
47             tensor
48         )
49         super().__init__(message)
50 
51 
52 class WorkerNotFoundException(Exception):
53     """Raised when a non-existent worker is requested."""
54 
55     pass
56 
57 
58 class CompressionNotFoundException(Exception):
59     """Raised when a non existent compression/decompression scheme is requested."""
60 
61     pass
62 
63 
64 class CannotRequestObjectAttribute(Exception):
65     """Raised when .get() is called on a pointer which points to an attribute of
66     another object."""
67 
68     pass
69 
70 
71 class TensorsNotCollocatedException(Exception):
72     """Raised when a command is executed on two tensors which are not
73     on the same machine. The goal is to provide as useful input as possible
74     to help the user identify which tensors are where so that they can debug
75     which one needs to be moved."""
76 
77     def __init__(self, tensor_a, tensor_b, attr="a method"):
78 
79         if hasattr(tensor_a, "child") and tensor_a.is_wrapper:
80             tensor_a = tensor_a.child
81 
82         if hasattr(tensor_b, "child") and tensor_b.is_wrapper:
83             tensor_b = tensor_b.child
84 
85         if isinstance(tensor_a, sy.PointerTensor) and isinstance(tensor_b, sy.PointerTensor):
86             message = (
87                 "You tried to call "
88                 + attr
89                 + " involving two tensors which "
90                 + "are not on the same machine! One tensor is on "
91                 + str(tensor_a.location)
92                 + " while the other is on "
93                 + str(tensor_b.location)
94                 + ". Use a combination of .move(), .get(), and/or .send() to co-locate them to the same machine."
95             )
96         elif isinstance(tensor_a, sy.PointerTensor):
97             message = (
98                 "You tried to call "
99                 + attr
100                 + " involving two tensors where one tensor is actually located"
101                 + "on another machine (is a PointerTensor). Call .get() on the PointerTensor or .send("
102                 + str(tensor_a.location.id)
103                 + ") on the other tensor.\n"
104                 + "\nTensor A: "
105                 + str(tensor_a)
106                 + "\nTensor B: "
107                 + str(tensor_b)
108             )
109         elif isinstance(tensor_b, sy.PointerTensor):
110             message = (
111                 "You tried to call "
112                 + attr
113                 + " involving two tensors where one tensor is actually located"
114                 + "on another machine (is a PointerTensor). Call .get() on the PointerTensor or .send("
115                 + str(tensor_b.location.id)
116                 + ") on the other tensor.\n"
117                 + "\nTensor A: "
118                 + str(tensor_a)
119                 + "\nTensor B: "
120                 + str(tensor_b)
121             )
122         else:
123             message = (
124                 "You tried to call "
125                 + attr
126                 + " involving two tensors which are not on the same machine."
127                 + "Try calling .send(), .move(), and/or .get() on these tensors to get them to the same"
128                 + "worker before calling methods that involve them working together."
129             )
130 
131         super().__init__(message)
132 
133         self.tensor_a = tensor_a
134         self.tensor_b = tensor_b
135 
136 
137 class ResponseSignatureError(Exception):
138     """Raised when the return of a hooked function is not correctly predicted
139     (when defining in advance ids for results)"""
140 
141     def __init__(self, ids_generated=None):
142         self.ids_generated = ids_generated
143 
144     def get_attributes(self):
145         """
146         Specify all the attributes need to report an error correctly.
147         """
148         return {"ids_generated": self.ids_generated}
149 
150     @staticmethod
151     def simplify(e):
152         """
153         Serialize information about an Exception which was raised to forward it
154         """
155         # Get information about the exception: type of error,  traceback
156         tp = type(e)
157         tb = e.__traceback__
158         # Serialize the traceback
159         traceback_str = "Traceback (most recent call last):\n" + "".join(traceback.format_tb(tb))
160         # Include special attributes if relevant
161         try:
162             attributes = e.get_attributes()
163         except AttributeError:
164             attributes = {}
165         return tp.__name__, traceback_str, sy.serde._simplify(attributes)
166 
167     @staticmethod
168     def detail(worker: "sy.workers.AbstractWorker", error_tuple: Tuple[str, str, dict]):
169         """
170         Detail and re-raise an Exception forwarded by another worker
171         """
172         error_name, traceback_str, attributes = error_tuple
173         error_name, traceback_str = error_name.decode("utf-8"), traceback_str.decode("utf-8")
174         attributes = sy.serde._detail(worker, attributes)
175         # De-serialize the traceback
176         tb = Traceback.from_string(traceback_str)
177         # Check that the error belongs to a valid set of Exceptions
178         if error_name in dir(sy.exceptions):
179             error_type = getattr(sy.exceptions, error_name)
180             error = error_type()
181             # Include special attributes if any
182             for attr_name, attr in attributes.items():
183                 setattr(error, attr_name, attr)
184             reraise(error_type, error, tb.as_traceback())
185         else:
186             raise ValueError(f"Invalid Exception returned:\n{traceback_str}")
187 
188 
189 class GetNotPermittedError(Exception):
190     """Raised when calling get on a pointer to a tensor which does not allow
191     get to be called on it. This can happen do to sensitivity being too high"""
192 
193     @staticmethod
194     def simplify(e):
195         """
196         Serialize information about an Exception which was raised to forward it
197         """
198         # Get information about the exception: type of error,  traceback
199         tp = type(e)
200         tb = e.__traceback__
201         # Serialize the traceback
202         traceback_str = "Traceback (most recent call last):\n" + "".join(traceback.format_tb(tb))
203         # Include special attributes if relevant
204         try:
205             attributes = e.get_attributes()
206         except AttributeError:
207             attributes = {}
208         return tp.__name__, traceback_str, sy.serde._simplify(attributes)
209 
210     @staticmethod
211     def detail(worker: "sy.workers.AbstractWorker", error_tuple: Tuple[str, str, dict]):
212         """
213         Detail and re-raise an Exception forwarded by another worker
214         """
215         error_name, traceback_str, attributes = error_tuple
216         error_name, traceback_str = error_name.decode("utf-8"), traceback_str.decode("utf-8")
217         attributes = sy.serde._detail(worker, attributes)
218         # De-serialize the traceback
219         tb = Traceback.from_string(traceback_str)
220         # Check that the error belongs to a valid set of Exceptions
221         if error_name in dir(sy.exceptions):
222             error_type = getattr(sy.exceptions, error_name)
223             error = error_type()
224             # Include special attributes if any
225             for attr_name, attr in attributes.items():
226                 setattr(error, attr_name, attr)
227             reraise(error_type, error, tb.as_traceback())
228         else:
229             raise ValueError(f"Invalid Exception returned:\n{traceback_str}")
230 
231 
232 class IdNotUniqueError(Exception):
233     """Raised by the ID Provider when setting ids that have already been generated"""
234 
235     pass
236 
237 
238 def route_method_exception(exception, self, args, kwargs):
239     try:
240         if self.is_wrapper:
241             if isinstance(self.child, sy.PointerTensor):
242                 if len(args) > 0:
243                     if not args[0].is_wrapper:
244                         return TensorsNotCollocatedException(self, args[0])
245                     elif isinstance(args[0].child, sy.PointerTensor):
246                         if self.location != args[0].child.location:
247                             return TensorsNotCollocatedException(self, args[0])
248 
249         # if self is a normal tensor
250         elif isinstance(self, torch.Tensor):
251             if len(args) > 0:
252                 if args[0].is_wrapper:
253                     if isinstance(args[0].child, sy.PointerTensor):
254                         return TensorsNotCollocatedException(self, args[0])
255                 elif isinstance(args[0], sy.PointerTensor):
256                     return TensorsNotCollocatedException(self, args[0])
257     except:
258         ""
259     return exception
260
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/syft/exceptions.py b/syft/exceptions.py
--- a/syft/exceptions.py
+++ b/syft/exceptions.py
@@ -86,8 +86,8 @@
             message = (
                 "You tried to call "
                 + attr
-                + " involving two tensors which "
-                + "are not on the same machine! One tensor is on "
+                + " involving two tensors which"
+                + " are not on the same machine! One tensor is on "
                 + str(tensor_a.location)
                 + " while the other is on "
                 + str(tensor_b.location)
@@ -98,7 +98,7 @@
                 "You tried to call "
                 + attr
                 + " involving two tensors where one tensor is actually located"
-                + "on another machine (is a PointerTensor). Call .get() on the PointerTensor or .send("
+                + " on another machine (is a PointerTensor). Call .get() on the PointerTensor or .send("
                 + str(tensor_a.location.id)
                 + ") on the other tensor.\n"
                 + "\nTensor A: "
@@ -111,7 +111,7 @@
                 "You tried to call "
                 + attr
                 + " involving two tensors where one tensor is actually located"
-                + "on another machine (is a PointerTensor). Call .get() on the PointerTensor or .send("
+                + " on another machine (is a PointerTensor). Call .get() on the PointerTensor or .send("
                 + str(tensor_b.location.id)
                 + ") on the other tensor.\n"
                 + "\nTensor A: "

{"golden_diff": "diff --git a/syft/exceptions.py b/syft/exceptions.py\n--- a/syft/exceptions.py\n+++ b/syft/exceptions.py\n@@ -86,8 +86,8 @@\n             message = (\n                 \"You tried to call \"\n                 + attr\n-                + \" involving two tensors which \"\n-                + \"are not on the same machine! One tensor is on \"\n+                + \" involving two tensors which\"\n+                + \" are not on the same machine! One tensor is on \"\n                 + str(tensor_a.location)\n                 + \" while the other is on \"\n                 + str(tensor_b.location)\n@@ -98,7 +98,7 @@\n                 \"You tried to call \"\n                 + attr\n                 + \" involving two tensors where one tensor is actually located\"\n-                + \"on another machine (is a PointerTensor). Call .get() on the PointerTensor or .send(\"\n+                + \" on another machine (is a PointerTensor). Call .get() on the PointerTensor or .send(\"\n                 + str(tensor_a.location.id)\n                 + \") on the other tensor.\\n\"\n                 + \"\\nTensor A: \"\n@@ -111,7 +111,7 @@\n                 \"You tried to call \"\n                 + attr\n                 + \" involving two tensors where one tensor is actually located\"\n-                + \"on another machine (is a PointerTensor). Call .get() on the PointerTensor or .send(\"\n+                + \" on another machine (is a PointerTensor). Call .get() on the PointerTensor or .send(\"\n                 + str(tensor_b.location.id)\n                 + \") on the other tensor.\\n\"\n                 + \"\\nTensor A: \"\n", "issue": "Cosmetic space to add for TensorsNotCollocatedException\n**Describe the bug**\r\nCosmetic spacing, just 1, missing for TensorsNotCollocatedException\r\n\r\n**To Reproduce**\r\n1. initiate two tensors, one send to remote worker, one locate\r\n2. add two tensors\r\n2. get TensorsNotCollocatedException\r\n\r\n```\r\nbob = sy.VirtualWorker(hook, id=\"bob\")\r\nx = torch.tensor([1,2,3,4,5]).send(bob)\r\ny = torch.tensor([1,1,1,1,1])\r\nz = x+y\r\n```\r\n\r\n**Expected behavior**\r\n\" involving two tensors where one tensor is actually locatedon another machine (is a PointerTensor). Call .get() on the PointerTensor or .send(\"\r\n\r\nbecomes \r\n\" involving two tensors where one tensor is actually located on another machine (is a PointerTensor). Call .get() on the PointerTensor or .send(\"\r\n\r\n`locatedon` becomes `located on`\r\n\r\n\r\n**Screenshots**\r\n[screenshot of error message](https://github.com/theoptips/udacity_project_submission/blob/master/Screen%20Shot%202019-06-28%20at%202.50.34%20PM.png)\r\n\r\n\r\n\r\n[exception.py with proposed change](https://github.com/theoptips/PySyft/blob/dev/syft/exceptions.py)\r\n[commit message with proposed change explained](https://github.com/theoptips/PySyft/commit/533da84afa6ac4071a58754e97c21ce1ca7056aa)\r\n[exception.py changed line highlighted](https://github.com/theoptips/PySyft/commit/4b68c3c6fbe0c18cdf87dfe6ddc3c2071a71f1cc)\n", "before_files": [{"content": "\"\"\"Specific Pysyft exceptions.\"\"\"\n\nimport syft as sy\nimport torch\nfrom tblib import Traceback\nimport traceback\nfrom six import reraise\nfrom typing import Tuple\n\n\nclass PureTorchTensorFoundError(BaseException):\n    \"\"\"Exception raised for errors in the input.\n    This error is used in a recursive analysis of the args provided as an\n    input of a function, to break the recursion if a TorchTensor is found\n    as it means that _probably_ all the tensors are pure torch tensor and\n    the function can be applied natively on this input.\n\n    Attributes:\n        expression -- input expression in which the error occurred\n        message -- explanation of the error\n    \"\"\"\n\n    pass\n\n\nclass RemoteObjectFoundError(BaseException):\n    \"\"\"Exception raised for errors in the input.\n    This error is used in a context similar to PureTorchTensorFoundError but\n    to indicate that a Pointer to a remote tensor was found  in the input\n    and thus that the command should be send elsewhere. The pointer retrieved\n    by the error gives the location where the command should be sent.\n\n    Attributes:\n        expression -- input expression in which the error occurred\n        message -- explanation of the error\n    \"\"\"\n\n    def __init__(self, pointer):\n        self.pointer = pointer\n\n\nclass InvalidTensorForRemoteGet(Exception):\n    \"\"\"Raised when a chain of pointer tensors is not provided for `remote_get`.\"\"\"\n\n    def __init__(self, tensor: object):\n        message = \"Tensor does not have attribute child. You remote get should be called on a chain of pointer tensors, instead you called it on {}.\".format(\n            tensor\n        )\n        super().__init__(message)\n\n\nclass WorkerNotFoundException(Exception):\n    \"\"\"Raised when a non-existent worker is requested.\"\"\"\n\n    pass\n\n\nclass CompressionNotFoundException(Exception):\n    \"\"\"Raised when a non existent compression/decompression scheme is requested.\"\"\"\n\n    pass\n\n\nclass CannotRequestObjectAttribute(Exception):\n    \"\"\"Raised when .get() is called on a pointer which points to an attribute of\n    another object.\"\"\"\n\n    pass\n\n\nclass TensorsNotCollocatedException(Exception):\n    \"\"\"Raised when a command is executed on two tensors which are not\n    on the same machine. The goal is to provide as useful input as possible\n    to help the user identify which tensors are where so that they can debug\n    which one needs to be moved.\"\"\"\n\n    def __init__(self, tensor_a, tensor_b, attr=\"a method\"):\n\n        if hasattr(tensor_a, \"child\") and tensor_a.is_wrapper:\n            tensor_a = tensor_a.child\n\n        if hasattr(tensor_b, \"child\") and tensor_b.is_wrapper:\n            tensor_b = tensor_b.child\n\n        if isinstance(tensor_a, sy.PointerTensor) and isinstance(tensor_b, sy.PointerTensor):\n            message = (\n                \"You tried to call \"\n                + attr\n                + \" involving two tensors which \"\n                + \"are not on the same machine! One tensor is on \"\n                + str(tensor_a.location)\n                + \" while the other is on \"\n                + str(tensor_b.location)\n                + \". Use a combination of .move(), .get(), and/or .send() to co-locate them to the same machine.\"\n            )\n        elif isinstance(tensor_a, sy.PointerTensor):\n            message = (\n                \"You tried to call \"\n                + attr\n                + \" involving two tensors where one tensor is actually located\"\n                + \"on another machine (is a PointerTensor). Call .get() on the PointerTensor or .send(\"\n                + str(tensor_a.location.id)\n                + \") on the other tensor.\\n\"\n                + \"\\nTensor A: \"\n                + str(tensor_a)\n                + \"\\nTensor B: \"\n                + str(tensor_b)\n            )\n        elif isinstance(tensor_b, sy.PointerTensor):\n            message = (\n                \"You tried to call \"\n                + attr\n                + \" involving two tensors where one tensor is actually located\"\n                + \"on another machine (is a PointerTensor). Call .get() on the PointerTensor or .send(\"\n                + str(tensor_b.location.id)\n                + \") on the other tensor.\\n\"\n                + \"\\nTensor A: \"\n                + str(tensor_a)\n                + \"\\nTensor B: \"\n                + str(tensor_b)\n            )\n        else:\n            message = (\n                \"You tried to call \"\n                + attr\n                + \" involving two tensors which are not on the same machine.\"\n                + \"Try calling .send(), .move(), and/or .get() on these tensors to get them to the same\"\n                + \"worker before calling methods that involve them working together.\"\n            )\n\n        super().__init__(message)\n\n        self.tensor_a = tensor_a\n        self.tensor_b = tensor_b\n\n\nclass ResponseSignatureError(Exception):\n    \"\"\"Raised when the return of a hooked function is not correctly predicted\n    (when defining in advance ids for results)\"\"\"\n\n    def __init__(self, ids_generated=None):\n        self.ids_generated = ids_generated\n\n    def get_attributes(self):\n        \"\"\"\n        Specify all the attributes need to report an error correctly.\n        \"\"\"\n        return {\"ids_generated\": self.ids_generated}\n\n    @staticmethod\n    def simplify(e):\n        \"\"\"\n        Serialize information about an Exception which was raised to forward it\n        \"\"\"\n        # Get information about the exception: type of error,  traceback\n        tp = type(e)\n        tb = e.__traceback__\n        # Serialize the traceback\n        traceback_str = \"Traceback (most recent call last):\\n\" + \"\".join(traceback.format_tb(tb))\n        # Include special attributes if relevant\n        try:\n            attributes = e.get_attributes()\n        except AttributeError:\n            attributes = {}\n        return tp.__name__, traceback_str, sy.serde._simplify(attributes)\n\n    @staticmethod\n    def detail(worker: \"sy.workers.AbstractWorker\", error_tuple: Tuple[str, str, dict]):\n        \"\"\"\n        Detail and re-raise an Exception forwarded by another worker\n        \"\"\"\n        error_name, traceback_str, attributes = error_tuple\n        error_name, traceback_str = error_name.decode(\"utf-8\"), traceback_str.decode(\"utf-8\")\n        attributes = sy.serde._detail(worker, attributes)\n        # De-serialize the traceback\n        tb = Traceback.from_string(traceback_str)\n        # Check that the error belongs to a valid set of Exceptions\n        if error_name in dir(sy.exceptions):\n            error_type = getattr(sy.exceptions, error_name)\n            error = error_type()\n            # Include special attributes if any\n            for attr_name, attr in attributes.items():\n                setattr(error, attr_name, attr)\n            reraise(error_type, error, tb.as_traceback())\n        else:\n            raise ValueError(f\"Invalid Exception returned:\\n{traceback_str}\")\n\n\nclass GetNotPermittedError(Exception):\n    \"\"\"Raised when calling get on a pointer to a tensor which does not allow\n    get to be called on it. This can happen do to sensitivity being too high\"\"\"\n\n    @staticmethod\n    def simplify(e):\n        \"\"\"\n        Serialize information about an Exception which was raised to forward it\n        \"\"\"\n        # Get information about the exception: type of error,  traceback\n        tp = type(e)\n        tb = e.__traceback__\n        # Serialize the traceback\n        traceback_str = \"Traceback (most recent call last):\\n\" + \"\".join(traceback.format_tb(tb))\n        # Include special attributes if relevant\n        try:\n            attributes = e.get_attributes()\n        except AttributeError:\n            attributes = {}\n        return tp.__name__, traceback_str, sy.serde._simplify(attributes)\n\n    @staticmethod\n    def detail(worker: \"sy.workers.AbstractWorker\", error_tuple: Tuple[str, str, dict]):\n        \"\"\"\n        Detail and re-raise an Exception forwarded by another worker\n        \"\"\"\n        error_name, traceback_str, attributes = error_tuple\n        error_name, traceback_str = error_name.decode(\"utf-8\"), traceback_str.decode(\"utf-8\")\n        attributes = sy.serde._detail(worker, attributes)\n        # De-serialize the traceback\n        tb = Traceback.from_string(traceback_str)\n        # Check that the error belongs to a valid set of Exceptions\n        if error_name in dir(sy.exceptions):\n            error_type = getattr(sy.exceptions, error_name)\n            error = error_type()\n            # Include special attributes if any\n            for attr_name, attr in attributes.items():\n                setattr(error, attr_name, attr)\n            reraise(error_type, error, tb.as_traceback())\n        else:\n            raise ValueError(f\"Invalid Exception returned:\\n{traceback_str}\")\n\n\nclass IdNotUniqueError(Exception):\n    \"\"\"Raised by the ID Provider when setting ids that have already been generated\"\"\"\n\n    pass\n\n\ndef route_method_exception(exception, self, args, kwargs):\n    try:\n        if self.is_wrapper:\n            if isinstance(self.child, sy.PointerTensor):\n                if len(args) > 0:\n                    if not args[0].is_wrapper:\n                        return TensorsNotCollocatedException(self, args[0])\n                    elif isinstance(args[0].child, sy.PointerTensor):\n                        if self.location != args[0].child.location:\n                            return TensorsNotCollocatedException(self, args[0])\n\n        # if self is a normal tensor\n        elif isinstance(self, torch.Tensor):\n            if len(args) > 0:\n                if args[0].is_wrapper:\n                    if isinstance(args[0].child, sy.PointerTensor):\n                        return TensorsNotCollocatedException(self, args[0])\n                elif isinstance(args[0], sy.PointerTensor):\n                    return TensorsNotCollocatedException(self, args[0])\n    except:\n        \"\"\n    return exception\n", "path": "syft/exceptions.py"}], "after_files": [{"content": "\"\"\"Specific Pysyft exceptions.\"\"\"\n\nimport syft as sy\nimport torch\nfrom tblib import Traceback\nimport traceback\nfrom six import reraise\nfrom typing import Tuple\n\n\nclass PureTorchTensorFoundError(BaseException):\n    \"\"\"Exception raised for errors in the input.\n    This error is used in a recursive analysis of the args provided as an\n    input of a function, to break the recursion if a TorchTensor is found\n    as it means that _probably_ all the tensors are pure torch tensor and\n    the function can be applied natively on this input.\n\n    Attributes:\n        expression -- input expression in which the error occurred\n        message -- explanation of the error\n    \"\"\"\n\n    pass\n\n\nclass RemoteObjectFoundError(BaseException):\n    \"\"\"Exception raised for errors in the input.\n    This error is used in a context similar to PureTorchTensorFoundError but\n    to indicate that a Pointer to a remote tensor was found  in the input\n    and thus that the command should be send elsewhere. The pointer retrieved\n    by the error gives the location where the command should be sent.\n\n    Attributes:\n        expression -- input expression in which the error occurred\n        message -- explanation of the error\n    \"\"\"\n\n    def __init__(self, pointer):\n        self.pointer = pointer\n\n\nclass InvalidTensorForRemoteGet(Exception):\n    \"\"\"Raised when a chain of pointer tensors is not provided for `remote_get`.\"\"\"\n\n    def __init__(self, tensor: object):\n        message = \"Tensor does not have attribute child. You remote get should be called on a chain of pointer tensors, instead you called it on {}.\".format(\n            tensor\n        )\n        super().__init__(message)\n\n\nclass WorkerNotFoundException(Exception):\n    \"\"\"Raised when a non-existent worker is requested.\"\"\"\n\n    pass\n\n\nclass CompressionNotFoundException(Exception):\n    \"\"\"Raised when a non existent compression/decompression scheme is requested.\"\"\"\n\n    pass\n\n\nclass CannotRequestObjectAttribute(Exception):\n    \"\"\"Raised when .get() is called on a pointer which points to an attribute of\n    another object.\"\"\"\n\n    pass\n\n\nclass TensorsNotCollocatedException(Exception):\n    \"\"\"Raised when a command is executed on two tensors which are not\n    on the same machine. The goal is to provide as useful input as possible\n    to help the user identify which tensors are where so that they can debug\n    which one needs to be moved.\"\"\"\n\n    def __init__(self, tensor_a, tensor_b, attr=\"a method\"):\n\n        if hasattr(tensor_a, \"child\") and tensor_a.is_wrapper:\n            tensor_a = tensor_a.child\n\n        if hasattr(tensor_b, \"child\") and tensor_b.is_wrapper:\n            tensor_b = tensor_b.child\n\n        if isinstance(tensor_a, sy.PointerTensor) and isinstance(tensor_b, sy.PointerTensor):\n            message = (\n                \"You tried to call \"\n                + attr\n                + \" involving two tensors which\"\n                + \" are not on the same machine! One tensor is on \"\n                + str(tensor_a.location)\n                + \" while the other is on \"\n                + str(tensor_b.location)\n                + \". Use a combination of .move(), .get(), and/or .send() to co-locate them to the same machine.\"\n            )\n        elif isinstance(tensor_a, sy.PointerTensor):\n            message = (\n                \"You tried to call \"\n                + attr\n                + \" involving two tensors where one tensor is actually located\"\n                + \" on another machine (is a PointerTensor). Call .get() on the PointerTensor or .send(\"\n                + str(tensor_a.location.id)\n                + \") on the other tensor.\\n\"\n                + \"\\nTensor A: \"\n                + str(tensor_a)\n                + \"\\nTensor B: \"\n                + str(tensor_b)\n            )\n        elif isinstance(tensor_b, sy.PointerTensor):\n            message = (\n                \"You tried to call \"\n                + attr\n                + \" involving two tensors where one tensor is actually located\"\n                + \" on another machine (is a PointerTensor). Call .get() on the PointerTensor or .send(\"\n                + str(tensor_b.location.id)\n                + \") on the other tensor.\\n\"\n                + \"\\nTensor A: \"\n                + str(tensor_a)\n                + \"\\nTensor B: \"\n                + str(tensor_b)\n            )\n        else:\n            message = (\n                \"You tried to call \"\n                + attr\n                + \" involving two tensors which are not on the same machine.\"\n                + \"Try calling .send(), .move(), and/or .get() on these tensors to get them to the same\"\n                + \"worker before calling methods that involve them working together.\"\n            )\n\n        super().__init__(message)\n\n        self.tensor_a = tensor_a\n        self.tensor_b = tensor_b\n\n\nclass ResponseSignatureError(Exception):\n    \"\"\"Raised when the return of a hooked function is not correctly predicted\n    (when defining in advance ids for results)\"\"\"\n\n    def __init__(self, ids_generated=None):\n        self.ids_generated = ids_generated\n\n    def get_attributes(self):\n        \"\"\"\n        Specify all the attributes need to report an error correctly.\n        \"\"\"\n        return {\"ids_generated\": self.ids_generated}\n\n    @staticmethod\n    def simplify(e):\n        \"\"\"\n        Serialize information about an Exception which was raised to forward it\n        \"\"\"\n        # Get information about the exception: type of error,  traceback\n        tp = type(e)\n        tb = e.__traceback__\n        # Serialize the traceback\n        traceback_str = \"Traceback (most recent call last):\\n\" + \"\".join(traceback.format_tb(tb))\n        # Include special attributes if relevant\n        try:\n            attributes = e.get_attributes()\n        except AttributeError:\n            attributes = {}\n        return tp.__name__, traceback_str, sy.serde._simplify(attributes)\n\n    @staticmethod\n    def detail(worker: \"sy.workers.AbstractWorker\", error_tuple: Tuple[str, str, dict]):\n        \"\"\"\n        Detail and re-raise an Exception forwarded by another worker\n        \"\"\"\n        error_name, traceback_str, attributes = error_tuple\n        error_name, traceback_str = error_name.decode(\"utf-8\"), traceback_str.decode(\"utf-8\")\n        attributes = sy.serde._detail(worker, attributes)\n        # De-serialize the traceback\n        tb = Traceback.from_string(traceback_str)\n        # Check that the error belongs to a valid set of Exceptions\n        if error_name in dir(sy.exceptions):\n            error_type = getattr(sy.exceptions, error_name)\n            error = error_type()\n            # Include special attributes if any\n            for attr_name, attr in attributes.items():\n                setattr(error, attr_name, attr)\n            reraise(error_type, error, tb.as_traceback())\n        else:\n            raise ValueError(f\"Invalid Exception returned:\\n{traceback_str}\")\n\n\nclass GetNotPermittedError(Exception):\n    \"\"\"Raised when calling get on a pointer to a tensor which does not allow\n    get to be called on it. This can happen do to sensitivity being too high\"\"\"\n\n    @staticmethod\n    def simplify(e):\n        \"\"\"\n        Serialize information about an Exception which was raised to forward it\n        \"\"\"\n        # Get information about the exception: type of error,  traceback\n        tp = type(e)\n        tb = e.__traceback__\n        # Serialize the traceback\n        traceback_str = \"Traceback (most recent call last):\\n\" + \"\".join(traceback.format_tb(tb))\n        # Include special attributes if relevant\n        try:\n            attributes = e.get_attributes()\n        except AttributeError:\n            attributes = {}\n        return tp.__name__, traceback_str, sy.serde._simplify(attributes)\n\n    @staticmethod\n    def detail(worker: \"sy.workers.AbstractWorker\", error_tuple: Tuple[str, str, dict]):\n        \"\"\"\n        Detail and re-raise an Exception forwarded by another worker\n        \"\"\"\n        error_name, traceback_str, attributes = error_tuple\n        error_name, traceback_str = error_name.decode(\"utf-8\"), traceback_str.decode(\"utf-8\")\n        attributes = sy.serde._detail(worker, attributes)\n        # De-serialize the traceback\n        tb = Traceback.from_string(traceback_str)\n        # Check that the error belongs to a valid set of Exceptions\n        if error_name in dir(sy.exceptions):\n            error_type = getattr(sy.exceptions, error_name)\n            error = error_type()\n            # Include special attributes if any\n            for attr_name, attr in attributes.items():\n                setattr(error, attr_name, attr)\n            reraise(error_type, error, tb.as_traceback())\n        else:\n            raise ValueError(f\"Invalid Exception returned:\\n{traceback_str}\")\n\n\nclass IdNotUniqueError(Exception):\n    \"\"\"Raised by the ID Provider when setting ids that have already been generated\"\"\"\n\n    pass\n\n\ndef route_method_exception(exception, self, args, kwargs):\n    try:\n        if self.is_wrapper:\n            if isinstance(self.child, sy.PointerTensor):\n                if len(args) > 0:\n                    if not args[0].is_wrapper:\n                        return TensorsNotCollocatedException(self, args[0])\n                    elif isinstance(args[0].child, sy.PointerTensor):\n                        if self.location != args[0].child.location:\n                            return TensorsNotCollocatedException(self, args[0])\n\n        # if self is a normal tensor\n        elif isinstance(self, torch.Tensor):\n            if len(args) > 0:\n                if args[0].is_wrapper:\n                    if isinstance(args[0].child, sy.PointerTensor):\n                        return TensorsNotCollocatedException(self, args[0])\n                elif isinstance(args[0], sy.PointerTensor):\n                    return TensorsNotCollocatedException(self, args[0])\n    except:\n        \"\"\n    return exception\n", "path": "syft/exceptions.py"}]}