dimples 1.2.1__tar.gz → 1.2.3__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 (144) hide show
  1. {dimples-1.2.1 → dimples-1.2.3}/PKG-INFO +1 -1
  2. {dimples-1.2.1 → dimples-1.2.3}/dimples/client/network/session.py +2 -2
  3. {dimples-1.2.1 → dimples-1.2.3}/dimples/client/terminal.py +2 -0
  4. {dimples-1.2.1 → dimples-1.2.3}/dimples/conn/gatekeeper.py +0 -20
  5. {dimples-1.2.1 → dimples-1.2.3}/dimples/database/dos/base.py +10 -10
  6. {dimples-1.2.1 → dimples-1.2.3}/dimples/database/dos/document.py +3 -3
  7. {dimples-1.2.1 → dimples-1.2.3}/dimples/database/dos/group.py +6 -6
  8. {dimples-1.2.1 → dimples-1.2.3}/dimples/database/dos/group_history.py +2 -2
  9. {dimples-1.2.1 → dimples-1.2.3}/dimples/database/dos/group_keys.py +2 -2
  10. {dimples-1.2.1 → dimples-1.2.3}/dimples/database/dos/login.py +2 -2
  11. {dimples-1.2.1 → dimples-1.2.3}/dimples/database/dos/meta.py +2 -2
  12. {dimples-1.2.1 → dimples-1.2.3}/dimples/database/dos/private.py +14 -14
  13. {dimples-1.2.1 → dimples-1.2.3}/dimples/database/dos/station.py +13 -13
  14. {dimples-1.2.1 → dimples-1.2.3}/dimples/database/dos/user.py +2 -2
  15. {dimples-1.2.1 → dimples-1.2.3}/dimples/database/t_meta.py +1 -1
  16. {dimples-1.2.1 → dimples-1.2.3}/dimples/edge/octopus.py +0 -8
  17. {dimples-1.2.1 → dimples-1.2.3}/dimples/edge/shared.py +26 -6
  18. {dimples-1.2.1 → dimples-1.2.3}/dimples/edge/start.py +7 -3
  19. {dimples-1.2.1 → dimples-1.2.3}/dimples/group/helper.py +1 -1
  20. {dimples-1.2.1 → dimples-1.2.3}/dimples/register/run.py +7 -3
  21. {dimples-1.2.1 → dimples-1.2.3}/dimples/server/archivist.py +3 -2
  22. {dimples-1.2.1 → dimples-1.2.3}/dimples/server/dispatcher.py +0 -8
  23. {dimples-1.2.1 → dimples-1.2.3}/dimples/server/push.py +0 -8
  24. {dimples-1.2.1 → dimples-1.2.3}/dimples/server/session.py +17 -10
  25. {dimples-1.2.1 → dimples-1.2.3}/dimples/station/handler.py +1 -0
  26. {dimples-1.2.1 → dimples-1.2.3}/dimples/station/shared.py +26 -6
  27. {dimples-1.2.1 → dimples-1.2.3}/dimples/station/start.py +7 -3
  28. {dimples-1.2.1 → dimples-1.2.3}/dimples/utils/__init__.py +2 -1
  29. {dimples-1.2.1 → dimples-1.2.3}/dimples/utils/cache.py +0 -8
  30. {dimples-1.2.1 → dimples-1.2.3}/dimples.egg-info/PKG-INFO +1 -1
  31. {dimples-1.2.1 → dimples-1.2.3}/dimples.egg-info/SOURCES.txt +0 -1
  32. {dimples-1.2.1 → dimples-1.2.3}/dimples.egg-info/requires.txt +1 -0
  33. {dimples-1.2.1 → dimples-1.2.3}/setup.py +3 -1
  34. dimples-1.2.1/dimples/utils/dos.py +0 -227
  35. {dimples-1.2.1 → dimples-1.2.3}/README.md +0 -0
  36. {dimples-1.2.1 → dimples-1.2.3}/dimples/__init__.py +0 -0
  37. {dimples-1.2.1 → dimples-1.2.3}/dimples/client/__init__.py +0 -0
  38. {dimples-1.2.1 → dimples-1.2.3}/dimples/client/archivist.py +0 -0
  39. {dimples-1.2.1 → dimples-1.2.3}/dimples/client/checkpoint.py +0 -0
  40. {dimples-1.2.1 → dimples-1.2.3}/dimples/client/cpu/__init__.py +0 -0
  41. {dimples-1.2.1 → dimples-1.2.3}/dimples/client/cpu/commands.py +0 -0
  42. {dimples-1.2.1 → dimples-1.2.3}/dimples/client/cpu/creator.py +0 -0
  43. {dimples-1.2.1 → dimples-1.2.3}/dimples/client/cpu/group.py +0 -0
  44. {dimples-1.2.1 → dimples-1.2.3}/dimples/client/cpu/grp_expel.py +0 -0
  45. {dimples-1.2.1 → dimples-1.2.3}/dimples/client/cpu/grp_invite.py +0 -0
  46. {dimples-1.2.1 → dimples-1.2.3}/dimples/client/cpu/grp_join.py +0 -0
  47. {dimples-1.2.1 → dimples-1.2.3}/dimples/client/cpu/grp_query.py +0 -0
  48. {dimples-1.2.1 → dimples-1.2.3}/dimples/client/cpu/grp_quit.py +0 -0
  49. {dimples-1.2.1 → dimples-1.2.3}/dimples/client/cpu/grp_reset.py +0 -0
  50. {dimples-1.2.1 → dimples-1.2.3}/dimples/client/cpu/grp_resign.py +0 -0
  51. {dimples-1.2.1 → dimples-1.2.3}/dimples/client/cpu/handshake.py +0 -0
  52. {dimples-1.2.1 → dimples-1.2.3}/dimples/client/facebook.py +0 -0
  53. {dimples-1.2.1 → dimples-1.2.3}/dimples/client/messenger.py +0 -0
  54. {dimples-1.2.1 → dimples-1.2.3}/dimples/client/network/__init__.py +0 -0
  55. {dimples-1.2.1 → dimples-1.2.3}/dimples/client/network/state.py +0 -0
  56. {dimples-1.2.1 → dimples-1.2.3}/dimples/client/network/transition.py +0 -0
  57. {dimples-1.2.1 → dimples-1.2.3}/dimples/client/packer.py +0 -0
  58. {dimples-1.2.1 → dimples-1.2.3}/dimples/client/processor.py +0 -0
  59. {dimples-1.2.1 → dimples-1.2.3}/dimples/common/__init__.py +0 -0
  60. {dimples-1.2.1 → dimples-1.2.3}/dimples/common/anonymous.py +0 -0
  61. {dimples-1.2.1 → dimples-1.2.3}/dimples/common/ans.py +0 -0
  62. {dimples-1.2.1 → dimples-1.2.3}/dimples/common/archivist.py +0 -0
  63. {dimples-1.2.1 → dimples-1.2.3}/dimples/common/compat/__init__.py +0 -0
  64. {dimples-1.2.1 → dimples-1.2.3}/dimples/common/compat/btc.py +0 -0
  65. {dimples-1.2.1 → dimples-1.2.3}/dimples/common/compat/compatible.py +0 -0
  66. {dimples-1.2.1 → dimples-1.2.3}/dimples/common/compat/entity.py +0 -0
  67. {dimples-1.2.1 → dimples-1.2.3}/dimples/common/compat/meta.py +0 -0
  68. {dimples-1.2.1 → dimples-1.2.3}/dimples/common/compat/network.py +0 -0
  69. {dimples-1.2.1 → dimples-1.2.3}/dimples/common/dbi/__init__.py +0 -0
  70. {dimples-1.2.1 → dimples-1.2.3}/dimples/common/dbi/account.py +0 -0
  71. {dimples-1.2.1 → dimples-1.2.3}/dimples/common/dbi/message.py +0 -0
  72. {dimples-1.2.1 → dimples-1.2.3}/dimples/common/dbi/session.py +0 -0
  73. {dimples-1.2.1 → dimples-1.2.3}/dimples/common/facebook.py +0 -0
  74. {dimples-1.2.1 → dimples-1.2.3}/dimples/common/messenger.py +0 -0
  75. {dimples-1.2.1 → dimples-1.2.3}/dimples/common/packer.py +0 -0
  76. {dimples-1.2.1 → dimples-1.2.3}/dimples/common/processer.py +0 -0
  77. {dimples-1.2.1 → dimples-1.2.3}/dimples/common/protocol/__init__.py +0 -0
  78. {dimples-1.2.1 → dimples-1.2.3}/dimples/common/protocol/ans.py +0 -0
  79. {dimples-1.2.1 → dimples-1.2.3}/dimples/common/protocol/block.py +0 -0
  80. {dimples-1.2.1 → dimples-1.2.3}/dimples/common/protocol/handshake.py +0 -0
  81. {dimples-1.2.1 → dimples-1.2.3}/dimples/common/protocol/login.py +0 -0
  82. {dimples-1.2.1 → dimples-1.2.3}/dimples/common/protocol/mute.py +0 -0
  83. {dimples-1.2.1 → dimples-1.2.3}/dimples/common/protocol/report.py +0 -0
  84. {dimples-1.2.1 → dimples-1.2.3}/dimples/common/register.py +0 -0
  85. {dimples-1.2.1 → dimples-1.2.3}/dimples/common/session.py +0 -0
  86. {dimples-1.2.1 → dimples-1.2.3}/dimples/conn/__init__.py +0 -0
  87. {dimples-1.2.1 → dimples-1.2.3}/dimples/conn/flexible.py +0 -0
  88. {dimples-1.2.1 → dimples-1.2.3}/dimples/conn/gate.py +0 -0
  89. {dimples-1.2.1 → dimples-1.2.3}/dimples/conn/mars.py +0 -0
  90. {dimples-1.2.1 → dimples-1.2.3}/dimples/conn/mtp.py +0 -0
  91. {dimples-1.2.1 → dimples-1.2.3}/dimples/conn/protocol/__init__.py +0 -0
  92. {dimples-1.2.1 → dimples-1.2.3}/dimples/conn/protocol/mars.py +0 -0
  93. {dimples-1.2.1 → dimples-1.2.3}/dimples/conn/protocol/ws.py +0 -0
  94. {dimples-1.2.1 → dimples-1.2.3}/dimples/conn/queue.py +0 -0
  95. {dimples-1.2.1 → dimples-1.2.3}/dimples/conn/seeker.py +0 -0
  96. {dimples-1.2.1 → dimples-1.2.3}/dimples/conn/session.py +0 -0
  97. {dimples-1.2.1 → dimples-1.2.3}/dimples/conn/ws.py +0 -0
  98. {dimples-1.2.1 → dimples-1.2.3}/dimples/database/__init__.py +0 -0
  99. {dimples-1.2.1 → dimples-1.2.3}/dimples/database/account.py +0 -0
  100. {dimples-1.2.1 → dimples-1.2.3}/dimples/database/dos/__init__.py +0 -0
  101. {dimples-1.2.1 → dimples-1.2.3}/dimples/database/message.py +0 -0
  102. {dimples-1.2.1 → dimples-1.2.3}/dimples/database/session.py +0 -0
  103. {dimples-1.2.1 → dimples-1.2.3}/dimples/database/t_cipherkey.py +0 -0
  104. {dimples-1.2.1 → dimples-1.2.3}/dimples/database/t_document.py +0 -0
  105. {dimples-1.2.1 → dimples-1.2.3}/dimples/database/t_group.py +0 -0
  106. {dimples-1.2.1 → dimples-1.2.3}/dimples/database/t_group_history.py +0 -0
  107. {dimples-1.2.1 → dimples-1.2.3}/dimples/database/t_group_keys.py +0 -0
  108. {dimples-1.2.1 → dimples-1.2.3}/dimples/database/t_login.py +0 -0
  109. {dimples-1.2.1 → dimples-1.2.3}/dimples/database/t_message.py +0 -0
  110. {dimples-1.2.1 → dimples-1.2.3}/dimples/database/t_private.py +0 -0
  111. {dimples-1.2.1 → dimples-1.2.3}/dimples/database/t_station.py +0 -0
  112. {dimples-1.2.1 → dimples-1.2.3}/dimples/database/t_user.py +0 -0
  113. {dimples-1.2.1 → dimples-1.2.3}/dimples/edge/__init__.py +0 -0
  114. {dimples-1.2.1 → dimples-1.2.3}/dimples/group/__init__.py +0 -0
  115. {dimples-1.2.1 → dimples-1.2.3}/dimples/group/admin.py +0 -0
  116. {dimples-1.2.1 → dimples-1.2.3}/dimples/group/builder.py +0 -0
  117. {dimples-1.2.1 → dimples-1.2.3}/dimples/group/delegate.py +0 -0
  118. {dimples-1.2.1 → dimples-1.2.3}/dimples/group/emitter.py +0 -0
  119. {dimples-1.2.1 → dimples-1.2.3}/dimples/group/manager.py +0 -0
  120. {dimples-1.2.1 → dimples-1.2.3}/dimples/group/packer.py +0 -0
  121. {dimples-1.2.1 → dimples-1.2.3}/dimples/register/__init__.py +0 -0
  122. {dimples-1.2.1 → dimples-1.2.3}/dimples/register/base.py +0 -0
  123. {dimples-1.2.1 → dimples-1.2.3}/dimples/register/ext.py +0 -0
  124. {dimples-1.2.1 → dimples-1.2.3}/dimples/register/shared.py +0 -0
  125. {dimples-1.2.1 → dimples-1.2.3}/dimples/server/__init__.py +0 -0
  126. {dimples-1.2.1 → dimples-1.2.3}/dimples/server/cpu/__init__.py +0 -0
  127. {dimples-1.2.1 → dimples-1.2.3}/dimples/server/cpu/ans.py +0 -0
  128. {dimples-1.2.1 → dimples-1.2.3}/dimples/server/cpu/document.py +0 -0
  129. {dimples-1.2.1 → dimples-1.2.3}/dimples/server/cpu/handshake.py +0 -0
  130. {dimples-1.2.1 → dimples-1.2.3}/dimples/server/cpu/login.py +0 -0
  131. {dimples-1.2.1 → dimples-1.2.3}/dimples/server/cpu/report.py +0 -0
  132. {dimples-1.2.1 → dimples-1.2.3}/dimples/server/messenger.py +0 -0
  133. {dimples-1.2.1 → dimples-1.2.3}/dimples/server/packer.py +0 -0
  134. {dimples-1.2.1 → dimples-1.2.3}/dimples/server/processor.py +0 -0
  135. {dimples-1.2.1 → dimples-1.2.3}/dimples/server/session_center.py +0 -0
  136. {dimples-1.2.1 → dimples-1.2.3}/dimples/server/trace.py +0 -0
  137. {dimples-1.2.1 → dimples-1.2.3}/dimples/station/__init__.py +0 -0
  138. {dimples-1.2.1 → dimples-1.2.3}/dimples/utils/config.py +0 -0
  139. {dimples-1.2.1 → dimples-1.2.3}/dimples/utils/log.py +0 -0
  140. {dimples-1.2.1 → dimples-1.2.3}/dimples/utils/runner.py +0 -0
  141. {dimples-1.2.1 → dimples-1.2.3}/dimples.egg-info/dependency_links.txt +0 -0
  142. {dimples-1.2.1 → dimples-1.2.3}/dimples.egg-info/entry_points.txt +0 -0
  143. {dimples-1.2.1 → dimples-1.2.3}/dimples.egg-info/top_level.txt +0 -0
  144. {dimples-1.2.1 → dimples-1.2.3}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: dimples
