motorcortex-python 0.22.9__tar.gz → 0.23.0__tar.gz

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.
Files changed (24) hide show
  1. {motorcortex-python-0.22.9/motorcortex_python.egg-info → motorcortex-python-0.23.0}/PKG-INFO +1 -1
  2. {motorcortex-python-0.22.9 → motorcortex-python-0.23.0}/motorcortex/__init__.py +2 -0
  3. {motorcortex-python-0.22.9 → motorcortex-python-0.23.0}/motorcortex/message_types.py +4 -4
  4. {motorcortex-python-0.22.9 → motorcortex-python-0.23.0}/motorcortex/parameter_tree.py +1 -1
  5. {motorcortex-python-0.22.9 → motorcortex-python-0.23.0}/motorcortex/reply.py +5 -5
  6. {motorcortex-python-0.22.9 → motorcortex-python-0.23.0}/motorcortex/request.py +28 -24
  7. {motorcortex-python-0.22.9 → motorcortex-python-0.23.0}/motorcortex/setup_logger.py +1 -1
  8. motorcortex-python-0.23.0/motorcortex/state_callback_handler.py +62 -0
  9. {motorcortex-python-0.22.9 → motorcortex-python-0.23.0}/motorcortex/subscribe.py +21 -16
  10. {motorcortex-python-0.22.9 → motorcortex-python-0.23.0}/motorcortex/subscription.py +10 -12
  11. motorcortex-python-0.23.0/motorcortex/version.py +1 -0
  12. {motorcortex-python-0.22.9 → motorcortex-python-0.23.0/motorcortex_python.egg-info}/PKG-INFO +1 -1
  13. {motorcortex-python-0.22.9 → motorcortex-python-0.23.0}/motorcortex_python.egg-info/SOURCES.txt +1 -0
  14. {motorcortex-python-0.22.9 → motorcortex-python-0.23.0}/motorcortex_python.egg-info/requires.txt +1 -1
  15. {motorcortex-python-0.22.9 → motorcortex-python-0.23.0}/setup.py +1 -1
  16. motorcortex-python-0.22.9/motorcortex/version.py +0 -1
  17. {motorcortex-python-0.22.9 → motorcortex-python-0.23.0}/LICENSE +0 -0
  18. {motorcortex-python-0.22.9 → motorcortex-python-0.23.0}/MANIFEST.in +0 -0
  19. {motorcortex-python-0.22.9 → motorcortex-python-0.23.0}/README.md +0 -0
  20. {motorcortex-python-0.22.9 → motorcortex-python-0.23.0}/motorcortex/motorcortex_hash.json +0 -0
  21. {motorcortex-python-0.22.9 → motorcortex-python-0.23.0}/motorcortex/motorcortex_pb2.py +0 -0
  22. {motorcortex-python-0.22.9 → motorcortex-python-0.23.0}/motorcortex_python.egg-info/dependency_links.txt +0 -0
  23. {motorcortex-python-0.22.9 → motorcortex-python-0.23.0}/motorcortex_python.egg-info/top_level.txt +0 -0
  24. {motorcortex-python-0.22.9 → motorcortex-python-0.23.0}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: motorcortex-python
3
- Version: 0.22.9
3
+ Version: 0.23.0
4
4
  Summary: Python bindings for Motorcortex Engine
5
5
  Home-page: https://www.motorcortex.io
6
6
  Author: Alexey Zakharov
@@ -13,6 +13,8 @@ from motorcortex.reply import Reply
13
13
  from motorcortex.subscribe import Subscribe
14
14
  from motorcortex.subscription import Subscription
15
15
  from motorcortex.setup_logger import logger
16
+ from motorcortex.state_callback_handler import StateCallbackHandler
17
+
16
18
 
17
19
  def parseUrl(url):
18
20
  end = url.rfind(':')
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/python3
2
2
 
3
3
  #
4
- # Developer : Alexey Zakharov (alexey.zakharov@vectioneer.com)
4
+ # Developer: Alexey Zakharov (alexey.zakharov@vectioneer.com)
5
5
  # All rights reserved. Copyright (c) 2016 VECTIONEER.
