Nyx Node
Loading...
Searching...
No Matches
obj.py
1# -*- coding: utf-8 -*-
2########################################################################################################################
3# NyxNode
4# Author: Jérôme ODIER <jerome.odier@lpsc.in2p3.fr>
5# SPDX-License-Identifier: GPL-3.0+
6########################################################################################################################
7
8from __future__ import annotations
9
10########################################################################################################################
11
12import ctypes
13import typing
14import weakref
15
16########################################################################################################################
17
18from . import bind
19
20if typing.TYPE_CHECKING:
21
22 from .node import NyxNode
23
24 from .xml import NyxXMLDoc
25
26########################################################################################################################
27
28def nyx_callback(nyx_callback_type):
29
30 ####################################################################################################################
31
32 def decorate(callback: typing.Callable) -> typing.Callable:
33
34 callback._nyx_callback_type = nyx_callback_type
35
36 return callback
37
38 ####################################################################################################################
39
40 return decorate
41
42########################################################################################################################
43
45 """!
46 @brief Base class for JSON Nyx objects.
47 """
48
49 ####################################################################################################################
50
51 def __init__(self, ptr: int):
52 """!
53 @brief Wraps a C JSON object pointer.
54
55 @param ptr JSON object pointer.
56 """
57
58 self._callbacks = []
59 self._c_callback = None
60
61 self._ptr = bind.check_ptr(ptr, 'nyx_object_t')
62
63 self._finalizer = weakref.finalize(self, NyxObject._finalize, self._ptr)
64
65 ####################################################################################################################
66
67 @staticmethod
68 def _finalize(ptr: int) -> None:
69
70 ptr = ctypes.cast(ptr, bind.nyx_object_p)
71
72 ptr.contents.callback = None
73
74 bind.lib.nyx_object_unref(ptr)
75
76 ####################################################################################################################
77
78 @property
79 def ptr(self) -> int:
80 """!
81 @private
82 @brief C pointer to the JSON object.
83
84 @return The JSON object pointer.
85 """
86
87 if not self._ptr:
88
89 raise ValueError('Nyx object has been closed')
90
91 return self._ptr
92
93 ####################################################################################################################
94
95 @staticmethod
96 def _wrap_borrowed_ptr(ptr: int) -> NyxObject:
97
98 ################################################################################################################
99
100 ptr = bind.check_ptr(ptr, 'nyx_object_t')
101
102 ################################################################################################################
103
104 bind.lib.nyx_object_ref(ptr)
105
106 ################################################################################################################
107
108 try:
109
110 ############################################################################################################
111
112 object_type = bind.lib.nyx_object_get_type(ptr)
113
114 ############################################################################################################
115
116 if object_type == bind.NyxObjectType.NULL:
117 from .json.json_null import NyxNull
118 return NyxNull(ptr = ptr)
119
120 if object_type == bind.NyxObjectType.BOOLEAN:
121 from .json.json_boolean import NyxBoolean
122 return NyxBoolean(ptr = ptr)
123
124 if object_type == bind.NyxObjectType.NUMBER:
125 from .json.json_number import NyxNumber
126 return NyxNumber(ptr = ptr)
127
128 if object_type == bind.NyxObjectType.STRING:
129 from .json.json_string import NyxString
130 return NyxString(ptr = ptr)
131
132 if object_type == bind.NyxObjectType.DICT:
133 from .json.json_dict import NyxDict
134 return NyxDict(ptr = ptr)
135
136 if object_type == bind.NyxObjectType.LIST:
137 from .json.json_list import NyxList
138 return NyxList(ptr = ptr)
139
140 ############################################################################################################
141
142 raise TypeError(f'internal error, unknown Nyx object type `{object_type}`')
143
144 ############################################################################################################
145
146 except BaseException:
147
148 bind.lib.nyx_object_unref(ptr)
149
150 raise
151
152 ####################################################################################################################
153
154 def _dispatch_callbacks(self, *args):
155
156 return tuple(callback(*args) for callback in tuple(self._callbacks))
157
158 ####################################################################################################################
159
160 # noinspection PyTypeChecker, PyUnresolvedReferences
161 def on(self, callback: typing.Callable) -> typing.Callable:
162 """!
163 @brief Registers a callback triggered when clients modify this object.
164
165 @param callback Callback triggered when clients modify this object.
166 @return The registered callback.
167
168 @code{.py}
169 @prop.on
170 def on_changed(new_value, old_value):
171 ...
172
173 @vector.on
174 def on_changed(modified):
175 ...
176 @endcode
177 """
178
179 if not callable(callback):
180
181 raise TypeError('Expected a callable')
182
183 ################################################################################################################
184
185 callback_func = getattr(type(self), '_nyx_callback_func', None)
186 callback_type = getattr(callback_func, '_nyx_callback_type', None)
187
188 if callback_type is None:
189
190 raise TypeError(f'{type(self).__name__} does not support callbacks')
191
192 ################################################################################################################
193
194 if self._c_callback is None:
195
196 self._c_callback = callback_type(self._nyx_callback_func)
197
198 object_ptr = ctypes.cast(self.ptr, bind.nyx_object_p)
199
200 object_ptr.contents.callback = ctypes.cast(
201 self._c_callback,
202 ctypes.c_void_p,
203 )
204
205 ################################################################################################################
206
207 self._callbacks.append(callback)
208
209 ################################################################################################################
210
211 return callback
212
213 ####################################################################################################################
214
215 def notify(self) -> bool:
216 """!
217 @brief Notifies this Nyx / INDI object to the clients.
218
219 @return @c True if the object was notified, @c False otherwise.
220 """
221
222 return bool(bind.lib.nyx_object_notify(self.ptr))
223
224 ####################################################################################################################
225
226 @staticmethod
227 def from_string(string: str) -> NyxObject:
228 """!
229 @brief Parses a JSON object from a string.
230
231 @param string JSON string.
232 @return The new JSON object.
233 """
234
235 return NyxObject(bind.lib.nyx_object_parse(bind.as_bytes(string, allow_none = False)))
236
237 ####################################################################################################################
238
239 def to_string(self, json_string: bool = True) -> str:
240 """!
241 @brief Returns a string representing this JSON object.
242
243 @param json_string If @c True, the resulting string is escaped.
244
245 @return A string that represents this JSON document.
246 """
247
248 if json_string:
249 return bind.take_string(bind.lib.nyx_object_to_string(self.ptr))
250 else:
251 return bind.take_string(bind.lib.nyx_object_to_cstring(self.ptr))
252
253 ####################################################################################################################
254
255 def to_xmldoc(self) -> NyxXMLDoc:
256 """!
257 @brief Converts this JSON Nyx / INDI command to the XML one.
258
259 @return The corresponding XML Nyx / INDI command.
260 """
261
262 from .xml import NyxXMLDoc
263
264 return NyxXMLDoc(bind.lib.nyx_object_to_xmldoc(self.ptr))
265
266 ####################################################################################################################
267
268 def __eq__(self, other) -> bool:
269
270 if not isinstance(other, NyxObject):
271
272 return NotImplemented
273
274 return bool(bind.lib.nyx_object_equal(self.ptr, other.ptr))
275
276 ####################################################################################################################
277
278 def __str__(self) -> str:
279
280 return self.to_string()
281
282 def __repr__(self) -> str:
283
284 return self.to_string()
285
286########################################################################################################################
287
288__all__ = [name for name in globals() if name.lower().startswith('nyx')]
289
290########################################################################################################################
JSON dict object.
Definition json_dict.py:22
JSON list object.
Definition json_list.py:22
JSON null object.
Definition json_null.py:17
Base class for JSON Nyx objects.
Definition obj.py:44
NyxXMLDoc to_xmldoc(self)
Converts this JSON Nyx / INDI command to the XML one.
Definition obj.py:255
typing.Callable on(self, typing.Callable callback)
Registers a callback triggered when clients modify this object.
Definition obj.py:161
bool notify(self)
Notifies this Nyx / INDI object to the clients.
Definition obj.py:215
__init__(self, int ptr)
Wraps a C JSON object pointer.
Definition obj.py:51
NyxObject from_string(str string)
Parses a JSON object from a string.
Definition obj.py:227
str to_string(self, bool json_string=True)
Returns a string representing this JSON object.
Definition obj.py:239
list _callbacks
Definition obj.py:58
XML document.
Definition xml.py:25