3
- Version: 1.2.1
3
+ Version: 1.2.3
4
4
  Summary: DIMP Library for Edges and Stations
5
5
  Home-page: https://github.com/dimchat/demo-py
6
6
  Author: Albert Moky
@@ -147,7 +147,7 @@ class ClientSession(BaseSession):
147
147
 
148
148
  # Override
149
149
  async def docker_status_changed(self, previous: DockerStatus, current: DockerStatus, docker: Docker):
150
- # super().docker_status_changed(previous=previous, current=current, docker=docker)
150
+ # await super().docker_status_changed(previous=previous, current=current, docker=docker)
151
151
  if current is None or current == DockerStatus.ERROR:
152
152
  # connection error or session finished
153
153
  self.set_active(active=False)
@@ -159,7 +159,7 @@ class ClientSession(BaseSession):
159
159
 
160
160
  # Override
161
161
  async def docker_received(self, ship: Arrival, docker: Docker):
162
- # super().docker_received(ship=ship, docker=docker)
162
+ # await super().docker_received(ship=ship, docker=docker)
163
163
  all_responses = []
164
164
  messenger = self.messenger
165
165
  # 1. get data packages from arrival ship's payload
@@ -75,6 +75,7 @@ class Terminal(Runner, DeviceMixin, Logging, StateDelegate):
75
75
 