6
6
  #
7
7
 
@@ -120,11 +120,11 @@ class PrimitiveTypes(object):
120
120
  if t is bytes:
121
121
  return value
122
122
 
123
- # if string prepare and encode
123
+ # if the argument is a string, prepare and encode
124
124
  if t is str:
125
125
  return self.__encoder(-1, value)
126
126
 
127
- # if not list convert to list
127
+ # if not list, convert to list
128
128
  if t is not list:
129
129
  value = [value]
130
130
 
@@ -213,7 +213,7 @@ class MessageTypes(object):
213
213
  self.__hashes_by_name[hash_type_pair['type']] = hash
214
214
 
215
215
  module = module_hash_pair.module
216
- # searching for messages from hash file
216
+ # searching for messages from a hash file
217
217
 
218
218
  for name in module.__dict__:
219
219
  type = module.__dict__[name]
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/python3
2
2
 
3
3
  #
4
- # Developer : Alexey Zakharov (alexey.zakharov@vectioneer.com)
4
+ # Developer: Alexey Zakharov (alexey.zakharov@vectioneer.com)
5
5
  # All rights reserved. Copyright (c) 2016 VECTIONEER.
6
6
  #
7
7
 
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/python3
2
2
 
3
3
  #
4
- # Developer : Alexey Zakharov (alexey.zakharov@vectioneer.com)
4
+ # Developer: Alexey Zakharov (alexey.zakharov@vectioneer.com)
5
5
  # All rights reserved. Copyright (c) 2016-2020 VECTIONEER.
6
6
  #
7
7
 
@@ -9,7 +9,7 @@
9
9
  class Reply(object):
10
10
  """Reply handle is a JavaScript-like Promise.
11
11
 
12
- It is resolved when reply is received with successful status and fails otherwise.
12
+ It is resolved when a reply is received with successful status and fails otherwise.
13
13
  """
14
14
 
15
15
  def __init__(self, future):
@@ -34,15 +34,15 @@ class Reply(object):
34
34
  def done(self):
35
35
  """
36
36
  Returns:
37
- bool: True if the call was successfully cancelled or finished running.
37
+ bool: True if the call was successfully canceled or finished running.
38
38
  """
39
39
  return self.__future.done()
40
40
 
41
41
  def then(self, received_clb, *args, **kwargs):
42
- """JavaScript-like promise, which is resolved when reply is received.
42
+ """JavaScript-like promise, which is resolved when a reply is received.
43
43
 
44
44
  Args:
45
- received_clb: callback which is resolved when reply is received.
45
+ received_clb: callback which is resolved when the reply is received.
46
46
 
47
47
  Returns:
48
48
  self pointer to add 'catch' callback
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/python3
2
2
 
3
3
  #
4
- # Developer : Alexey Zakharov (alexey.zakharov@vectioneer.com)
5
- # All rights reserved. Copyright (c) 2016-2020 VECTIONEER.
4
+ # Developer: Alexey Zakharov (alexey.zakharov@vectioneer.com)
5
+ # All rights reserved. Copyright (c) 2016-2025 VECTIONEER.
6
6
  #
7
7
  import base64
8
8
  import hashlib
@@ -11,6 +11,7 @@ import tempfile
11
11
 
12
12
  from motorcortex.reply import Reply
13
13
  from motorcortex.setup_logger import logger
14
+ from motorcortex.state_callback_handler import StateCallbackHandler
14
15
 
15
16
  import os
16
17
  import queue
@@ -56,9 +57,9 @@ class Request(object):
56
57
  self.__connected_lock = None
57
58
  self.__protobuf_types = protobuf_types
58
59
  self.__parameter_tree = parameter_tree
59
- self.__pool = ThreadPoolExecutor(max_workers=1)
60
- self.__clb = ThreadPoolExecutor(max_workers=1)
61
60
  self.__connection_state = ConnectionState.DISCONNECTED
61
+ self.__pool = ThreadPoolExecutor(max_workers=1)
62
+ self.__callback_handler = StateCallbackHandler()
62
63
 
