np-services 0.1.69__py3-none-any.whl → 0.1.71__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.
- np_services/__init__.py +8 -8
- np_services/open_ephys.py +377 -378
- np_services/protocols.py +185 -185
- np_services/proxies.py +1489 -1489
- np_services/resources/mvr_connector.py +260 -260
- np_services/resources/zro.py +325 -325
- np_services/scripts/pretest.py +412 -389
- np_services/stim_computer_theme_changer.py +41 -41
- np_services/utils.py +167 -167
- {np_services-0.1.69.dist-info → np_services-0.1.71.dist-info}/METADATA +5 -5
- np_services-0.1.71.dist-info/RECORD +15 -0
- {np_services-0.1.69.dist-info → np_services-0.1.71.dist-info}/WHEEL +2 -1
- {np_services-0.1.69.dist-info → np_services-0.1.71.dist-info}/entry_points.txt +1 -1
- np_services-0.1.71.dist-info/top_level.txt +1 -0
- np_services/.mypy_cache/.gitignore +0 -2
- np_services/.mypy_cache/3.9/@plugins_snapshot.json +0 -1
- np_services/.mypy_cache/3.9/__future__.data.json +0 -1
- np_services/.mypy_cache/3.9/__future__.meta.json +0 -1
- np_services/.mypy_cache/3.9/_ast.data.json +0 -1
- np_services/.mypy_cache/3.9/_ast.meta.json +0 -1
- np_services/.mypy_cache/3.9/_codecs.data.json +0 -1
- np_services/.mypy_cache/3.9/_codecs.meta.json +0 -1
- np_services/.mypy_cache/3.9/_collections_abc.data.json +0 -1
- np_services/.mypy_cache/3.9/_collections_abc.meta.json +0 -1
- np_services/.mypy_cache/3.9/_ctypes.data.json +0 -1
- np_services/.mypy_cache/3.9/_ctypes.meta.json +0 -1
- np_services/.mypy_cache/3.9/_decimal.data.json +0 -1
- np_services/.mypy_cache/3.9/_decimal.meta.json +0 -1
- np_services/.mypy_cache/3.9/_random.data.json +0 -1
- np_services/.mypy_cache/3.9/_random.meta.json +0 -1
- np_services/.mypy_cache/3.9/_socket.data.json +0 -1
- np_services/.mypy_cache/3.9/_socket.meta.json +0 -1
- np_services/.mypy_cache/3.9/_thread.data.json +0 -1
- np_services/.mypy_cache/3.9/_thread.meta.json +0 -1
- np_services/.mypy_cache/3.9/_typeshed/__init__.data.json +0 -1
- np_services/.mypy_cache/3.9/_typeshed/__init__.meta.json +0 -1
- np_services/.mypy_cache/3.9/_warnings.data.json +0 -1
- np_services/.mypy_cache/3.9/_warnings.meta.json +0 -1
- np_services/.mypy_cache/3.9/_weakref.data.json +0 -1
- np_services/.mypy_cache/3.9/_weakref.meta.json +0 -1
- np_services/.mypy_cache/3.9/_weakrefset.data.json +0 -1
- np_services/.mypy_cache/3.9/_weakrefset.meta.json +0 -1
- np_services/.mypy_cache/3.9/_winapi.data.json +0 -1
- np_services/.mypy_cache/3.9/_winapi.meta.json +0 -1
- np_services/.mypy_cache/3.9/abc.data.json +0 -1
- np_services/.mypy_cache/3.9/abc.meta.json +0 -1
- np_services/.mypy_cache/3.9/array.data.json +0 -1
- np_services/.mypy_cache/3.9/array.meta.json +0 -1
- np_services/.mypy_cache/3.9/atexit.data.json +0 -1
- np_services/.mypy_cache/3.9/atexit.meta.json +0 -1
- np_services/.mypy_cache/3.9/builtins.data.json +0 -1
- np_services/.mypy_cache/3.9/builtins.meta.json +0 -1
- np_services/.mypy_cache/3.9/codecs.data.json +0 -1
- np_services/.mypy_cache/3.9/codecs.meta.json +0 -1
- np_services/.mypy_cache/3.9/collections/__init__.data.json +0 -1
- np_services/.mypy_cache/3.9/collections/__init__.meta.json +0 -1
- np_services/.mypy_cache/3.9/collections/abc.data.json +0 -1
- np_services/.mypy_cache/3.9/collections/abc.meta.json +0 -1
- np_services/.mypy_cache/3.9/contextlib.data.json +0 -1
- np_services/.mypy_cache/3.9/contextlib.meta.json +0 -1
- np_services/.mypy_cache/3.9/ctypes/__init__.data.json +0 -1
- np_services/.mypy_cache/3.9/ctypes/__init__.meta.json +0 -1
- np_services/.mypy_cache/3.9/datetime.data.json +0 -1
- np_services/.mypy_cache/3.9/datetime.meta.json +0 -1
- np_services/.mypy_cache/3.9/decimal.data.json +0 -1
- np_services/.mypy_cache/3.9/decimal.meta.json +0 -1
- np_services/.mypy_cache/3.9/email/__init__.data.json +0 -1
- np_services/.mypy_cache/3.9/email/__init__.meta.json +0 -1
- np_services/.mypy_cache/3.9/email/charset.data.json +0 -1
- np_services/.mypy_cache/3.9/email/charset.meta.json +0 -1
- np_services/.mypy_cache/3.9/email/contentmanager.data.json +0 -1
- np_services/.mypy_cache/3.9/email/contentmanager.meta.json +0 -1
- np_services/.mypy_cache/3.9/email/errors.data.json +0 -1
- np_services/.mypy_cache/3.9/email/errors.meta.json +0 -1
- np_services/.mypy_cache/3.9/email/header.data.json +0 -1
- np_services/.mypy_cache/3.9/email/header.meta.json +0 -1
- np_services/.mypy_cache/3.9/email/message.data.json +0 -1
- np_services/.mypy_cache/3.9/email/message.meta.json +0 -1
- np_services/.mypy_cache/3.9/email/policy.data.json +0 -1
- np_services/.mypy_cache/3.9/email/policy.meta.json +0 -1
- np_services/.mypy_cache/3.9/enum.data.json +0 -1
- np_services/.mypy_cache/3.9/enum.meta.json +0 -1
- np_services/.mypy_cache/3.9/errno.data.json +0 -1
- np_services/.mypy_cache/3.9/errno.meta.json +0 -1
- np_services/.mypy_cache/3.9/fractions.data.json +0 -1
- np_services/.mypy_cache/3.9/fractions.meta.json +0 -1
- np_services/.mypy_cache/3.9/genericpath.data.json +0 -1
- np_services/.mypy_cache/3.9/genericpath.meta.json +0 -1
- np_services/.mypy_cache/3.9/importlib/__init__.data.json +0 -1
- np_services/.mypy_cache/3.9/importlib/__init__.meta.json +0 -1
- np_services/.mypy_cache/3.9/importlib/abc.data.json +0 -1
- np_services/.mypy_cache/3.9/importlib/abc.meta.json +0 -1
- np_services/.mypy_cache/3.9/importlib/machinery.data.json +0 -1
- np_services/.mypy_cache/3.9/importlib/machinery.meta.json +0 -1
- np_services/.mypy_cache/3.9/importlib/metadata/__init__.data.json +0 -1
- np_services/.mypy_cache/3.9/importlib/metadata/__init__.meta.json +0 -1
- np_services/.mypy_cache/3.9/io.data.json +0 -1
- np_services/.mypy_cache/3.9/io.meta.json +0 -1
- np_services/.mypy_cache/3.9/json/__init__.data.json +0 -1
- np_services/.mypy_cache/3.9/json/__init__.meta.json +0 -1
- np_services/.mypy_cache/3.9/json/decoder.data.json +0 -1
- np_services/.mypy_cache/3.9/json/decoder.meta.json +0 -1
- np_services/.mypy_cache/3.9/json/encoder.data.json +0 -1
- np_services/.mypy_cache/3.9/json/encoder.meta.json +0 -1
- np_services/.mypy_cache/3.9/logging/__init__.data.json +0 -1
- np_services/.mypy_cache/3.9/logging/__init__.meta.json +0 -1
- np_services/.mypy_cache/3.9/math.data.json +0 -1
- np_services/.mypy_cache/3.9/math.meta.json +0 -1
- np_services/.mypy_cache/3.9/mmap.data.json +0 -1
- np_services/.mypy_cache/3.9/mmap.meta.json +0 -1
- np_services/.mypy_cache/3.9/np_services/__init__.data.json +0 -1
- np_services/.mypy_cache/3.9/np_services/__init__.meta.json +0 -1
- np_services/.mypy_cache/3.9/np_services/config.data.json +0 -1
- np_services/.mypy_cache/3.9/np_services/config.meta.json +0 -1
- np_services/.mypy_cache/3.9/np_services/protocols.data.json +0 -1
- np_services/.mypy_cache/3.9/np_services/protocols.meta.json +0 -1
- np_services/.mypy_cache/3.9/np_services/zro.data.json +0 -1
- np_services/.mypy_cache/3.9/np_services/zro.meta.json +0 -1
- np_services/.mypy_cache/3.9/ntpath.data.json +0 -1
- np_services/.mypy_cache/3.9/ntpath.meta.json +0 -1
- np_services/.mypy_cache/3.9/numbers.data.json +0 -1
- np_services/.mypy_cache/3.9/numbers.meta.json +0 -1
- np_services/.mypy_cache/3.9/os/__init__.data.json +0 -1
- np_services/.mypy_cache/3.9/os/__init__.meta.json +0 -1
- np_services/.mypy_cache/3.9/os/path.data.json +0 -1
- np_services/.mypy_cache/3.9/os/path.meta.json +0 -1
- np_services/.mypy_cache/3.9/pathlib.data.json +0 -1
- np_services/.mypy_cache/3.9/pathlib.meta.json +0 -1
- np_services/.mypy_cache/3.9/pickle.data.json +0 -1
- np_services/.mypy_cache/3.9/pickle.meta.json +0 -1
- np_services/.mypy_cache/3.9/platform.data.json +0 -1
- np_services/.mypy_cache/3.9/platform.meta.json +0 -1
- np_services/.mypy_cache/3.9/posixpath.data.json +0 -1
- np_services/.mypy_cache/3.9/posixpath.meta.json +0 -1
- np_services/.mypy_cache/3.9/random.data.json +0 -1
- np_services/.mypy_cache/3.9/random.meta.json +0 -1
- np_services/.mypy_cache/3.9/re.data.json +0 -1
- np_services/.mypy_cache/3.9/re.meta.json +0 -1
- np_services/.mypy_cache/3.9/shutil.data.json +0 -1
- np_services/.mypy_cache/3.9/shutil.meta.json +0 -1
- np_services/.mypy_cache/3.9/socket.data.json +0 -1
- np_services/.mypy_cache/3.9/socket.meta.json +0 -1
- np_services/.mypy_cache/3.9/sre_compile.data.json +0 -1
- np_services/.mypy_cache/3.9/sre_compile.meta.json +0 -1
- np_services/.mypy_cache/3.9/sre_constants.data.json +0 -1
- np_services/.mypy_cache/3.9/sre_constants.meta.json +0 -1
- np_services/.mypy_cache/3.9/sre_parse.data.json +0 -1
- np_services/.mypy_cache/3.9/sre_parse.meta.json +0 -1
- np_services/.mypy_cache/3.9/string.data.json +0 -1
- np_services/.mypy_cache/3.9/string.meta.json +0 -1
- np_services/.mypy_cache/3.9/subprocess.data.json +0 -1
- np_services/.mypy_cache/3.9/subprocess.meta.json +0 -1
- np_services/.mypy_cache/3.9/sys.data.json +0 -1
- np_services/.mypy_cache/3.9/sys.meta.json +0 -1
- np_services/.mypy_cache/3.9/threading.data.json +0 -1
- np_services/.mypy_cache/3.9/threading.meta.json +0 -1
- np_services/.mypy_cache/3.9/time.data.json +0 -1
- np_services/.mypy_cache/3.9/time.meta.json +0 -1
- np_services/.mypy_cache/3.9/types.data.json +0 -1
- np_services/.mypy_cache/3.9/types.meta.json +0 -1
- np_services/.mypy_cache/3.9/typing.data.json +0 -1
- np_services/.mypy_cache/3.9/typing.meta.json +0 -1
- np_services/.mypy_cache/3.9/typing_extensions.data.json +0 -1
- np_services/.mypy_cache/3.9/typing_extensions.meta.json +0 -1
- np_services/.mypy_cache/3.9/warnings.data.json +0 -1
- np_services/.mypy_cache/3.9/warnings.meta.json +0 -1
- np_services/.mypy_cache/3.9/weakref.data.json +0 -1
- np_services/.mypy_cache/3.9/weakref.meta.json +0 -1
- np_services/.mypy_cache/3.9/zmq/__init__.data.json +0 -1
- np_services/.mypy_cache/3.9/zmq/__init__.meta.json +0 -1
- np_services/.mypy_cache/3.9/zmq/_typing.data.json +0 -1
- np_services/.mypy_cache/3.9/zmq/_typing.meta.json +0 -1
- np_services/.mypy_cache/3.9/zmq/backend/__init__.data.json +0 -1
- np_services/.mypy_cache/3.9/zmq/backend/__init__.meta.json +0 -1
- np_services/.mypy_cache/3.9/zmq/backend/select.data.json +0 -1
- np_services/.mypy_cache/3.9/zmq/backend/select.meta.json +0 -1
- np_services/.mypy_cache/3.9/zmq/constants.data.json +0 -1
- np_services/.mypy_cache/3.9/zmq/constants.meta.json +0 -1
- np_services/.mypy_cache/3.9/zmq/error.data.json +0 -1
- np_services/.mypy_cache/3.9/zmq/error.meta.json +0 -1
- np_services/.mypy_cache/3.9/zmq/sugar/__init__.data.json +0 -1
- np_services/.mypy_cache/3.9/zmq/sugar/__init__.meta.json +0 -1
- np_services/.mypy_cache/3.9/zmq/sugar/attrsettr.data.json +0 -1
- np_services/.mypy_cache/3.9/zmq/sugar/attrsettr.meta.json +0 -1
- np_services/.mypy_cache/3.9/zmq/sugar/context.data.json +0 -1
- np_services/.mypy_cache/3.9/zmq/sugar/context.meta.json +0 -1
- np_services/.mypy_cache/3.9/zmq/sugar/frame.data.json +0 -1
- np_services/.mypy_cache/3.9/zmq/sugar/frame.meta.json +0 -1
- np_services/.mypy_cache/3.9/zmq/sugar/poll.data.json +0 -1
- np_services/.mypy_cache/3.9/zmq/sugar/poll.meta.json +0 -1
- np_services/.mypy_cache/3.9/zmq/sugar/socket.data.json +0 -1
- np_services/.mypy_cache/3.9/zmq/sugar/socket.meta.json +0 -1
- np_services/.mypy_cache/3.9/zmq/sugar/tracker.data.json +0 -1
- np_services/.mypy_cache/3.9/zmq/sugar/tracker.meta.json +0 -1
- np_services/.mypy_cache/3.9/zmq/sugar/version.data.json +0 -1
- np_services/.mypy_cache/3.9/zmq/sugar/version.meta.json +0 -1
- np_services/.mypy_cache/3.9/zmq/utils/__init__.data.json +0 -1
- np_services/.mypy_cache/3.9/zmq/utils/__init__.meta.json +0 -1
- np_services/.mypy_cache/3.9/zmq/utils/interop.data.json +0 -1
- np_services/.mypy_cache/3.9/zmq/utils/interop.meta.json +0 -1
- np_services/.mypy_cache/3.9/zmq/utils/jsonapi.data.json +0 -1
- np_services/.mypy_cache/3.9/zmq/utils/jsonapi.meta.json +0 -1
- np_services/.mypy_cache/CACHEDIR.TAG +0 -3
- np_services/resources/black_desktop.ps1 +0 -66
- np_services/resources/grey_desktop.ps1 +0 -66
- np_services/resources/reset_desktop.ps1 +0 -66
- np_services-0.1.69.dist-info/RECORD +0 -206
np_services/resources/zro.py
CHANGED
|
@@ -1,325 +1,325 @@
|
|
|
1
|
-
# -*- coding: utf-8 -*-
|
|
2
|
-
"""
|
|
3
|
-
proxy.py
|
|
4
|
-
|
|
5
|
-
@author: derricw
|
|
6
|
-
|
|
7
|
-
Proxy device and manager for ZRO devices.
|
|
8
|
-
|
|
9
|
-
`Proxy` is a remote object proxy designed to interact with objects
|
|
10
|
-
extending `BasePubRepDevice` (from device.py).
|
|
11
|
-
|
|
12
|
-
"""
|
|
13
|
-
import np_logging
|
|
14
|
-
import zmq
|
|
15
|
-
|
|
16
|
-
logger = np_logging.getLogger(__name__)
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
def get_address(ip="", port=None):
|
|
20
|
-
"""
|
|
21
|
-
Trys to get a properly formatted address given a port and ip.
|
|
22
|
-
|
|
23
|
-
ZMQ likes address to be in this format:
|
|
24
|
-
|
|
25
|
-
{protocol}://{ip}:{port}
|
|
26
|
-
|
|
27
|
-
Args:
|
|
28
|
-
ip (Optional[str]): ip address with some semblance of correct formatting
|
|
29
|
-
port (Optional[int]): port to use in the event that the port is not
|
|
30
|
-
included in the IP
|
|
31
|
-
|
|
32
|
-
Returns:
|
|
33
|
-
str: a properly formatted ip str.
|
|
34
|
-
|
|
35
|
-
"""
|
|
36
|
-
if not ip and not port:
|
|
37
|
-
raise ValueError("Need a port or IP.")
|
|
38
|
-
elif not ip and port:
|
|
39
|
-
return "tcp://*:{}".format(port)
|
|
40
|
-
else:
|
|
41
|
-
if ip[:6] != "tcp://":
|
|
42
|
-
ip = "tcp://" + ip
|
|
43
|
-
if len(ip.split(":")) == 2:
|
|
44
|
-
return "{}:{}".format(ip, port)
|
|
45
|
-
else:
|
|
46
|
-
return ip
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
class DeviceProxy(object):
|
|
50
|
-
"""
|
|
51
|
-
Proxy object for a BasePubRepDevice.
|
|
52
|
-
|
|
53
|
-
args:
|
|
54
|
-
ip (Optional[str]): IP/DNS address of actual device. Defaults to
|
|
55
|
-
"localhost".
|
|
56
|
-
port (Optional[int]): REP port for actual device, if it isn't include
|
|
57
|
-
in IP.
|
|
58
|
-
timeout (Optional[float]): Timeout in seconds for all commands.
|
|
59
|
-
Defaults to 10.
|
|
60
|
-
serialization (Optional[str]): Serialization method. "pickle" (default)
|
|
61
|
-
or "json".
|
|
62
|
-
|
|
63
|
-
Example:
|
|
64
|
-
>>> dev = DeviceProxy("localhost:5556")
|
|
65
|
-
>>> dev.call_method_on_device(some_argument)
|
|
66
|
-
>>> dev.attr_on_device = 5
|
|
67
|
-
|
|
68
|
-
"""
|
|
69
|
-
|
|
70
|
-
_context = zmq.Context()
|
|
71
|
-
_context.setsockopt(zmq.LINGER, 1)
|
|
72
|
-
|
|
73
|
-
def __init__(
|
|
74
|
-
self, ip="localhost", port=None, timeout=10.0, serialization="pickle",
|
|
75
|
-
):
|
|
76
|
-
super().__init__()
|
|
77
|
-
self.__dict__["ip"] = ip
|
|
78
|
-
self.__dict__["rep_port"] = port
|
|
79
|
-
self.__dict__["timeout"] = timeout
|
|
80
|
-
self.__dict__["serialization"] = serialization.lower()
|
|
81
|
-
|
|
82
|
-
self._setup_socket()
|
|
83
|
-
# self._setup_getset()
|
|
84
|
-
|
|
85
|
-
def __setattr__(self, name, value):
|
|
86
|
-
"""
|
|
87
|
-
Overwrite __setattr__ so that attributes are set on target object
|
|
88
|
-
instead of this object.
|
|
89
|
-
"""
|
|
90
|
-
packet = {"command": "set", "args": (name, value)}
|
|
91
|
-
self._send_packet(packet)
|
|
92
|
-
response = self.__dict__["recv"]()
|
|
93
|
-
if response == "0":
|
|
94
|
-
return None
|
|
95
|
-
else:
|
|
96
|
-
raise ZroError(message=str(response))
|
|
97
|
-
|
|
98
|
-
def __getattr__(self, name):
|
|
99
|
-
"""
|
|
100
|
-
Overwrite __getattr__ so that attributes are grabbed from target object
|
|
101
|
-
instead of this object.
|
|
102
|
-
"""
|
|
103
|
-
packet = {"command": "get", "args": (name,)}
|
|
104
|
-
self._send_packet(packet)
|
|
105
|
-
response = self.__dict__["recv"]()
|
|
106
|
-
if isinstance(response, ZroError):
|
|
107
|
-
raise ZroError(message=str(response))
|
|
108
|
-
elif response in ("callable", "__callable__"):
|
|
109
|
-
self.__dict__["to_call"] = name # HOLD ON TO YOUR BUTTS
|
|
110
|
-
return self._call
|
|
111
|
-
else:
|
|
112
|
-
return response
|
|
113
|
-
|
|
114
|
-
def __dir__(self):
|
|
115
|
-
"""
|
|
116
|
-
Overwrite __dir__ so that attributes and methods come from target
|
|
117
|
-
object.
|
|
118
|
-
"""
|
|
119
|
-
self.__dict__["to_call"] = "get_attribute_list"
|
|
120
|
-
attrs = self._call()
|
|
121
|
-
self.__dict__["to_call"] = "get_command_list"
|
|
122
|
-
methods = self._call()
|
|
123
|
-
return attrs + methods
|
|
124
|
-
|
|
125
|
-
def _send_packet(self, packet):
|
|
126
|
-
"""
|
|
127
|
-
Sends a packet. Attempts to reconnect once if there is a failure.
|
|
128
|
-
|
|
129
|
-
#TODO: Make packet a class.
|
|
130
|
-
"""
|
|
131
|
-
try:
|
|
132
|
-
self.__dict__["send"](packet)
|
|
133
|
-
except zmq.ZMQError:
|
|
134
|
-
self.__dict__["req_socket"].close()
|
|
135
|
-
self._setup_socket()
|
|
136
|
-
self.__dict__["send"](packet)
|
|
137
|
-
|
|
138
|
-
def _setup_socket(self):
|
|
139
|
-
"""
|
|
140
|
-
Sets up the request socket.
|
|
141
|
-
"""
|
|
142
|
-
ip = self.__dict__["ip"]
|
|
143
|
-
rep_port = self.__dict__["rep_port"]
|
|
144
|
-
addr_str = get_address(ip, rep_port)
|
|
145
|
-
timeout = self.__dict__["timeout"]
|
|
146
|
-
self.__dict__["req_socket"] = self._context.socket(zmq.REQ)
|
|
147
|
-
self.__dict__["req_socket"].setsockopt(zmq.SNDTIMEO, int(timeout * 1000))
|
|
148
|
-
self.__dict__["req_socket"].setsockopt(zmq.RCVTIMEO, int(timeout * 1000))
|
|
149
|
-
self.__dict__["req_socket"].connect(addr_str)
|
|
150
|
-
|
|
151
|
-
if self.__dict__["serialization"] in ["pickle", "pkl", "p"]:
|
|
152
|
-
self.__dict__["send"] = self.__dict__["req_socket"].send_pyobj
|
|
153
|
-
self.__dict__["recv"] = self.__dict__["req_socket"].recv_pyobj
|
|
154
|
-
elif self.__dict__["serialization"] in ["json", "j"]:
|
|
155
|
-
self.__dict__["send"] = self.__dict__["req_socket"].send_json
|
|
156
|
-
self.__dict__["recv"] = self.__dict__["req_socket"].recv_json
|
|
157
|
-
else:
|
|
158
|
-
raise ValueError("Incorrect serialization type. Try 'pickle' or 'json'.")
|
|
159
|
-
|
|
160
|
-
def _call(self, *args, **kwargs):
|
|
161
|
-
"""
|
|
162
|
-
Used for calling arbitrary methods in the device.
|
|
163
|
-
"""
|
|
164
|
-
packet = {
|
|
165
|
-
"command": "run",
|
|
166
|
-
"callable": self.to_call,
|
|
167
|
-
"args": args,
|
|
168
|
-
"kwargs": kwargs,
|
|
169
|
-
}
|
|
170
|
-
self.__dict__["send"](packet)
|
|
171
|
-
response = self.__dict__["recv"]()
|
|
172
|
-
if isinstance(response, dict) and response.get("ZroError", False):
|
|
173
|
-
response = ZroError.from_dict(response)
|
|
174
|
-
if isinstance(response, ZroError):
|
|
175
|
-
raise ZroError(message=str(response))
|
|
176
|
-
return response
|
|
177
|
-
|
|
178
|
-
def __del__(self):
|
|
179
|
-
"""
|
|
180
|
-
Close the socket on cleanup.
|
|
181
|
-
"""
|
|
182
|
-
self.__dict__["req_socket"].close()
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
Proxy = DeviceProxy
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
class ZroError(Exception):
|
|
189
|
-
"""Base class for zro errors."""
|
|
190
|
-
|
|
191
|
-
error_codes = {
|
|
192
|
-
1: "{} -> HAS_NO_ATTRIBUTE -> {}",
|
|
193
|
-
2: "{} -> HAS_NO_CALLABLE -> {}",
|
|
194
|
-
3: "{} -> ATTRIBUTE_NOT_CALLABLE -> {}",
|
|
195
|
-
4: "{} -> CALLABLE_FAILED -> {}",
|
|
196
|
-
5: "{} -> ARGUMENTS_INVALID -> {}",
|
|
197
|
-
6: "{} -> UNHANDLED_ERROR -> {}",
|
|
198
|
-
7: "{} -> ASYNC_RESULT_INVALID_HANDLE -> {}",
|
|
199
|
-
8: "{} -> ASYNC_RESULT_UNFINISHED -> {}",
|
|
200
|
-
9: "{} -> ASYNC_CALLBACK_FAILED -> {}",
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
HAS_NO_ATTRIBUTE = 1
|
|
204
|
-
HAS_NO_CALLABLE = 2
|
|
205
|
-
ATTRIBUTE_NOT_CALLABLE = 3
|
|
206
|
-
CALLABLE_FAILED = 4
|
|
207
|
-
ARGUMENTS_INVALID = 5
|
|
208
|
-
UNHANDLED_ERROR = 6
|
|
209
|
-
ASYNC_RESULT_INVALID_HANDLE = 7
|
|
210
|
-
ASYNC_RESULT_UNFINISHED = 8
|
|
211
|
-
ASYNC_CALLBACK_FAILED = 9
|
|
212
|
-
|
|
213
|
-
def __init__(self, obj=None, target=None, error_code=6, message=""):
|
|
214
|
-
if not message:
|
|
215
|
-
message = self.error_codes[error_code].format(obj, target)
|
|
216
|
-
self.message = message
|
|
217
|
-
self.error_code = error_code
|
|
218
|
-
super(ZroError, self).__init__(message)
|
|
219
|
-
|
|
220
|
-
def to_JSON(self):
|
|
221
|
-
return {
|
|
222
|
-
"ZroError": str(
|
|
223
|
-
type(self.get_specific_error())
|
|
224
|
-
), # this key lets zro convert this on the receive side
|
|
225
|
-
"error_code": self.error_code,
|
|
226
|
-
"message": str(self.message),
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
@staticmethod
|
|
230
|
-
def from_dict(d):
|
|
231
|
-
return ZroError(
|
|
232
|
-
error_code=d["error_code"], message=d["message"]
|
|
233
|
-
).get_specific_error()
|
|
234
|
-
|
|
235
|
-
def get_specific_error(self, to_raise=False):
|
|
236
|
-
"""Get the appropriate ZroError for the error type."""
|
|
237
|
-
err = _SPECIFIC_ERRORS[self.error_code](message=self.message)
|
|
238
|
-
if to_raise:
|
|
239
|
-
raise err
|
|
240
|
-
return err
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
class ZroNoAttributeError(ZroError):
|
|
244
|
-
"""Error for HAS_NO_ATTRIBUTE."""
|
|
245
|
-
|
|
246
|
-
def __init__(self, obj=None, target=None, message=""):
|
|
247
|
-
super(ZroNoAttributeError, self).__init__(
|
|
248
|
-
obj, target, ZroError.HAS_NO_ATTRIBUTE, message
|
|
249
|
-
)
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
class ZroNoCallableError(ZroError):
|
|
253
|
-
"""Error for HAS_NO_CALLABLE."""
|
|
254
|
-
|
|
255
|
-
def __init__(self, obj=None, target=None, message=""):
|
|
256
|
-
super(ZroNoCallableError, self).__init__(
|
|
257
|
-
obj, target, ZroError.HAS_NO_CALLABLE, message
|
|
258
|
-
)
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
class ZroAttrNotCallableError(ZroError):
|
|
262
|
-
"""Error for ATTRIBUTE_NOT_CALLABLE."""
|
|
263
|
-
|
|
264
|
-
def __init__(self, obj=None, target=None, message=""):
|
|
265
|
-
super(ZroAttrNotCallableError, self).__init__(
|
|
266
|
-
obj, target, ZroError.ATTRIBUTE_NOT_CALLABLE, message
|
|
267
|
-
)
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
class ZroCallableFailedError(ZroError):
|
|
271
|
-
"""Error for CALLABLE_FAILED."""
|
|
272
|
-
|
|
273
|
-
def __init__(self, obj=None, target=None, message=""):
|
|
274
|
-
super(ZroCallableFailedError, self).__init__(
|
|
275
|
-
obj, target, ZroError.CALLABLE_FAILED, message
|
|
276
|
-
)
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
class ZroArgumentsInvalidError(ZroError):
|
|
280
|
-
"""Error for ARGUMENTS_INVALID."""
|
|
281
|
-
|
|
282
|
-
def __init__(self, obj=None, target=None, message=""):
|
|
283
|
-
super(ZroArgumentsInvalidError, self).__init__(
|
|
284
|
-
obj, target, ZroError.ARGUMENTS_INVALID, message
|
|
285
|
-
)
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
class ZroAsyncHandleInvalidError(ZroError):
|
|
289
|
-
"""Error for ASYNC_RESULT_INVALID_HANDLE."""
|
|
290
|
-
|
|
291
|
-
def __init__(self, obj=None, target=None, message=""):
|
|
292
|
-
super(ZroAsyncHandleInvalidError, self).__init__(
|
|
293
|
-
obj, target, ZroError.ASYNC_RESULT_INVALID_HANDLE, message
|
|
294
|
-
)
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
class ZroResultUnfinishedError(ZroError):
|
|
298
|
-
"""Error for ASYNC_RESULT_UNFINISHED."""
|
|
299
|
-
|
|
300
|
-
def __init__(self, obj=None, target=None, message=""):
|
|
301
|
-
super(ZroResultUnfinishedError, self).__init__(
|
|
302
|
-
obj, target, ZroError.ASYNC_RESULT_UNFINISHED, message
|
|
303
|
-
)
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
class ZroCallbackFailedError(ZroError):
|
|
307
|
-
"""Error for ASYNC_CALLBACK_FAILED."""
|
|
308
|
-
|
|
309
|
-
def __init__(self, obj=None, target=None, message=""):
|
|
310
|
-
super(ZroCallbackFailedError, self).__init__(
|
|
311
|
-
obj, target, ZroError.ASYNC_CALLBACK_FAILED, message
|
|
312
|
-
)
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
_SPECIFIC_ERRORS = {
|
|
316
|
-
1: ZroNoAttributeError,
|
|
317
|
-
2: ZroNoCallableError,
|
|
318
|
-
3: ZroAttrNotCallableError,
|
|
319
|
-
4: ZroCallableFailedError,
|
|
320
|
-
5: ZroArgumentsInvalidError,
|
|
321
|
-
6: ZroError,
|
|
322
|
-
7: ZroAsyncHandleInvalidError,
|
|
323
|
-
8: ZroResultUnfinishedError,
|
|
324
|
-
9: ZroCallbackFailedError,
|
|
325
|
-
}
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
"""
|
|
3
|
+
proxy.py
|
|
4
|
+
|
|
5
|
+
@author: derricw
|
|
6
|
+
|
|
7
|
+
Proxy device and manager for ZRO devices.
|
|
8
|
+
|
|
9
|
+
`Proxy` is a remote object proxy designed to interact with objects
|
|
10
|
+
extending `BasePubRepDevice` (from device.py).
|
|
11
|
+
|
|
12
|
+
"""
|
|
13
|
+
import np_logging
|
|
14
|
+
import zmq
|
|
15
|
+
|
|
16
|
+
logger = np_logging.getLogger(__name__)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def get_address(ip="", port=None):
|
|
20
|
+
"""
|
|
21
|
+
Trys to get a properly formatted address given a port and ip.
|
|
22
|
+
|
|
23
|
+
ZMQ likes address to be in this format:
|
|
24
|
+
|
|
25
|
+
{protocol}://{ip}:{port}
|
|
26
|
+
|
|
27
|
+
Args:
|
|
28
|
+
ip (Optional[str]): ip address with some semblance of correct formatting
|
|
29
|
+
port (Optional[int]): port to use in the event that the port is not
|
|
30
|
+
included in the IP
|
|
31
|
+
|
|
32
|
+
Returns:
|
|
33
|
+
str: a properly formatted ip str.
|
|
34
|
+
|
|
35
|
+
"""
|
|
36
|
+
if not ip and not port:
|
|
37
|
+
raise ValueError("Need a port or IP.")
|
|
38
|
+
elif not ip and port:
|
|
39
|
+
return "tcp://*:{}".format(port)
|
|
40
|
+
else:
|
|
41
|
+
if ip[:6] != "tcp://":
|
|
42
|
+
ip = "tcp://" + ip
|
|
43
|
+
if len(ip.split(":")) == 2:
|
|
44
|
+
return "{}:{}".format(ip, port)
|
|
45
|
+
else:
|
|
46
|
+
return ip
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
class DeviceProxy(object):
|
|
50
|
+
"""
|
|
51
|
+
Proxy object for a BasePubRepDevice.
|
|
52
|
+
|
|
53
|
+
args:
|
|
54
|
+
ip (Optional[str]): IP/DNS address of actual device. Defaults to
|
|
55
|
+
"localhost".
|
|
56
|
+
port (Optional[int]): REP port for actual device, if it isn't include
|
|
57
|
+
in IP.
|
|
58
|
+
timeout (Optional[float]): Timeout in seconds for all commands.
|
|
59
|
+
Defaults to 10.
|
|
60
|
+
serialization (Optional[str]): Serialization method. "pickle" (default)
|
|
61
|
+
or "json".
|
|
62
|
+
|
|
63
|
+
Example:
|
|
64
|
+
>>> dev = DeviceProxy("localhost:5556")
|
|
65
|
+
>>> dev.call_method_on_device(some_argument)
|
|
66
|
+
>>> dev.attr_on_device = 5
|
|
67
|
+
|
|
68
|
+
"""
|
|
69
|
+
|
|
70
|
+
_context = zmq.Context()
|
|
71
|
+
_context.setsockopt(zmq.LINGER, 1)
|
|
72
|
+
|
|
73
|
+
def __init__(
|
|
74
|
+
self, ip="localhost", port=None, timeout=10.0, serialization="pickle",
|
|
75
|
+
):
|
|
76
|
+
super().__init__()
|
|
77
|
+
self.__dict__["ip"] = ip
|
|
78
|
+
self.__dict__["rep_port"] = port
|
|
79
|
+
self.__dict__["timeout"] = timeout
|
|
80
|
+
self.__dict__["serialization"] = serialization.lower()
|
|
81
|
+
|
|
82
|
+
self._setup_socket()
|
|
83
|
+
# self._setup_getset()
|
|
84
|
+
|
|
85
|
+
def __setattr__(self, name, value):
|
|
86
|
+
"""
|
|
87
|
+
Overwrite __setattr__ so that attributes are set on target object
|
|
88
|
+
instead of this object.
|
|
89
|
+
"""
|
|
90
|
+
packet = {"command": "set", "args": (name, value)}
|
|
91
|
+
self._send_packet(packet)
|
|
92
|
+
response = self.__dict__["recv"]()
|
|
93
|
+
if response == "0":
|
|
94
|
+
return None
|
|
95
|
+
else:
|
|
96
|
+
raise ZroError(message=str(response))
|
|
97
|
+
|
|
98
|
+
def __getattr__(self, name):
|
|
99
|
+
"""
|
|
100
|
+
Overwrite __getattr__ so that attributes are grabbed from target object
|
|
101
|
+
instead of this object.
|
|
102
|
+
"""
|
|
103
|
+
packet = {"command": "get", "args": (name,)}
|
|
104
|
+
self._send_packet(packet)
|
|
105
|
+
response = self.__dict__["recv"]()
|
|
106
|
+
if isinstance(response, ZroError):
|
|
107
|
+
raise ZroError(message=str(response))
|
|
108
|
+
elif response in ("callable", "__callable__"):
|
|
109
|
+
self.__dict__["to_call"] = name # HOLD ON TO YOUR BUTTS
|
|
110
|
+
return self._call
|
|
111
|
+
else:
|
|
112
|
+
return response
|
|
113
|
+
|
|
114
|
+
def __dir__(self):
|
|
115
|
+
"""
|
|
116
|
+
Overwrite __dir__ so that attributes and methods come from target
|
|
117
|
+
object.
|
|
118
|
+
"""
|
|
119
|
+
self.__dict__["to_call"] = "get_attribute_list"
|
|
120
|
+
attrs = self._call()
|
|
121
|
+
self.__dict__["to_call"] = "get_command_list"
|
|
122
|
+
methods = self._call()
|
|
123
|
+
return attrs + methods
|
|
124
|
+
|
|
125
|
+
def _send_packet(self, packet):
|
|
126
|
+
"""
|
|
127
|
+
Sends a packet. Attempts to reconnect once if there is a failure.
|
|
128
|
+
|
|
129
|
+
#TODO: Make packet a class.
|
|
130
|
+
"""
|
|
131
|
+
try:
|
|
132
|
+
self.__dict__["send"](packet)
|
|
133
|
+
except zmq.ZMQError:
|
|
134
|
+
self.__dict__["req_socket"].close()
|
|
135
|
+
self._setup_socket()
|
|
136
|
+
self.__dict__["send"](packet)
|
|
137
|
+
|
|
138
|
+
def _setup_socket(self):
|
|
139
|
+
"""
|
|
140
|
+
Sets up the request socket.
|
|
141
|
+
"""
|
|
142
|
+
ip = self.__dict__["ip"]
|
|
143
|
+
rep_port = self.__dict__["rep_port"]
|
|
144
|
+
addr_str = get_address(ip, rep_port)
|
|
145
|
+
timeout = self.__dict__["timeout"]
|
|
146
|
+
self.__dict__["req_socket"] = self._context.socket(zmq.REQ)
|
|
147
|
+
self.__dict__["req_socket"].setsockopt(zmq.SNDTIMEO, int(timeout * 1000))
|
|
148
|
+
self.__dict__["req_socket"].setsockopt(zmq.RCVTIMEO, int(timeout * 1000))
|
|
149
|
+
self.__dict__["req_socket"].connect(addr_str)
|
|
150
|
+
|
|
151
|
+
if self.__dict__["serialization"] in ["pickle", "pkl", "p"]:
|
|
152
|
+
self.__dict__["send"] = self.__dict__["req_socket"].send_pyobj
|
|
153
|
+
self.__dict__["recv"] = self.__dict__["req_socket"].recv_pyobj
|
|
154
|
+
elif self.__dict__["serialization"] in ["json", "j"]:
|
|
155
|
+
self.__dict__["send"] = self.__dict__["req_socket"].send_json
|
|
156
|
+
self.__dict__["recv"] = self.__dict__["req_socket"].recv_json
|
|
157
|
+
else:
|
|
158
|
+
raise ValueError("Incorrect serialization type. Try 'pickle' or 'json'.")
|
|
159
|
+
|
|
160
|
+
def _call(self, *args, **kwargs):
|
|
161
|
+
"""
|
|
162
|
+
Used for calling arbitrary methods in the device.
|
|
163
|
+
"""
|
|
164
|
+
packet = {
|
|
165
|
+
"command": "run",
|
|
166
|
+
"callable": self.to_call,
|
|
167
|
+
"args": args,
|
|
168
|
+
"kwargs": kwargs,
|
|
169
|
+
}
|
|
170
|
+
self.__dict__["send"](packet)
|
|
171
|
+
response = self.__dict__["recv"]()
|
|
172
|
+
if isinstance(response, dict) and response.get("ZroError", False):
|
|
173
|
+
response = ZroError.from_dict(response)
|
|
174
|
+
if isinstance(response, ZroError):
|
|
175
|
+
raise ZroError(message=str(response))
|
|
176
|
+
return response
|
|
177
|
+
|
|
178
|
+
def __del__(self):
|
|
179
|
+
"""
|
|
180
|
+
Close the socket on cleanup.
|
|
181
|
+
"""
|
|
182
|
+
self.__dict__["req_socket"].close()
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
Proxy = DeviceProxy
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
class ZroError(Exception):
|
|
189
|
+
"""Base class for zro errors."""
|
|
190
|
+
|
|
191
|
+
error_codes = {
|
|
192
|
+
1: "{} -> HAS_NO_ATTRIBUTE -> {}",
|
|
193
|
+
2: "{} -> HAS_NO_CALLABLE -> {}",
|
|
194
|
+
3: "{} -> ATTRIBUTE_NOT_CALLABLE -> {}",
|
|
195
|
+
4: "{} -> CALLABLE_FAILED -> {}",
|
|
196
|
+
5: "{} -> ARGUMENTS_INVALID -> {}",
|
|
197
|
+
6: "{} -> UNHANDLED_ERROR -> {}",
|
|
198
|
+
7: "{} -> ASYNC_RESULT_INVALID_HANDLE -> {}",
|
|
199
|
+
8: "{} -> ASYNC_RESULT_UNFINISHED -> {}",
|
|
200
|
+
9: "{} -> ASYNC_CALLBACK_FAILED -> {}",
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
HAS_NO_ATTRIBUTE = 1
|
|
204
|
+
HAS_NO_CALLABLE = 2
|
|
205
|
+
ATTRIBUTE_NOT_CALLABLE = 3
|
|
206
|
+
CALLABLE_FAILED = 4
|
|
207
|
+
ARGUMENTS_INVALID = 5
|
|
208
|
+
UNHANDLED_ERROR = 6
|
|
209
|
+
ASYNC_RESULT_INVALID_HANDLE = 7
|
|
210
|
+
ASYNC_RESULT_UNFINISHED = 8
|
|
211
|
+
ASYNC_CALLBACK_FAILED = 9
|
|
212
|
+
|
|
213
|
+
def __init__(self, obj=None, target=None, error_code=6, message=""):
|
|
214
|
+
if not message:
|
|
215
|
+
message = self.error_codes[error_code].format(obj, target)
|
|
216
|
+
self.message = message
|
|
217
|
+
self.error_code = error_code
|
|
218
|
+
super(ZroError, self).__init__(message)
|
|
219
|
+
|
|
220
|
+
def to_JSON(self):
|
|
221
|
+
return {
|
|
222
|
+
"ZroError": str(
|
|
223
|
+
type(self.get_specific_error())
|
|
224
|
+
), # this key lets zro convert this on the receive side
|
|
225
|
+
"error_code": self.error_code,
|
|
226
|
+
"message": str(self.message),
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
@staticmethod
|
|
230
|
+
def from_dict(d):
|
|
231
|
+
return ZroError(
|
|
232
|
+
error_code=d["error_code"], message=d["message"]
|
|
233
|
+
).get_specific_error()
|
|
234
|
+
|
|
235
|
+
def get_specific_error(self, to_raise=False):
|
|
236
|
+
"""Get the appropriate ZroError for the error type."""
|
|
237
|
+
err = _SPECIFIC_ERRORS[self.error_code](message=self.message)
|
|
238
|
+
if to_raise:
|
|
239
|
+
raise err
|
|
240
|
+
return err
|
|
241
|
+
|
|
242
|
+
|
|
243
|
+
class ZroNoAttributeError(ZroError):
|
|
244
|
+
"""Error for HAS_NO_ATTRIBUTE."""
|
|
245
|
+
|
|
246
|
+
def __init__(self, obj=None, target=None, message=""):
|
|
247
|
+
super(ZroNoAttributeError, self).__init__(
|
|
248
|
+
obj, target, ZroError.HAS_NO_ATTRIBUTE, message
|
|
249
|
+
)
|
|
250
|
+
|
|
251
|
+
|
|
252
|
+
class ZroNoCallableError(ZroError):
|
|
253
|
+
"""Error for HAS_NO_CALLABLE."""
|
|
254
|
+
|
|
255
|
+
def __init__(self, obj=None, target=None, message=""):
|
|
256
|
+
super(ZroNoCallableError, self).__init__(
|
|
257
|
+
obj, target, ZroError.HAS_NO_CALLABLE, message
|
|
258
|
+
)
|
|
259
|
+
|
|
260
|
+
|
|
261
|
+
class ZroAttrNotCallableError(ZroError):
|
|
262
|
+
"""Error for ATTRIBUTE_NOT_CALLABLE."""
|
|
263
|
+
|
|
264
|
+
def __init__(self, obj=None, target=None, message=""):
|
|
265
|
+
super(ZroAttrNotCallableError, self).__init__(
|
|
266
|
+
obj, target, ZroError.ATTRIBUTE_NOT_CALLABLE, message
|
|
267
|
+
)
|
|
268
|
+
|
|
269
|
+
|
|
270
|
+
class ZroCallableFailedError(ZroError):
|
|
271
|
+
"""Error for CALLABLE_FAILED."""
|
|
272
|
+
|
|
273
|
+
def __init__(self, obj=None, target=None, message=""):
|
|
274
|
+
super(ZroCallableFailedError, self).__init__(
|
|
275
|
+
obj, target, ZroError.CALLABLE_FAILED, message
|
|
276
|
+
)
|
|
277
|
+
|
|
278
|
+
|
|
279
|
+
class ZroArgumentsInvalidError(ZroError):
|
|
280
|
+
"""Error for ARGUMENTS_INVALID."""
|
|
281
|
+
|
|
282
|
+
def __init__(self, obj=None, target=None, message=""):
|
|
283
|
+
super(ZroArgumentsInvalidError, self).__init__(
|
|
284
|
+
obj, target, ZroError.ARGUMENTS_INVALID, message
|
|
285
|
+
)
|
|
286
|
+
|
|
287
|
+
|
|
288
|
+
class ZroAsyncHandleInvalidError(ZroError):
|
|
289
|
+
"""Error for ASYNC_RESULT_INVALID_HANDLE."""
|
|
290
|
+
|
|
291
|
+
def __init__(self, obj=None, target=None, message=""):
|
|
292
|
+
super(ZroAsyncHandleInvalidError, self).__init__(
|
|
293
|
+
obj, target, ZroError.ASYNC_RESULT_INVALID_HANDLE, message
|
|
294
|
+
)
|
|
295
|
+
|
|
296
|
+
|
|
297
|
+
class ZroResultUnfinishedError(ZroError):
|
|
298
|
+
"""Error for ASYNC_RESULT_UNFINISHED."""
|
|
299
|
+
|
|
300
|
+
def __init__(self, obj=None, target=None, message=""):
|
|
301
|
+
super(ZroResultUnfinishedError, self).__init__(
|
|
302
|
+
obj, target, ZroError.ASYNC_RESULT_UNFINISHED, message
|
|
303
|
+
)
|
|
304
|
+
|
|
305
|
+
|
|
306
|
+
class ZroCallbackFailedError(ZroError):
|
|
307
|
+
"""Error for ASYNC_CALLBACK_FAILED."""
|
|
308
|
+
|
|
309
|
+
def __init__(self, obj=None, target=None, message=""):
|
|
310
|
+
super(ZroCallbackFailedError, self).__init__(
|
|
311
|
+
obj, target, ZroError.ASYNC_CALLBACK_FAILED, message
|
|
312
|
+
)
|
|
313
|
+
|
|
314
|
+
|
|
315
|
+
_SPECIFIC_ERRORS = {
|
|
316
|
+
1: ZroNoAttributeError,
|
|
317
|
+
2: ZroNoCallableError,
|
|
318
|
+
3: ZroAttrNotCallableError,
|
|
319
|
+
4: ZroCallableFailedError,
|
|
320
|
+
5: ZroArgumentsInvalidError,
|
|
321
|
+
6: ZroError,
|
|
322
|
+
7: ZroAsyncHandleInvalidError,
|
|
323
|
+
8: ZroResultUnfinishedError,
|
|
324
|
+
9: ZroCallbackFailedError,
|
|
325
|
+
}
|