76
76
  # Override
77
77
  async def setup(self):
78
+ await super().setup()
78
79
  session = self.session
79
80
  session.fsm.delegate = self
80
81
  await session.start()
@@ -82,6 +83,7 @@ class Terminal(Runner, DeviceMixin, Logging, StateDelegate):
82
83
  # Override
83
84
  async def finish(self):
84
85
  await self.session.stop()
86
+ await super().finish()
85
87
 
86
88
  # Override
87
89
  async def process(self) -> bool:
@@ -220,26 +220,6 @@ class GateKeeper(Runner, DockerDelegate, Logging):
220
220
  self.__last_active = when
221
221
  return True
222
222
 
223
- # @property # Override
224
- # def running(self) -> bool:
225
- # if super().running:
226
- # return self.gate.running
227
- #
228
- # # Override
229
- # async def stop(self):
230
- # await super().stop()
231
- # await self.gate.stop()
232
-
233
- # Override
234
- async def setup(self):
235
- # await self.gate.start()
236
- pass
237
-
238
- # Override
239
- async def finish(self):
240
- # await self.gate.stop()
241
- pass
242
-
243
223
  # Override
244
224
  async def process(self) -> bool:
245
225
  gate = self.gate
@@ -85,37 +85,37 @@ class Storage:
85
85
  return Path.join(self._public, template)