63
64
  def url(self):
64
65
  return self.__url
@@ -66,6 +67,10 @@ class Request(object):
66
67
  def connect(self, url, **kwargs):
67
68
  self.__connection_state = ConnectionState.CONNECTING
68
69
  conn_timeout_ms, recv_timeout_ms, certificate, state_update = self.parse(**kwargs)
70
+
71
+ if state_update:
72
+ self.__callback_handler.start(state_update)
73
+
69
74
  self.__url = url
70
75
  tls_config = None
71
76
  if certificate:
@@ -77,8 +82,7 @@ class Request(object):
77
82
  def pre_connect_cb(pipe):
78
83
  self.__connected_lock.put(True)
79
84
  self.__connection_state = ConnectionState.CONNECTION_OK
80
- if state_update:
81
- self.__clb.submit(state_update, self, self.connectionState())
85
+ self.__callback_handler.notify(self, self.connectionState())
82
86
 
83
87
  def post_remove_cb(pipe):
84
88
  if self.__connection_state == ConnectionState.DISCONNECTING:
@@ -88,8 +92,7 @@ class Request(object):
88
92
  elif self.__connection_state == ConnectionState.CONNECTION_OK:
89
93
  self.__connection_state = ConnectionState.CONNECTION_LOST
90
94
  self.__connected_lock.put(False)
91
- if state_update:
92
- self.__clb.submit(state_update, self, self.connectionState())
95
+ self.__callback_handler.notify(self, self.connectionState())
93
96
 
94
97
  self.__socket.add_post_pipe_connect_cb(pre_connect_cb)
95
98
  self.__socket.add_post_pipe_remove_cb(post_remove_cb)
@@ -103,6 +106,7 @@ class Request(object):
103
106
  if self.__connected_lock:
104
107
  self.__connected_lock.put(False)
105
108
  self.__socket.close()
109
+ self.__callback_handler.stop()
106
110
 
107
111
  def send(self, encoded_msg, do_not_decode_reply=False):
108
112
  if self.__socket is not None:
@@ -119,7 +123,7 @@ class Request(object):
119
123
 
120
124
  Results:
121
125
  Reply(StatusMsg): A Promise, which resolves if login is successful and fails otherwise.
122
- Returned message has a status code, which indicates a status of the login.
126
+ The returned message has a status code, which indicates the status of the login.
123
127
 
124
128
  Examples:
125
129
  >>> login_reply = req.login('operator', 'iddqd')
@@ -161,7 +165,7 @@ class Request(object):
161
165
  """Request a parameter tree from the server.
162
166
 
163
167
  Returns:
164
- Reply(ParameterTreeMsg): A Promise, which resolves when parameter tree is received or fails
168
+ Reply(ParameterTreeMsg): A Promise, which resolves when a parameter tree is received or fails
165
169
  otherwise. ParameterTreeMsg message has a status field to check the status of the operation.
166
170
 
167
171
  Examples:
@@ -194,14 +198,14 @@ class Request(object):
194
198
  return self.send(self.__protobuf_types.encode(param_save_msg))
195
199
 
196
200
  def setParameter(self, path, value, type_name=None, offset=0, length=0):
197
- """Set new value to a parameter with given path
201
+ """Set a new value to a parameter with a given path
198
202
 
199
203
  Args:
200
204
  path(str): parameter path in the tree
201
205
  value(any): new parameter value
202
- type_name(str): type of the value (by default resolved automatically)
203
- offset(int): offset of the elements to update in the destination array, (by default is 0)
204
- length(int): number of the elements to update in the destination array, (by default takes length of the
206
+ type_name(str): type of the value (by default, resolved automatically)
207
+ offset(int): offset of the elements to update in the destination array, (by default, is 0)
208
+ length(int): number of the elements to update in the destination array, (by default, takes length of the
205
209
  value argument)
206
210
 
207
211
  Returns:
@@ -262,7 +266,7 @@ class Request(object):
262
266
  path(str): parameter path in the tree.
263
267
 
264
268
  Returns:
265
- Reply(ParameterMsg): Returns a Promise, which resolves when parameter
269
+ Reply(ParameterMsg): Returns a Promise, which resolves when a parameter
266
270
  message is successfully obtained, fails otherwise.
267
271
 
268
272
  Examples:
@@ -276,10 +280,10 @@ class Request(object):
276
280
  """Get description and values of requested parameters.
277
281
 
278
282
  Args:
279
- path_list(list(str)): list of parameter paths in the tree.
283
+ path_list(list(str)): a list of parameter paths in the tree.
280
284
 
281
285
  Returns:
282
- Reply(ParameterListMsg): A Promise, which resolves when list of the parameter values is received, fails
286
+ Reply(ParameterListMsg): A Promise, which resolves when a list of the parameter values is received, fails
283
287
  otherwise.
284
288
 
285
289
  Examples:
@@ -299,17 +303,17 @@ class Request(object):
299
303
 
300
304
  def overwriteParameter(self, path, value, force_activate=False, type_name=None):
301
305
  """Overwrites actual value of the parameter and depending on the flag forces this value to stay active.
302
- This method of setting values is useful during debug and installation process, it is not recommended to use
306
+ This method of setting values is useful during the debug and installation process, it is not recommended to use
303
307
  this method during normal operation.
304
308
 
305
309
  Args:
306
310
  path(str): parameter path in the tree
307
311
  value(any): new parameter value
308
- force_activate(bool): forces new value to stay active. (by default is set to 'False')
309
- type_name(str): type of the value (by default resolved automatically)
312
+ force_activate(bool): forces the new value to stay active. (by default, is set to 'False')
313
+ type_name(str): type of the value (by default, resolved automatically)
310
314
 
311
315
  Returns:
312
- Reply(StatusMsg): A Promise, which resolves when parameter value is updated or fails otherwise.
316
+ Reply(StatusMsg): A Promise, which resolves when a parameter value is updated or fails otherwise.
313
317
 
314
318
  Examples:
315
319
  >>> reply = req.overwriteParameter("root/Control/dummyBool", False, True)
@@ -322,13 +326,13 @@ class Request(object):
322
326
  self.__parameter_tree)))
323
327
 
324
328
  def releaseParameter(self, path):
325
- """Deactivate overwrite operation of the parameter.
329
+ """Deactivate the overwrite operation of the parameter.
326
330
 
327
331
  Args:
328
332
  path(str): parameter path in the tree
329
333
 
330
334
  Returns:
331
- Reply(StatusMsg): A Promise, which resolves when parameter value is released or fails otherwise.
335
+ Reply(StatusMsg): A Promise, which resolves when a parameter value is released or fails otherwise.
332
336
 
333
337
  Examples:
334
338
  >>> reply = req.releaseParameter("root/Control/dummyBool")
@@ -348,7 +352,7 @@ class Request(object):
348
352
  frq_divider(int): frequency divider is a downscaling factor for the group publish rate
349
353
 
350
354
  Returns:
351
- Reply(GroupStatusMsg): A Promise, which resolves when subscription is complete,
355
+ Reply(GroupStatusMsg): A Promise, which resolves when the subscription is complete,
352
356
  fails otherwise.
353
357
  """
354
358
 
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/python3
2
2
 
3
3
  #
4
- # Developer : Alexey Zakharov (alexey.zakharov@vectioneer.com)
4
+ # Developer: Alexey Zakharov (alexey.zakharov@vectioneer.com)
5
5
  # All rights reserved. Copyright (c) 2021 VECTIONEER.
6
6
  #
7
7
 