86
86
 
87
87
  @classmethod
88
- def read_text(cls, path: str) -> Optional[str]:
88
+ async def read_text(cls, path: str) -> Optional[str]:
89
89
  try:
90
- return TextFile(path=path).read()
90
+ return await TextFile(path=path).read()
91
91
  except Exception as error:
92
92
  Log.error(msg='Storage >\t%s' % error)
93
93
 
94
94
  @classmethod
95
- def read_json(cls, path: str) -> Union[dict, list, None]:
95
+ async def read_json(cls, path: str) -> Union[dict, list, None]:
96
96
  try:
97
- return JSONFile(path=path).read()
97
+ return await JSONFile(path=path).read()
98
98
  except Exception as error:
99
99
  Log.error(msg='Storage >\t%s' % error)
100
100
 
101
101
  @classmethod
102
- def write_text(cls, text: str, path: str) -> bool:
102
+ async def write_text(cls, text: str, path: str) -> bool:
103
103
  try:
104
- return TextFile(path=path).write(text=text)
104
+ return await TextFile(path=path).write(text=text)
105
105
  except Exception as error:
106
106
  Log.error(msg='Storage >\t%s' % error)
107
107
 
108
108
  @classmethod
109
- def write_json(cls, container: Union[dict, list], path: str) -> bool:
109
+ async def write_json(cls, container: Union[dict, list], path: str) -> bool:
110
110
  try:
111
- return JSONFile(path=path).write(container=container)
111
+ return await JSONFile(path=path).write(container=container)
112
112
  except Exception as error:
113
113
  Log.error(msg='Storage >\t%s' % error)
114
114
 
115
115
  @classmethod
116
- def append_text(cls, text: str, path: str) -> bool:
116
+ async def append_text(cls, text: str, path: str) -> bool:
117
117
  try:
118
- return TextFile(path=path).append(text=text)
118
+ return await TextFile(path=path).append(text=text)
119
119
  except Exception as error:
120
120
  Log.error(msg='Storage >\t%s' % error)
121
121
 
@@ -63,13 +63,13 @@ class DocumentStorage(Storage, DocumentDBI):
63
63
  for doc in documents:
64
64
  assert doc.identifier == identifier, 'document ID not matched: %s, %s' % (identifier, doc)
65
65
  array.append(doc.dictionary)
66
- return self.write_json(container=array, path=path)
66
+ return await self.write_json(container=array, path=path)
67
67
 
68
68
  async def load_documents(self, identifier: ID) -> Optional[List[Document]]:
69
69
  """ load documents from file """
70
70
  path = self.__all_path(identifier=identifier)
71
71
  self.info(msg='Loading documents from: %s' % path)
72
- array = self.read_json(path=path)
72
+ array = await self.read_json(path=path)
73
73
  if array is None:
74
74
  # file not found
75
75
  return None
@@ -86,7 +86,7 @@ class DocumentStorage(Storage, DocumentDBI):
86
86
  """ load document from file """
87
87
  path = self.__doc_path(identifier=identifier)
88
88
  self.info(msg='Loading document from: %s' % path)
89
- info = self.read_json(path=path)
89
+ info = await self.read_json(path=path)
90
90
  if info is not None:
91
91
  return parse_document(dictionary=info, identifier=identifier)
92
92
 
@@ -84,7 +84,7 @@ class GroupStorage(Storage, GroupDBI):
84
84
  """ load members from file """
85
85
  path = self.__members_path(identifier=group)
86
86
  self.info(msg='Loading members from: %s' % path)
87
- users = self.read_json(path=path)
87
+ users = await self.read_json(path=path)
88
88
  if users is None:
89
89
  # members not found
90
90
  return []
@@ -95,14 +95,14 @@ class GroupStorage(Storage, GroupDBI):
95
95
  """ save members into file """
96
96
  path = self.__members_path(identifier=group)
97
97
  self.info(msg='Saving members into: %s' % path)
98
- return self.write_json(container=ID.revert(array=members), path=path)
98
+ return await self.write_json(container=ID.revert(array=members), path=path)
99
99
 
100
100
  # Override
101
101
  async def get_assistants(self, group: ID) -> List[ID]:
102
102
  """ load assistants from file """
103
103
  path = self.__assistants_path(identifier=group)