@@ -0,0 +1,62 @@
1
+ #!/usr/bin/python3
2
+
3
+ #
4
+ # Developer: Alexey Zakharov (alexey.zakharov@vectioneer.com)
5
+ # All rights reserved. Copyright (c) 2025 VECTIONEER.
6
+ #
7
+
8
+ from queue import Queue, Empty
9
+ import threading
10
+ from motorcortex.setup_logger import logger
11
+
12
+
13
+ class StateCallbackHandler:
14
+ """Handles state change callbacks processing"""
15
+
16
+ def __init__(self):
17
+ self.running = False
18
+ self.callback_queue = Queue()
19
+ self.callback_thread = None
20
+ self.state_update_handler = None
21
+
22
+ def start(self, state_update_handler):
23
+ """Start the callback handler with the given update function"""
24
+ if state_update_handler:
25
+ self.state_update_handler = state_update_handler
26
+ self.running = True
27
+ self.callback_thread = threading.Thread(
28
+ target=self.__process_callbacks,
29
+ daemon=True
30
+ )
31
+ self.callback_thread.start()
32
+
33
+ def stop(self):
34
+ """Stop the callback handler and clean up"""
35
+ self.running = False
36
+ if self.callback_thread:
37
+ self.callback_queue.put(None) # Signal thread to exit
38
+ self.callback_thread.join(timeout=1.0)
39
+ self.callback_thread = None
40
+ self.state_update_handler = None
41
+
42
+ def notify(self, *args):
43
+ """Queue a state update notification"""
44
+ if self.state_update_handler:
45
+ self.callback_queue.put(args)
46
+
47
+ def __process_callbacks(self):
48
+ """Process callbacks in a dedicated thread"""
49
+ while self.running:
50
+ try:
51
+ args = self.callback_queue.get(timeout=0.1)
52
+ if args is None: # Stop signal
53
+ break
54
+ try:
55
+ self.state_update_handler(*args)
56
+ except Exception as e:
57
+ logger.exception("Error in state callback: %s", e)
58
+ except Empty:
59
+ continue
60
+ except Exception as e:
61
+ if self.running:
62
+ logger.exception("Error processing callbacks: %s", e)
@@ -1,19 +1,21 @@
1
1
  #!/usr/bin/python3
2
2
 
3
3
  #
4
- # Developer : Alexey Zakharov (alexey.zakharov@vectioneer.com)
5
- # All rights reserved. Copyright (c) 2016 VECTIONEER.
4
+ # Developer: Alexey Zakharov (alexey.zakharov@vectioneer.com)
5
+ # All rights reserved. Copyright (c) 2016-2025 VECTIONEER.
6
6
  #
7
7
 
8
8
  from motorcortex.request import Request, Reply, ConnectionState
9
9
  from motorcortex.subscription import Subscription
10
+ from motorcortex.state_callback_handler import StateCallbackHandler
11
+ from motorcortex.setup_logger import logger
10
12
  from pynng import Sub0, TLSConfig
11
13
  from concurrent.futures import ThreadPoolExecutor
12
14
  from queue import Queue
13
15
 
14
16
 
15
17
  class Subscribe:
16
- """Subscribe class is used to receive continuous parameter updates from motorcortex server.
18
+ """Subscribe class is used to receive continuous parameter updates from the motorcortex server.
17
19
 
18
20
  Subscribe class simplifies creating and removing subscription groups.
19
21
 
@@ -31,22 +33,26 @@ class Subscribe:
31
33
  self.__protobuf_types = protobuf_types
32
34
  self.__subscriptions = dict()
33
35
  self.__pool = ThreadPoolExecutor()
34
- self.__clb = ThreadPoolExecutor(max_workers=1)
36
+ self.__callback_handler = StateCallbackHandler()
35
37
  self.__connection_state = ConnectionState.DISCONNECTED
36
38
 
37
39
  def connect(self, url, **kwargs):
38
- """Open a subscribe connection.
40
+ """Open a subscription connection.
39
41
 
40
42
  Args:
41
43
  url(str): motorcortex server URL
42
44
 
43
45
  Returns:
44
- bool: True - if connected, False othesudo apt-get install python-devrwise
46
+ bool: True - if connected, False otherwise
45
47
  """
46
48
 
47
49
  self.__connection_state = ConnectionState.CONNECTING
48
50
  conn_timeout_ms, recv_timeout_ms, certificate, state_update = Request.parse(**kwargs)
49
- if recv_timeout_ms == 0:
51
+
52
+ if state_update:
53
+ self.__callback_handler.start(state_update)
54
+
55
+ if not recv_timeout_ms:
50
56
  recv_timeout_ms = 500
51
57
 
52
58
  self.__url = url
@@ -61,8 +67,7 @@ class Subscribe:
61
67
  def pre_connect_cb(pipe):
62
68
  self.__connected_lock.put(True)
63
69
  self.__connection_state = ConnectionState.CONNECTION_OK
64
- if state_update:
65
- self.__clb.submit(state_update, self.__req, self, self.connectionState())
70
+ self.__callback_handler.notify(self.__req, self, self.connectionState())
66
71
 
67
72
  def post_remove_cb(pipe):
68
73
  if self.__connection_state == ConnectionState.DISCONNECTING:
@@ -72,8 +77,7 @@ class Subscribe:
72
77
  elif self.__connection_state == ConnectionState.CONNECTION_OK:
73
78
  self.__connection_state = ConnectionState.CONNECTION_LOST
74
79
  self.__connected_lock.put(False)
75
- if state_update:
76
- self.__clb.submit(state_update, self.__req, self, self.connectionState())
80
+ self.__callback_handler.notify(self.__req, self, self.connectionState())
77
81
 
78
82
  self.__socket.add_pre_pipe_connect_cb(pre_connect_cb)
79
83
  self.__socket.add_post_pipe_remove_cb(post_remove_cb)
@@ -90,6 +94,7 @@ class Subscribe:
90
94
  if self.__connected_lock:
91
95
  self.__connected_lock.put(False)
92
96
  self.__socket.close()
97
+ self.__callback_handler.stop()
93
98
  self.__pool.shutdown(wait=True)
94
99
 
95
100
  def run(self, socket):
@@ -107,9 +112,9 @@ class Subscribe:
107
112
  elif protocol_version == 0:
108
113
  sub._updateProtocol0(buffer[4:], length - 4)
109
114
  else:
110
- print('Unknown protocol type: %d', protocol_version)
115
+ logger.error(f'Unknown protocol version: {protocol_version}')
111
116
 
112
- print('Subscribe connection closed')
117
+ logger.debug('Subscribe connection closed')
113
118
 
114
119
  def subscribe(self, param_list, group_alias, frq_divider=1):
115
120
  """Create a subscription group for a list of the parameters.
@@ -121,11 +126,11 @@ class Subscribe:
121
126
 
122
127
  Returns:
123
128
  Subscription: A subscription handle, which acts as a JavaScript Promise,
124
- it is resolved when subscription is ready or failed. After the subscription
125
- is ready the handle is used to retrieve latest data.
129
+ it is resolved when the subscription is ready or failed. After the subscription
130
+ is ready, the handle is used to retrieve the latest data.
126
131
  """
127
132
 
128
- subscription = Subscription(group_alias, self.__protobuf_types, frq_divider)
133
+ subscription = Subscription(group_alias, self.__protobuf_types, frq_divider, self.__pool)
129
134
  reply = self.__req.createGroup(param_list, group_alias, frq_divider)
130
135
  reply.then(self.__complete, subscription, self.__socket).catch(
131
136
  subscription._failed)
@@ -1,13 +1,13 @@
1
1
  #!/usr/bin/python3
2
2
 
3
3
  #
4
- # Developer : Alexey Zakharov (alexey.zakharov@vectioneer.com)
5
- # All rights reserved. Copyright (c) 2016 VECTIONEER.
4
+ # Developer: Alexey Zakharov (alexey.zakharov@vectioneer.com)
5
+ # All rights reserved. Copyright (c) 2016-2025 VECTIONEER.
6
6
  #
7
7
 
8
8
  from collections import namedtuple
9
9
  from struct import unpack_from
10
- from concurrent.futures import Future, ThreadPoolExecutor
10
+ from concurrent.futures import Future
11
11
  import time
12
12
 
13
13
  timespec = namedtuple('timespec', 'sec, nsec')
@@ -110,18 +110,17 @@ class Subscription(object):
110
110
  notifies on every update or could be used as polling.
111
111
  """
112
112
 