104
104
  self.info(msg='Loading assistants from: %s' % path)
105
- bots = self.read_json(path=path)
105
+ bots = await self.read_json(path=path)
106
106
  if bots is None:
107
107
  # assistants not found
108
108
  return []
@@ -113,14 +113,14 @@ class GroupStorage(Storage, GroupDBI):
113
113
  """ save assistants into file """
114
114
  path = self.__assistants_path(identifier=group)
115
115
  self.info(msg='Saving assistants into: %s' % path)
116
- return self.write_json(container=ID.revert(array=assistants), path=path)
116
+ return await self.write_json(container=ID.revert(array=assistants), path=path)
117
117
 
118
118
  # Override
119
119
  async def get_administrators(self, group: ID) -> List[ID]:
120
120
  """ load administrators from file """
121
121
  path = self.__administrators_path(identifier=group)
122
122
  self.info(msg='Loading administrators from: %s' % path)
123
- users = self.read_json(path=path)
123
+ users = await self.read_json(path=path)
124
124
  if users is None:
125
125
  # administrators not found
126
126
  return []
@@ -131,4 +131,4 @@ class GroupStorage(Storage, GroupDBI):
131
131
  """ save administrators into file """
132
132
  path = self.__administrators_path(identifier=group)
133
133
  self.info(msg='Saving administrators into: %s' % path)
134
- return self.write_json(container=ID.revert(array=administrators), path=path)
134
+ return await self.write_json(container=ID.revert(array=administrators), path=path)
@@ -57,7 +57,7 @@ class GroupHistoryStorage(Storage, GroupHistoryDBI):
57
57
  async def load_group_histories(self, group: ID) -> List[Tuple[GroupCommand, ReliableMessage]]:
58
58
  path = self.__history_path(group=group)
59
59
  self.info(msg='Loading group history from: %s' % path)
60
- array = self.read_json(path=path)
60
+ array = await self.read_json(path=path)
61
61
  if array is None:
62
62
  # history not found
63
63
  return []
@@ -88,7 +88,7 @@ class GroupHistoryStorage(Storage, GroupHistoryDBI):
88
88
  array.append(item)
89
89
  path = self.__history_path(group=group)
90
90
  self.info(msg='Saving %d group history(ies) into: %s' % (len(histories), path))
91
- return self.write_json(container=array, path=path)
91
+ return await self.write_json(container=array, path=path)
92
92
 
93
93
  #
94
94
  # Group History DBI
@@ -61,11 +61,11 @@ class GroupKeysStorage(Storage, GroupKeysDBI):
61
61
  """ load group keys from file """
62
62
  path = self.__keys_path(group=group, sender=sender)
63
63
  self.info(msg='Loading group keys from: %s' % path)
64
- return self.read_json(path=path)
64
+ return await self.read_json(path=path)
65
65
 
66
66
  # Override
67
67
  async def save_group_keys(self, group: ID, sender: ID, keys: Dict[str, str]) -> bool:
68
68
  """ save group keys into file """
69
69
  path = self.__keys_path(group=group, sender=sender)
70
70
  self.info(msg='Saving group keys into: %s' % path)
71
- return self.write_json(container=keys, path=path)
71
+ return await self.write_json(container=keys, path=path)
@@ -60,7 +60,7 @@ class LoginStorage(Storage, LoginDBI):
60
60
  """ load login command from file """
61
61
  path = self.__login_path(identifier=user)
62
62
  self.info(msg='Loading login command from: %s' % path)
63
- info = self.read_json(path=path)
63
+ info = await self.read_json(path=path)
64
64
  if info is None:
65
65
  # command not found
66
66
  return None, None
@@ -79,4 +79,4 @@ class LoginStorage(Storage, LoginDBI):
79
79
  }
80
80
  path = self.__login_path(identifier=user)
81
81
  self.info(msg='Saving login command into: %s' % path)
82
- return self.write_json(container=info, path=path)
82
+ return await self.write_json(container=info, path=path)
@@ -58,13 +58,13 @@ class MetaStorage(Storage, MetaDBI):
58
58
  """ save meta into file """
59
59
  path = self.__meta_path(identifier=identifier)
60
60
  self.info(msg='Saving meta into: %s' % path)
61
- return self.write_json(container=meta.dictionary, path=path)
61
+ return await self.write_json(container=meta.dictionary, path=path)
62
62
 
63
63
  # Override
64
64
  async def get_meta(self, identifier: ID) -> Optional[Meta]:
65
65
  """ load meta from file """
66
66
  path = self.__meta_path(identifier=identifier)
67
67
  self.info(msg='Loading meta from: %s' % path)
68
- info = self.read_json(path=path)
68
+ info = await self.read_json(path=path)
69
69
  if info is not None:
70
70
  return Meta.parse(meta=info)
@@ -67,20 +67,20 @@ class PrivateKeyStorage(Storage, PrivateKeyDBI):
67
67
  path = self.private_path(self.msg_keys_path)
68
68
  return template_replace(path, key='ADDRESS', value=str(identifier.address))
69
69
 
70
- def _save_id_key(self, key: PrivateKey, identifier: ID) -> bool:
70
+ async def _save_id_key(self, key: PrivateKey, identifier: ID) -> bool:
71
71
  path = self.__id_key_path(identifier=identifier)
72
72
  self.info(msg='Saving identity private key into: %s' % path)
73
- return self.write_json(container=key.dictionary, path=path)
73
+ return await self.write_json(container=key.dictionary, path=path)
74
74
 
75
- def _load_id_key(self, identifier: ID) -> Optional[PrivateKey]:
75
+ async def _load_id_key(self, identifier: ID) -> Optional[PrivateKey]:
76
76
  path = self.__id_key_path(identifier=identifier)