113
- def __init__(self, group_alias, protobuf_types, frq_divider):
113
+ def __init__(self, group_alias, protobuf_types, frq_divider, pool):
114
114
  self.__info = None
115
115
  self.__group_alias = group_alias
116
116
  self.__protobuf_types = protobuf_types
117
117
  self.__decoder = []
118
- self.__clb_list = []
119
118
  self.__future = Future()
120
119
  self.__values = None
121
120
  self.__layout = None
122
121
  self.__is_complete = False
123
122
  self.__observer_list = []
124
- self.__pool = None
123
+ self.__pool = pool
125
124
  self.__frq_divider = frq_divider
126
125
 
127
126
  def id(self):
@@ -164,7 +163,7 @@ class Subscription(object):
164
163
  def done(self):
165
164
  """
166
165
  Returns:
167
- bool: True if the call was successfully cancelled or finished running.
166
+ bool: True if the call was successfully canceled or finished running.
168
167
 
169
168
  Examples:
170
169
  >>> subscription = sub.subscribe("root/logger/logOut", "log")
@@ -176,7 +175,7 @@ class Subscription(object):
176
175
  def get(self, timeout_sec=1.0):
177
176
  """
178
177
  Returns:
179
- bool: StatusMsg if the call was successfully, None if timeout happened.
178
+ bool: StatusMsg if the call was successful, None if timeout happened.
180
179
 
181
180
  Examples:
182
181
  >>> subscription = sub.subscribe("root/logger/logOut", "log")
@@ -186,10 +185,10 @@ class Subscription(object):
186
185
  return self.__future.result(timeout_sec)
187
186
 
188
187
  def then(self, subscribed_clb):
189
- """JavaScript-like promise, which is resolved when subscription is completed.
188
+ """JavaScript-like promise, which is resolved when the subscription is completed.
190
189
 
191
190
  Args:
192
- subscribed_clb: callback which is resolved when subscription is completed.
191
+ subscribed_clb: callback which is resolved when the subscription is completed.
193
192
 
194
193
  Returns:
195
194
  self pointer to add 'catch' callback
@@ -208,7 +207,7 @@ class Subscription(object):
208
207
  """JavaScript-like promise, which is resolved when subscription has failed.
209
208
 
210
209
  Args:
211
- failed: callback which is resolved when subscription has failed
210
+ failed: callback which is resolved when the subscription has failed
212
211
 
213
212
  Returns:
214
213
  self pointer to add 'then' callback
@@ -238,7 +237,6 @@ class Subscription(object):
238
237
 
239
238
  """
240
239
  self.__observer_list = observer_list if type(observer_list) is list else [observer_list]
241
- self.__pool = ThreadPoolExecutor(len(self.__observer_list))
242
240
 
243
241
  def _complete(self, msg):
244
242
  self.__decoder = []
@@ -0,0 +1 @@
1
+ __version__ = '0.23.0'
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: motorcortex-python
3
- Version: 0.22.9
3
+ Version: 0.23.0
4
4
  Summary: Python bindings for Motorcortex Engine
5
5
  Home-page: https://www.motorcortex.io
6
6
  Author: Alexey Zakharov
@@ -10,6 +10,7 @@ motorcortex/parameter_tree.py
10
10
  motorcortex/reply.py
11
11
  motorcortex/request.py
12
12
  motorcortex/setup_logger.py
13
+ motorcortex/state_callback_handler.py
13
14
  motorcortex/subscribe.py
14
15
  motorcortex/subscription.py
15
16
  motorcortex/version.py
@@ -1,2 +1,2 @@
1
1
  protobuf==3.20.*
2
- pynng==0.7.*
2
+ pynng==0.8.*
@@ -23,7 +23,7 @@ setup(name='motorcortex-python',
23
23
  url='https://www.motorcortex.io',
24
24
  license='MIT',
25
25
  packages=['motorcortex'],
26
- install_requires=['pynng==0.7.*',
26
+ install_requires=['pynng==0.8.*',
27
27
  'protobuf==3.20.*'],
28
28
  include_package_data=True,
29
29
  )
@@ -1 +0,0 @@
1
- __version__ = '0.22.9'