77
77
  self.info(msg='Loading identity private key from: %s' % path)
78
- info = self.read_json(path=path)
78
+ info = await self.read_json(path=path)
79
79
  if info is not None:
80
80
  return PrivateKey.parse(key=info)
81
81
 
82
- def _save_msg_key(self, key: PrivateKey, identifier: ID) -> bool:
83
- private_keys = self._load_msg_keys(identifier=identifier)
82
+ async def _save_msg_key(self, key: PrivateKey, identifier: ID) -> bool:
83
+ private_keys = await self._load_msg_keys(identifier=identifier)
84
84
  private_keys = PrivateKeyDBI.insert(item=key, array=private_keys)
85
85
  if private_keys is None:
86
86
  # nothing changed
@@ -88,13 +88,13 @@ class PrivateKeyStorage(Storage, PrivateKeyDBI):
88
88
  plain = [item.dictionary for item in private_keys]
89
89
  path = self.__msg_keys_path(identifier=identifier)
90
90
  self.info(msg='Saving message private keys into: %s' % path)
91
- return self.write_json(container=plain, path=path)
91
+ return await self.write_json(container=plain, path=path)
92
92
 
93
- def _load_msg_keys(self, identifier: ID) -> List[PrivateKey]:
93
+ async def _load_msg_keys(self, identifier: ID) -> List[PrivateKey]:
94
94
  keys = []
95
95
  path = self.__msg_keys_path(identifier=identifier)
96
96
  self.info(msg='Loading message private keys from: %s' % path)
97
- array = self.read_json(path=path)
97
+ array = await self.read_json(path=path)
98
98
  if array is not None:
99
99
  for item in array:
100
100
  k = PrivateKey.parse(key=item)
@@ -110,17 +110,17 @@ class PrivateKeyStorage(Storage, PrivateKeyDBI):
110
110
  async def save_private_key(self, key: PrivateKey, user: ID, key_type: str = 'M') -> bool:
111
111
  if key_type == self.ID_KEY_TAG:
112
112
  # save private key for meta
113
- return self._save_id_key(key=key, identifier=user)
113
+ return await self._save_id_key(key=key, identifier=user)
114
114
  else:
115
115
  # save private key for visa
116
- return self._save_msg_key(key=key, identifier=user)
116
+ return await self._save_msg_key(key=key, identifier=user)
117
117
 
118
118
  # Override
119
119
  async def private_keys_for_decryption(self, user: ID) -> List[DecryptKey]:
120
- keys: list = self._load_msg_keys(identifier=user)
120
+ keys: list = await self._load_msg_keys(identifier=user)
121
121
  # the 'ID key' could be used for encrypting message too (RSA),
122
122
  # so we append it to the decrypt keys here
123
- id_key = self._load_id_key(identifier=user)
123
+ id_key = await self._load_id_key(identifier=user)
124
124
  if isinstance(id_key, DecryptKey) and PrivateKeyDBI.find(item=id_key, array=keys) < 0:
125
125
  keys.append(id_key)
126
126
  return keys
@@ -132,4 +132,4 @@ class PrivateKeyStorage(Storage, PrivateKeyDBI):
132
132
 
133
133
  # Override
134
134
  async def private_key_for_visa_signature(self, user: ID) -> Optional[SignKey]:
135
- return self._load_id_key(identifier=user)
135
+ return await self._load_id_key(identifier=user)
@@ -67,17 +67,17 @@ class StationStorage(Storage, ProviderDBI, StationDBI):
67
67
  """ load providers from file """
68
68
  path = self.__providers_path()
69
69
  self.info(msg='Loading providers from: %s' % path)
70
- providers = self.read_json(path=path)
70
+ providers = await self.read_json(path=path)
71
71
  if providers is None:
72
72
  # service providers not found
73
73
  return []
74
74
  return ProviderInfo.convert(array=providers)
75
75
 
76
- def _save_providers(self, providers: List[ProviderInfo]) -> bool:
76
+ async def _save_providers(self, providers: List[ProviderInfo]) -> bool:
77
77
  """ save providers into file """
78
78
  path = self.__providers_path()
79
79
  self.info(msg='Saving providers into: %s' % path)
80
- return self.write_json(container=ProviderInfo.revert(array=providers), path=path)
80
+ return await self.write_json(container=ProviderInfo.revert(array=providers), path=path)
81
81
 
82
82
  # Override
83
83
  async def add_provider(self, identifier: ID, chosen: int = 0) -> bool:
@@ -88,7 +88,7 @@ class StationStorage(Storage, ProviderDBI, StationDBI):
88
88
  self.warning(msg='provider exists: %s, %s' % (identifier, providers))
89
89
  return True
90
90
  providers.insert(0, ProviderInfo(identifier=identifier, chosen=chosen))
91
- return self._save_providers(providers=providers)
91
+ return await self._save_providers(providers=providers)
92
92
 
93
93
  # Override
94
94
  async def update_provider(self, identifier: ID, chosen: int) -> bool:
@@ -107,7 +107,7 @@ class StationStorage(Storage, ProviderDBI, StationDBI):
107
107
  providers.insert(0, info)
108
108
  else:
109
109
  info.chosen = chosen
110
- return self._save_providers(providers=providers)
110
+ return await self._save_providers(providers=providers)
111
111
 
112
112
  # Override
113
113
  async def remove_provider(self, identifier: ID) -> bool:
@@ -120,7 +120,7 @@ class StationStorage(Storage, ProviderDBI, StationDBI):
120
120
  break
121
121
  if info is not None:
122
122
  providers.remove(info)
123
- return self._save_providers(providers=providers)
123
+ return await self._save_providers(providers=providers)
124
124
 
125
125
  #
126
126
  # Station DBI
@@ -131,17 +131,17 @@ class StationStorage(Storage, ProviderDBI, StationDBI):
131
131
  """ load stations with SP ID """
132
132
  path = self.__stations_path(provider=provider)
133
133
  self.info(msg='Loading stations from: %s' % path)
134
- stations = self.read_json(path=path)
134
+ stations = await self.read_json(path=path)
135
135
  if stations is None:
136
136
  # stations not found
137
137
  return []
138
138
  return StationInfo.convert(array=stations)
139
139
 
140
- def _save_stations(self, stations: List[StationInfo], provider: ID) -> bool:
140
+ async def _save_stations(self, stations: List[StationInfo], provider: ID) -> bool:
141
141
  """ save stations into file """
142
142
  path = self.__stations_path(provider=provider)
143
143
  self.info(msg='Saving stations into: %s' % path)
144
- return self.write_json(container=StationInfo.revert(array=stations), path=path)
144
+ return await self.write_json(container=StationInfo.revert(array=stations), path=path)
145
145
 
146
146
  # Override
147
147
  async def add_station(self, identifier: Optional[ID], host: str, port: int, provider: ID, chosen: int = 0) -> bool:
@@ -152,7 +152,7 @@ class StationStorage(Storage, ProviderDBI, StationDBI):
152
152
  self.warning(msg='station exists: %s, %d, %s' % (host, port, stations))
153
153
  return True
154
154
  stations.insert(0, StationInfo(identifier=identifier, host=host, port=port, provider=provider, chosen=chosen))
155
- return self._save_stations(stations=stations, provider=provider)
155
+ return await self._save_stations(stations=stations, provider=provider)
156
156
 
157
157
  # Override
158
158
  async def update_station(self, identifier: Optional[ID], host: str, port: int,
@@ -174,7 +174,7 @@ class StationStorage(Storage, ProviderDBI, StationDBI):
174
174
  if not (identifier is None or identifier.is_broadcast):
175
175
  info.identifier = identifier
176
176
  info.chosen = chosen
177
- return self._save_stations(stations=stations, provider=provider)
177
+ return await self._save_stations(stations=stations, provider=provider)
178
178
 
179
179
  # Override
180
180
  async def remove_station(self, host: str, port: int, provider: ID) -> bool:
@@ -187,7 +187,7 @@ class StationStorage(Storage, ProviderDBI, StationDBI):
187
187
  break
188
188
  if info is not None:
189
189
  stations.remove(info)
190
- return self._save_stations(stations=stations, provider=provider)
190
+ return await self._save_stations(stations=stations, provider=provider)
191
191
 
192
192
  # Override
193
193
  async def remove_stations(self, provider: ID) -> bool:
@@ -196,4 +196,4 @@ class StationStorage(Storage, ProviderDBI, StationDBI):
196
196
  if len(stations) == 0:
197
197
  # already empty
198
198
  return True
199
- return self._save_stations(stations=[], provider=provider)
199
+ return await self._save_stations(stations=[], provider=provider)
@@ -71,7 +71,7 @@ class UserStorage(Storage, UserDBI, ContactDBI):
71
71
  """ load contacts from file """
72
72
  path = self.__contacts_path(identifier=user)
73
73
  self.info(msg='Loading contacts from: %s' % path)
74
- contacts = self.read_json(path=path)
74
+ contacts = await self.read_json(path=path)
75
75
  if contacts is None:
76
76
  # contacts not found
77
77
  return []
@@ -82,4 +82,4 @@ class UserStorage(Storage, UserDBI, ContactDBI):
82
82
  """ save contacts into file """
83
83
  path = self.__contacts_path(identifier=user)
84
84
  self.info(msg='Saving contacts into: %s' % path)
85
- return self.write_json(container=ID.revert(array=contacts), path=path)
85
+ return await self.write_json(container=ID.revert(array=contacts), path=path)
@@ -84,7 +84,7 @@ class MetaTable(MetaDBI):
84
84
  async def save_meta(self, meta: Meta, identifier: ID) -> bool:
85
85
  # assert Meta.match_id(meta=meta, identifier=identifier), 'meta invalid: %s, %s' % (identifier, meta)
86
86
  # 0. check old record
87
- old = self.get_meta(identifier=identifier)
87
+ old = await self.get_meta(identifier=identifier)
88
88
  if old is not None:
89
89
  # meta exists, no need to update it
90
90
  return True
@@ -142,14 +142,6 @@ class Octopus(Runner, Logging):
142
142
  # 3. stop runner
143
143
  await super().stop()
144
144
 
145
- # Override
146
- async def setup(self):
147
- pass
148
-
149
- # Override
150
- async def finish(self):
151
- pass
152
-
153
145
  # Override
154
146
  async def process(self) -> bool:
155
147
  # get all neighbor stations
@@ -64,7 +64,7 @@ def show_help(cmd: str, app_name: str, default_config: str):
64
64
  print('')
65
65
 
66
66
 
67
- def create_config(app_name: str, default_config: str) -> Config:
67
+ async def create_config(app_name: str, default_config: str) -> Config:
68
68
  """ Step 1: load config """
69
69
  cmd = sys.argv[0]
70
70
  try:
@@ -85,7 +85,7 @@ def create_config(app_name: str, default_config: str) -> Config:
85
85
  # check config filepath
86
86
  if ini_file is None:
87
87
  ini_file = default_config
88
- if not Path.exists(path=ini_file):
88
+ if not await Path.exists(path=ini_file):
89
89
  show_help(cmd=cmd, app_name=app_name, default_config=default_config)
90
90
  print('')
91
91
  print('!!! config file not exists: %s' % ini_file)
@@ -110,14 +110,34 @@ async def create_database(config: Config) -> Tuple[AccountDBI, MessageDBI, Sessi
110
110
  adb.show_info()
111
111
  mdb.show_info()
112
112
  sdb.show_info()
113
- # update neighbor stations (default provider)
113
+ #
114
+ # Update neighbor stations (default provider)
115
+ #
114
116
  provider = ProviderInfo.GSP
115
117
  neighbors = config.neighbors
116
118
  if len(neighbors) > 0:
117
- await sdb.remove_stations(provider=provider)
119
+ # await sdb.remove_stations(provider=provider)
120
+ # 1. remove vanished neighbors
121
+ old_stations = await sdb.all_stations(provider=provider)
122
+ for old in old_stations:
123
+ found = False
124
+ for item in neighbors:
125
+ if item.port == old.port and item.host == old.host:
126
+ found = True
127
+ break
128
+ if not found:
129
+ print('removing neighbor station: %s' % old)
130
+ await sdb.remove_station(host=old.host, port=old.port, provider=provider)
131
+ # 2. add new neighbors
118
132
  for node in neighbors:
119
- print('adding neighbor node: %s' % node)
120
- await sdb.add_station(identifier=None, host=node.host, port=node.port, provider=provider)
133
+ found = False
134
+ for old in old_stations:
135
+ if old.port == node.port and old.host == node.host:
136
+ found = True
137
+ break
138
+ if not found:
139
+ print('adding neighbor node: %s' % node)
140
+ await sdb.add_station(identifier=None, host=node.host, port=node.port, provider=provider)
121
141
  return adb, mdb, sdb
122
142
 
123
143
 
@@ -53,11 +53,11 @@ Log.LEVEL = Log.DEVELOP
53
53
  DEFAULT_CONFIG = '/etc/dim/edge.ini'
54
54
 
55
55
 
56
- async def main():
56
+ async def async_main():
57
57
  # create global variable
58
58
  shared = GlobalVariable()
59
59
  # Step 1: load config
60
- config = create_config(app_name='DIM Network Edge', default_config=DEFAULT_CONFIG)
60
+ config = await create_config(app_name='DIM Network Edge', default_config=DEFAULT_CONFIG)
61
61
  shared.config = config
62
62
  # Step 2: create database
63
63
  adb, mdb, sdb = await create_database(config=config)
@@ -79,5 +79,9 @@ async def main():
79
79
  Log.warning(msg='bot stopped: %s' % octopus)
80
80
 
81
81
 
82
+ def main():
83
+ Runner.sync_run(main=async_main())
84
+
85
+
82
86
  if __name__ == '__main__':
83
- Runner.sync_run(main=main())
87
+ main()
@@ -114,7 +114,7 @@ class GroupCommandHelper(Logging):
114
114
  # membership command, check with reset command
115
115
  cmd, _ = await self.get_reset_command_message(group=group)
116
116
  if cmd is None: # or msg is None:
117
- self.error(msg='"reset" command not found: %s' % content)
117
+ self.info(msg='"reset" command not found: %s' % content)
118
118
  return False
119
119
  return is_before(old_time=cmd.time, new_time=content.time)
120
120
 
@@ -74,7 +74,7 @@ def show_help():
74
74
  print('')
75
75
 
76
76
 
77
- async def main():
77
+ async def async_main():
78
78
  try:
79
79
  opts, args = getopt.getopt(args=sys.argv[1:],
80
80
  shortopts='hf:',
@@ -93,7 +93,7 @@ async def main():
93
93
  # check config filepath
94
94
  if ini_file is None:
95
95
  ini_file = DEFAULT_CONFIG
96
- if not Path.exists(path=ini_file):
96
+ if not await Path.exists(path=ini_file):
97
97
  show_help()
98
98
  print('')
99
99
  print('!!! config file not exists: %s' % ini_file)
@@ -117,5 +117,9 @@ async def main():
117
117
  show_help()
118
118
 
119
119
 
120
+ def main():
121
+ Runner.sync_run(main=async_main())
122
+
123
+
120
124
  if __name__ == '__main__':
121
- Runner.sync_run(main=main())
125
+ main()
@@ -142,8 +142,9 @@ class ServerArchivist(CommonArchivist, ABC):
142
142
  # dispatch
143
143
  dispatcher = get_dispatcher()
144
144
  neighbors = await self.all_neighbors
145
- # avoid the new recipients redirect it to same targets
146
- r_msg['recipients'] = ID.revert(neighbors)
145
+ self.info(msg='broadcast command "%s" to neighbors: %s' % (command.cmd, neighbors))
146
+ # # avoid the new recipients redirect it to same targets
147
+ # r_msg['recipients'] = ID.revert(neighbors)
147
148
  for receiver in neighbors:
148
149
  if receiver == sid:
149
150
  self.debug(msg='skip cycled message: %s -> %s' % (sid, receiver))
@@ -310,14 +310,6 @@ class Roamer(Runner, Logging):
310
310
  self.__append(info=info)
311
311
  return True
312
312
 
313
- # Override
314
- async def setup(self):
315
- pass
316
-
317
- # Override
318
- async def finish(self):
319
- pass
320
-
321
313
  # Override
322
314
  async def process(self) -> bool:
323
315
  info = self.__next()
@@ -149,14 +149,6 @@ class PushCenter(Runner, Logging):
149
149
  queue = self.__queue
150
150
  queue.add_message(msg=msg)
151
151
 
152
- # Override
153
- async def setup(self):
154
- pass
155
-
156
- # Override
157
- async def finish(self):
158
- pass
159
-
160
152
  # Override
161
153
  async def process(self) -> bool:
162
154
  # 1. get waiting messages