dimp 2.3.0__tar.gz → 2.3.2__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 (52) hide show
  1. {dimp-2.3.0 → dimp-2.3.2}/PKG-INFO +1 -1
  2. {dimp-2.3.0 → dimp-2.3.2}/dimp/__init__.py +3 -2
  3. {dimp-2.3.0 → dimp-2.3.2}/dimp/crypto/keys.py +46 -21
  4. {dimp-2.3.0 → dimp-2.3.2}/dimp/crypto/pnf.py +11 -10
  5. {dimp-2.3.0 → dimp-2.3.2}/dimp/crypto/ted.py +26 -22
  6. {dimp-2.3.0 → dimp-2.3.2}/dimp/dkd/__init__.py +17 -16
  7. {dimp-2.3.0 → dimp-2.3.2}/dimp/mkm/docs.py +19 -15
  8. {dimp-2.3.0 → dimp-2.3.2}/dimp/mkm/document.py +6 -21
  9. {dimp-2.3.0 → dimp-2.3.2}/dimp/mkm/meta.py +7 -8
  10. {dimp-2.3.0 → dimp-2.3.2}/dimp/msg/base.py +2 -2
  11. {dimp-2.3.0 → dimp-2.3.2}/dimp/msg/envelope.py +17 -14
  12. {dimp-2.3.0 → dimp-2.3.2}/dimp/msg/instant.py +13 -11
  13. {dimp-2.3.0 → dimp-2.3.2}/dimp/msg/reliable.py +2 -2
  14. {dimp-2.3.0 → dimp-2.3.2}/dimp/msg/secure.py +15 -9
  15. {dimp-2.3.0 → dimp-2.3.2}/dimp/plugins/__init__.py +2 -2
  16. {dimp-2.3.0 → dimp-2.3.2}/dimp/protocol/__init__.py +8 -8
  17. {dimp-2.3.0/dimp/dkd → dimp-2.3.2/dimp/protocol}/base.py +140 -15
  18. {dimp-2.3.0/dimp/dkd → dimp-2.3.2/dimp/protocol}/commands.py +126 -30
  19. {dimp-2.3.0/dimp/dkd → dimp-2.3.2/dimp/protocol}/contents.py +164 -128
  20. {dimp-2.3.0 → dimp-2.3.2}/dimp/protocol/files.py +150 -9
  21. dimp-2.3.2/dimp/protocol/forward.py +253 -0
  22. dimp-2.3.2/dimp/protocol/groups.py +498 -0
  23. {dimp-2.3.0/dimp/dkd → dimp-2.3.2/dimp/protocol}/money.py +100 -26
  24. {dimp-2.3.0 → dimp-2.3.2}/dimp/protocol/quote.py +51 -34
  25. {dimp-2.3.0/dimp/dkd → dimp-2.3.2/dimp/protocol}/receipt.py +83 -11
  26. {dimp-2.3.0 → dimp-2.3.2}/dimp.egg-info/PKG-INFO +1 -1
  27. {dimp-2.3.0 → dimp-2.3.2}/dimp.egg-info/SOURCES.txt +2 -10
  28. dimp-2.3.2/dimp.egg-info/requires.txt +2 -0
  29. {dimp-2.3.0 → dimp-2.3.2}/setup.py +3 -3
  30. dimp-2.3.0/dimp/dkd/files.py +0 -181
  31. dimp-2.3.0/dimp/dkd/group_admins.py +0 -106
  32. dimp-2.3.0/dimp/dkd/groups.py +0 -234
  33. dimp-2.3.0/dimp/dkd/quote.py +0 -141
  34. dimp-2.3.0/dimp/plugins/cmd.py +0 -79
  35. dimp-2.3.0/dimp/protocol/commands.py +0 -247
  36. dimp-2.3.0/dimp/protocol/contents.py +0 -279
  37. dimp-2.3.0/dimp/protocol/groups.py +0 -269
  38. dimp-2.3.0/dimp/protocol/money.py +0 -124
  39. dimp-2.3.0/dimp/protocol/receipt.py +0 -130
  40. dimp-2.3.0/dimp.egg-info/requires.txt +0 -2
  41. {dimp-2.3.0 → dimp-2.3.2}/LICENSE +0 -0
  42. {dimp-2.3.0 → dimp-2.3.2}/README.md +0 -0
  43. {dimp-2.3.0 → dimp-2.3.2}/dimp/crypto/__init__.py +0 -0
  44. {dimp-2.3.0 → dimp-2.3.2}/dimp/crypto/algorithms.py +0 -0
  45. {dimp-2.3.0 → dimp-2.3.2}/dimp/mkm/__init__.py +0 -0
  46. {dimp-2.3.0 → dimp-2.3.2}/dimp/msg/__init__.py +0 -0
  47. {dimp-2.3.0 → dimp-2.3.2}/dimp/protocol/docs.py +0 -0
  48. {dimp-2.3.0 → dimp-2.3.2}/dimp/protocol/helpers.py +0 -0
  49. {dimp-2.3.0 → dimp-2.3.2}/dimp/protocol/types.py +0 -0
  50. {dimp-2.3.0 → dimp-2.3.2}/dimp.egg-info/dependency_links.txt +0 -0
  51. {dimp-2.3.0 → dimp-2.3.2}/dimp.egg-info/top_level.txt +0 -0
  52. {dimp-2.3.0 → dimp-2.3.2}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: dimp
3
- Version: 2.3.0
3
+ Version: 2.3.2
4
4
  Summary: Decentralized Instant Messaging Protocol
5
5
  Home-page: https://github.com/dimchat/core-py
6
6
  Author: Albert Moky
@@ -34,7 +34,7 @@ from mkm.crypto import *
34
34
  from mkm import *
35
35
  from dkd import *
36
36
 
37
- from .protocol.commands import CommandFactory
37
+ from .protocol.base import CommandFactory
38
38
  from .protocol import *
39
39
  from .crypto import *
40
40
  from .mkm import *
@@ -52,7 +52,8 @@ __all__ = [
52
52
 
53
53
  'URI', 'DateTime',
54
54
 
55
- 'Converter', 'Copier',
55
+ 'Converter', 'DataConverter', 'BaseConverter',
56
+ 'Copier',
56
57
  'Wrapper', 'Stringer', 'Mapper',
57
58
  'ConstantString', # 'String',
58
59
  'Dictionary',
@@ -29,9 +29,9 @@
29
29
  # ==============================================================================
30
30
 
31
31
  from abc import ABC
32
- from typing import Optional, Any, Dict
32
+ from typing import Dict
33
33
 
34
- from mkm.types import Dictionary
34
+ from mkm.types import Mapper, Dictionary
35
35
  from mkm.crypto import CryptographyKey, EncryptKey, DecryptKey, SignKey, VerifyKey
36
36
  from mkm.crypto import SymmetricKey, AsymmetricKey, PublicKey, PrivateKey
37
37
  from mkm.plugins import SharedCryptoExtensions
@@ -46,7 +46,7 @@ from mkm.plugins import SharedCryptoExtensions
46
46
  # noinspection PyAbstractClass
47
47
  class BaseKey(Dictionary, CryptographyKey, ABC):
48
48
 
49
- def __init__(self, key: Dict[str, Any]):
49
+ def __init__(self, key: Dict):
50
50
  super().__init__(dictionary=key)
51
51
 
52
52
  @property # Override
@@ -58,9 +58,10 @@ class BaseKey(Dictionary, CryptographyKey, ABC):
58
58
  #
59
59
 
60
60
  @classmethod
61
- def get_key_algorithm(cls, key: Dict[str, Any]) -> Optional[str]:
61
+ def get_key_algorithm(cls, key: Dict) -> str:
62
62
  ext = SharedCryptoExtensions()
63
- return ext.helper.get_key_algorithm(key=key, default='')
63
+ algorithm = ext.helper.get_key_algorithm(key=key, default=None)
64
+ return '' if algorithm is None else algorithm
64
65
 
65
66
  @classmethod
66
67
  def match_encrypt_key(cls, encrypt_key: EncryptKey, decrypt_key: DecryptKey) -> bool:
@@ -96,20 +97,32 @@ class BaseKey(Dictionary, CryptographyKey, ABC):
96
97
  # noinspection PyAbstractClass
97
98
  class BaseSymmetricKey(Dictionary, SymmetricKey, ABC):
98
99
 
99
- def __init__(self, key: Dict[str, Any]):
100
+ def __init__(self, key: Dict):
100
101
  super().__init__(dictionary=key)
101
102
 
102
103
  # Override
103
104
  def __eq__(self, other) -> bool:
104
- if isinstance(other, SymmetricKey):
105
- return BaseKey.symmetric_keys_equal(other, self)
105
+ if isinstance(other, Mapper):
106
+ if self is other:
107
+ # same object
108
+ return True
109
+ elif isinstance(other, SymmetricKey):
110
+ return BaseKey.symmetric_keys_equal(other, self)
111
+ # compare with inner map
112
+ other = other.dictionary
113
+ return self.dictionary.__eq__(other)
106
114
 
107
115
  # Override
108
116
  def __ne__(self, other) -> bool:
109
- if isinstance(other, SymmetricKey):
110
- return not BaseKey.symmetric_keys_equal(other, self)
111
- else:
112
- return True
117
+ if isinstance(other, Mapper):
118
+ if self is other:
119
+ # same object
120
+ return False
121
+ elif isinstance(other, SymmetricKey):
122
+ return not BaseKey.symmetric_keys_equal(other, self)
123
+ # compare with inner map
124
+ other = other.dictionary
125
+ return self.dictionary.__ne__(other)
113
126
 
114
127
  @property # Override
115
128
  def algorithm(self) -> str:
@@ -123,7 +136,7 @@ class BaseSymmetricKey(Dictionary, SymmetricKey, ABC):
123
136
  # noinspection PyAbstractClass
124
137
  class BaseAsymmetricKey(Dictionary, AsymmetricKey, ABC):
125
138
 
126
- def __init__(self, key: Dict[str, Any]):
139
+ def __init__(self, key: Dict):
127
140
  super().__init__(dictionary=key)
128
141
 
129
142
  @property # Override
@@ -134,7 +147,7 @@ class BaseAsymmetricKey(Dictionary, AsymmetricKey, ABC):
134
147
  # noinspection PyAbstractClass
135
148
  class BasePublicKey(Dictionary, PublicKey, ABC):
136
149
 
137
- def __init__(self, key: Dict[str, Any]):
150
+ def __init__(self, key: Dict):
138
151
  super().__init__(dictionary=key)
139
152
 
140
153
  @property # Override
@@ -149,20 +162,32 @@ class BasePublicKey(Dictionary, PublicKey, ABC):
149
162
  # noinspection PyAbstractClass
150
163
  class BasePrivateKey(Dictionary, PrivateKey, ABC):
151
164
 
152
- def __init__(self, key: Dict[str, Any]):
165
+ def __init__(self, key: Dict):
153
166
  super().__init__(dictionary=key)
154
167
 
155
168
  # Override
156
169
  def __eq__(self, other) -> bool:
157
- if isinstance(other, PrivateKey):
158
- return BaseKey.private_keys_equal(other, self)
170
+ if isinstance(other, Mapper):
171
+ if self is other:
172
+ # same object
173
+ return True
174
+ elif isinstance(other, PrivateKey):
175
+ return BaseKey.private_keys_equal(other, self)
176
+ # compare with inner map
177
+ other = other.dictionary
178
+ return self.dictionary.__eq__(other)
159
179
 
160
180
  # Override
161
181
  def __ne__(self, other) -> bool:
162
- if isinstance(other, PrivateKey):
163
- return not BaseKey.private_keys_equal(other, self)
164
- else:
165
- return True
182
+ if isinstance(other, Mapper):
183
+ if self is other:
184
+ # same object
185
+ return False
186
+ elif isinstance(other, PrivateKey):
187
+ return not BaseKey.private_keys_equal(other, self)
188
+ # compare with inner map
189
+ other = other.dictionary
190
+ return self.dictionary.__ne__(other)
166
191
 
167
192
  @property # Override
168
193
  def algorithm(self) -> str:
@@ -28,15 +28,13 @@
28
28
  # SOFTWARE.
29
29
  # ==============================================================================
30
30
 
31
- from typing import Optional, Any, Dict
31
+ from typing import Optional, Dict
32
32
 
33
33
  from mkm.format import TransportableData
34
34
  from mkm.types import URI
35
35
  from mkm.types import Dictionary
36
36
  from mkm.crypto import DecryptKey, SymmetricKey
37
37
 
38
- from .algorithms import EncodeAlgorithms
39
-
40
38
 
41
39
  class BaseFileWrapper(Dictionary):
42
40
  """
@@ -57,7 +55,7 @@ class BaseFileWrapper(Dictionary):
57
55
  }
58
56
  """
59
57
 
60
- def __init__(self, dictionary: Dict[str, Any]):
58
+ def __init__(self, dictionary: Dict):
61
59
  super().__init__(dictionary=dictionary)
62
60
  # file data (not encrypted)
63
61
  self.__attachment: Optional[TransportableData] = None
@@ -92,7 +90,7 @@ class BaseFileWrapper(Dictionary):
92
90
  ted = None
93
91
  self.pop('data', None)
94
92
  else:
95
- ted = TransportableData.create(data=binary, algorithm=EncodeAlgorithms.DEFAULT)
93
+ ted = TransportableData.create(data=binary)
96
94
  self['data'] = ted.object
97
95
  self.__attachment = ted
98
96
 
@@ -117,11 +115,12 @@ class BaseFileWrapper(Dictionary):
117
115
 
118
116
  @property
119
117
  def url(self) -> Optional[URI]:
120
- if self.__url is None:
118
+ remote = self.__url
119
+ if remote is None:
121
120
  remote = self.get_str(key='URL', default=None)
122
121
  # TODO: convert str to URI
123
122
  self.__url = remote
124
- return self.__url
123
+ return remote
125
124
 
126
125
  @url.setter
127
126
  def url(self, remote: Optional[URI]):
@@ -138,10 +137,12 @@ class BaseFileWrapper(Dictionary):
138
137
 
139
138
  @property
140
139
  def password(self) -> Optional[DecryptKey]:
141
- if self.__password is None:
140
+ key = self.__password
141
+ if key is None:
142
142
  info = self.get('key')
143
- self.__password = SymmetricKey.parse(key=info)
144
- return self.__password
143
+ key = SymmetricKey.parse(key=info)
144
+ self.__password = key
145
+ return key
145
146
 
146
147
  @password.setter
147
148
  def password(self, key: Optional[DecryptKey]):
@@ -28,7 +28,7 @@
28
28
  # SOFTWARE.
29
29
  # ==============================================================================
30
30
 
31
- from typing import Optional, Any, Dict
31
+ from typing import Optional, Dict
32
32
 
33
33
  from mkm.format import base64_encode, base64_decode
34
34
  from mkm.format import base58_encode, base58_decode
@@ -54,26 +54,26 @@ class BaseDataWrapper(Dictionary):
54
54
  2. "data:image/png;base64,{BASE64_ENCODE}"
55
55
  """
56
56
 
57
- def __init__(self, dictionary: Dict[str, Any]):
57
+ def __init__(self, dictionary: Dict):
58
58
  super().__init__(dictionary=dictionary)
59
59
  # binary data
60
60
  self.__data: Optional[bytes] = None
61
61
 
62
- # Override
63
- def __len__(self) -> int:
64
- """ return len(self) """
65
- # if super().__len__() == 0:
66
- # return 0
67
- data = self.data
68
- return 0 if data is None else len(data)
62
+ # # Override
63
+ # def __len__(self) -> int:
64
+ # """ return len(self) """
65
+ # if super().__len__() == 0:
66
+ # return 0
67
+ # data = self.data
68
+ # return 0 if data is None else len(data)
69
69
 
70
70
  # Override
71
71
  def __str__(self) -> str:
72
- text = self.get_str(key='data', default='')
73
- if len(text) == 0:
74
- return text
75
- alg = self.get_str(key='algorithm', default='')
76
- if alg == EncodeAlgorithms.DEFAULT:
72
+ text = self.get_str(key='data', default=None)
73
+ if text is None: # or len(text) == 0:
74
+ return ''
75
+ alg = self.get_str(key='algorithm', default=None)
76
+ if alg is None or alg == EncodeAlgorithms.DEFAULT:
77
77
  alg = ''
78
78
  if len(alg) == 0:
79
79
  # 0. "{BASE64_ENCODE}"
@@ -85,9 +85,9 @@ class BaseDataWrapper(Dictionary):
85
85
  def encode(self, mime_type: str) -> str:
86
86
  """ toString(mimeType) """
87
87
  # get encoded data
88
- text = self.get_str(key='data', default='')
89
- if len(text) == 0:
90
- return text
88
+ text = self.get_str(key='data', default=None)
89
+ if text is None: # or len(text) == 0:
90
+ return ''
91
91
  alg = self.algorithm
92
92
  # 2. "data:image/png;base64,{BASE64_ENCODE}"
93
93
  return 'data:%s;%s,%s' % (mime_type, alg, text)
@@ -98,8 +98,8 @@ class BaseDataWrapper(Dictionary):
98
98
 
99
99
  @property
100
100
  def algorithm(self) -> str:
101
- alg = self.get_str(key='algorithm', default='')
102
- if len(alg) == 0:
101
+ alg = self.get_str(key='algorithm', default=None)
102
+ if alg is None or len(alg) == 0:
103
103
  alg = EncodeAlgorithms.DEFAULT
104
104
  return alg
105
105
 
@@ -118,8 +118,11 @@ class BaseDataWrapper(Dictionary):
118
118
  def data(self) -> Optional[bytes]:
119
119
  binary = self.__data
120
120
  if binary is None:
121
- text = self.get_str(key='data', default='')
122
- if len(text) > 0:
121
+ text = self.get_str(key='data', default=None)
122
+ if text is None or len(text) == 0:
123
+ # assert False, 'TED data empty: %s' % self.dictionary
124
+ return None
125
+ else:
123
126
  alg = self.algorithm
124
127
  if alg == EncodeAlgorithms.BASE_64:
125
128
  binary = base64_decode(string=text)
@@ -145,6 +148,7 @@ class BaseDataWrapper(Dictionary):
145
148
  elif alg == EncodeAlgorithms.HEX:
146
149
  text = hex_encode(data=binary)
147
150
  else:
148
- assert False, 'data algorithm not support: %s' % alg
151
+ raise ArithmeticError('data algorithm not support: %s' % alg)
152
+ # assert False, 'data algorithm not support: %s' % alg
149
153
  self['data'] = text
150
154
  self.__data = binary
@@ -31,22 +31,23 @@
31
31
  from dkd import *
32
32
  from ..protocol import *
33
33
 
34
- from .base import BaseContent, BaseCommand
35
- from .contents import BaseTextContent, ListContent, SecretContent
36
- from .contents import WebPageContent, NameCardContent
37
- from .files import BaseFileContent, ImageFileContent, AudioFileContent, VideoFileContent
38
- from .money import BaseMoneyContent, TransferMoneyContent
39
- from .quote import BaseQuoteContent, CombineForwardContent
40
-
41
- from .commands import BaseMetaCommand, BaseDocumentCommand
42
- from .receipt import BaseReceiptCommand
43
-
44
- from .groups import BaseHistoryCommand, BaseGroupCommand
45
- from .groups import InviteGroupCommand, ExpelGroupCommand, JoinGroupCommand
46
- from .groups import QuitGroupCommand, QueryGroupCommand, ResetGroupCommand
47
- from .group_admins import HireGroupCommand, FireGroupCommand, ResignGroupCommand
48
-
49
- # from ..protocol.commands import CommandHelper
34
+ from ..protocol.base import BaseContent
35
+ from ..protocol.contents import BaseTextContent, WebPageContent, NameCardContent
36
+ from ..protocol.forward import SecretContent, CombineForwardContent, ListContent
37
+ from ..protocol.files import BaseFileContent, ImageFileContent, AudioFileContent, VideoFileContent
38
+ from ..protocol.money import BaseMoneyContent, TransferMoneyContent
39
+ from ..protocol.quote import BaseQuoteContent
40
+
41
+ from ..protocol.base import BaseCommand
42
+ from ..protocol.commands import BaseMetaCommand, BaseDocumentCommand
43
+ from ..protocol.receipt import BaseReceiptCommand
44
+
45
+ from ..protocol.groups import BaseHistoryCommand, BaseGroupCommand
46
+ from ..protocol.groups import InviteGroupCommand, ExpelGroupCommand, JoinGroupCommand
47
+ from ..protocol.groups import QuitGroupCommand, QueryGroupCommand, ResetGroupCommand
48
+ from ..protocol.groups import HireGroupCommand, FireGroupCommand, ResignGroupCommand
49
+
50
+ # from ..protocol.base import CommandHelper
50
51
  # from ..protocol.helpers import CommandExtensions
51
52
 
52
53
  __all__ = [
@@ -28,7 +28,7 @@
28
28
  # SOFTWARE.
29
29
  # ==============================================================================
30
30
 
31
- from typing import Optional, Any, Dict, List
31
+ from typing import Optional, Dict, List
32
32
 
33
33
  from mkm.crypto import PublicKey, EncryptKey
34
34
  from mkm.format import TransportableData
@@ -43,7 +43,7 @@ from .document import BaseDocument
43
43
 
44
44
  class BaseVisa(BaseDocument, Visa):
45
45
 
46
- def __init__(self, document: Optional[Dict[str, Any]] = None,
46
+ def __init__(self, document: Optional[Dict] = None,
47
47
  identifier: ID = None, data: Optional[str] = None, signature: Optional[TransportableData] = None):
48
48
  if document is None:
49
49
  # 1. document from local
@@ -68,15 +68,17 @@ class BaseVisa(BaseDocument, Visa):
68
68
 
69
69
  @property # Override
70
70
  def public_key(self) -> Optional[EncryptKey]:
71
- if self.__key is None:
71
+ visa_key = self.__key
72
+ if visa_key is None:
72
73
  info = self.get_property(name='key')
73
74
  # assert info is not None, 'visa key not found: %s' % self.dictionary
74
75
  pub = PublicKey.parse(key=info)
75
76
  if isinstance(pub, EncryptKey):
76
- self.__key = pub
77
+ visa_key = pub
78
+ self.__key = visa_key
77
79
  else:
78
80
  assert info is None, 'visa key error: %s' % info
79
- return self.__key
81
+ return visa_key
80
82
 
81
83
  @public_key.setter # Override
82
84
  def public_key(self, key: EncryptKey):
@@ -91,25 +93,27 @@ class BaseVisa(BaseDocument, Visa):
91
93
 
92
94
  @property # Override
93
95
  def avatar(self) -> Optional[PortableNetworkFile]:
94
- if self.__avatar is None:
96
+ img = self.__avatar
97
+ if img is None:
95
98
  url = self.get_property(name='avatar')
96
99
  if isinstance(url, str) and len(url) == 0:
97
100
  # ignore empty URL
98
101
  pass
99
102
  else:
100
- self.__avatar = PortableNetworkFile.parse(url)
101
- return self.__avatar
103
+ img = PortableNetworkFile.parse(url)
104
+ self.__avatar = img
105
+ return img
102
106
 
103
107
  @avatar.setter # Override
104
- def avatar(self, url: PortableNetworkFile):
105
- info = None if url is None else url.object
108
+ def avatar(self, img: PortableNetworkFile):
109
+ info = None if img is None else img.object
106
110
  self.set_property(name='avatar', value=info)
107
- self.__avatar = url
111
+ self.__avatar = img
108
112
 
109
113
 
110
114
  class BaseBulletin(BaseDocument, Bulletin):
111
115
 
112
- def __init__(self, document: Optional[Dict[str, Any]] = None,
116
+ def __init__(self, document: Optional[Dict] = None,
113
117
  identifier: ID = None,
114
118
  data: Optional[str] = None, signature: Optional[TransportableData] = None):
115
119
  if document is None:
@@ -134,13 +138,13 @@ class BaseBulletin(BaseDocument, Bulletin):
134
138
  def assistants(self) -> Optional[List[ID]]:
135
139
  if self.__bots is None:
136
140
  bots = self.get_property(name='assistants')
137
- if bots is None:
141
+ if isinstance(bots, List):
142
+ self.__bots = ID.convert(array=bots)
143
+ else:
138
144
  # get from 'assistant'
139
145
  single = self.get_property(name='assistant')
140
146
  single = ID.parse(identifier=single)
141
147
  self.__bots = [] if single is None else [single]
142
- else:
143
- self.__bots = ID.convert(array=bots)
144
148
  return self.__bots
145
149
 
146
150
  @assistants.setter # Override
@@ -37,8 +37,6 @@ from mkm.format import TransportableData
37
37
  from mkm.format import json_encode, json_decode, utf8_encode
38
38
  from mkm import ID, Document
39
39
 
40
- from ..crypto import EncodeAlgorithms
41
-
42
40
 
43
41
  """
44
42
  Base Documents
@@ -50,7 +48,7 @@ from ..crypto import EncodeAlgorithms
50
48
 
51
49
  class BaseDocument(Dictionary, Document):
52
50
 
53
- def __init__(self, document: Dict[str, Any] = None,
51
+ def __init__(self, document: Dict = None,
54
52
  doc_type: str = None, identifier: ID = None,
55
53
  data: Optional[str] = None, signature: Optional[TransportableData] = None):
56
54
  # check parameters
@@ -102,15 +100,6 @@ class BaseDocument(Dictionary, Document):
102
100
  self.__properties = properties
103
101
  self.__status = status # 1 for valid, -1 for invalid
104
102
 
105
- # @property # Override
106
- # def type(self) -> Optional[str]:
107
- # doc_type = self.get_property(name='type') # deprecated
108
- # if doc_type is None:
109
- # ext = SharedAccountExtensions()
110
- # doc_type = ext.helper.get_document_type(document=self.dictionary, default=None)
111
- # # doc_type = self.get_str(key='type', default=None)
112
- # return doc_type
113
-
114
103
  @property # Override
115
104
  def identifier(self) -> ID:
116
105
  if self.__identifier is None:
@@ -200,17 +189,13 @@ class BaseDocument(Dictionary, Document):
200
189
  # 2. encode & sign
201
190
  info = self.properties
202
191
  if info is None:
203
- # assert False, 'should not happen'
192
+ # assert False, 'document invalid: %s' % self.dictionary
204
193
  return None
205
194
  data = json_encode(info)
206
- if len(data) == 0:
207
- # properties error
208
- return None
195
+ assert len(data) > 0, 'should not happen: %s' % info
209
196
  signature = private_key.sign(data=utf8_encode(string=data))
210
- if len(signature) == 0:
211
- # assert False, 'should not happen'
212
- return None
213
- ted = TransportableData.create(data=signature, algorithm=EncodeAlgorithms.DEFAULT)
197
+ assert len(signature) > 0, 'should not happen: %s' % info
198
+ ted = TransportableData.create(data=signature)
214
199
  # 3. update 'data' & 'signature' fields
215
200
  self['data'] = data # JsON string
216
201
  self['signature'] = ted.object # BASE-64
@@ -225,7 +210,7 @@ class BaseDocument(Dictionary, Document):
225
210
  #
226
211
 
227
212
  @property # Override
228
- def properties(self) -> Optional[Dict[str, Any]]:
213
+ def properties(self) -> Optional[Dict]:
229
214
  """ Load properties from data """
230
215
  if self.__status < 0:
231
216
  # invalid
@@ -29,7 +29,7 @@
29
29
  # ==============================================================================
30
30
 
31
31
  from abc import ABC, abstractmethod
32
- from typing import Optional, Any, Dict
32
+ from typing import Optional, Dict
33
33
 
34
34
  from mkm.format import utf8_encode
35
35
  from mkm.format import TransportableData
@@ -45,10 +45,10 @@ from mkm import Meta
45
45
  This class is used to generate entity ID
46
46
 
47
47
  data format: {
48
- type : 1, // meta version
49
- seed : "moKy", // user/group name
50
- key : "{public key}", // PK = secp256k1(SK);
51
- fingerprint: "..." // CT = sign(seed, SK);
48
+ type : 1, // meta version
49
+ key : "{public key}", // PK = secp256k1(SK);
50
+ seed : "moKy", // user/group name
51
+ fingerprint : "..." // CT = sign(seed, SK);
52
52
  }
53
53
 
54
54
  algorithm:
@@ -59,10 +59,9 @@ from mkm import Meta
59
59
  """
60
60
 
61
61
 
62
- # noinspection PyAbstractClass
63
62
  class BaseMeta(Dictionary, Meta, ABC):
64
63
 
65
- def __init__(self, meta: Dict[str, Any] = None,
64
+ def __init__(self, meta: Dict = None,
66
65
  version: str = None, public_key: VerifyKey = None,
67
66
  seed: Optional[str] = None, fingerprint: Optional[TransportableData] = None):
68
67
  # check parameters
@@ -143,7 +142,7 @@ class BaseMeta(Dictionary, Meta, ABC):
143
142
  ted = self.__fingerprint
144
143
  if ted is None and self.has_seed:
145
144
  base64 = self.get('fingerprint')
146
- assert base64 is not None, 'meta.fingerprint should not be empty: %s' % self
145
+ assert base64 is not None, 'meta.fingerprint should not be empty: %s' % self.dictionary
147
146
  self.__fingerprint = ted = TransportableData.parse(base64)
148
147
  assert ted is not None, 'meta.fingerprint error: %s' % base64
149
148
  if ted is not None:
@@ -50,7 +50,7 @@
50
50
  """
51
51
 
52
52
 
53
- from typing import Optional, Any, Dict
53
+ from typing import Optional, Dict
54
54
 
55
55
  from mkm.types import DateTime
56
56
  from mkm.types import Dictionary
@@ -61,7 +61,7 @@ from dkd import Envelope, Message
61
61
 
62
62
  class BaseMessage(Dictionary, Message):
63
63
 
64
- def __init__(self, msg: Dict[str, Any] = None, head: Envelope = None):
64
+ def __init__(self, msg: Dict = None, head: Envelope = None):
65
65
  if msg is None:
66
66
  # 1. new message with envelope
67
67
  assert head is not None, 'message envelope should not be empty'
@@ -28,7 +28,7 @@
28
28
  # SOFTWARE.
29
29
  # ==============================================================================
30
30
 
31
- from typing import Optional, Any, Dict
31
+ from typing import Optional, Dict
32
32
 
33
33
  from mkm.types import DateTime
34
34
  from mkm.types import Dictionary
@@ -53,7 +53,7 @@ from dkd import Envelope
53
53
 
54
54
  class MessageEnvelope(Dictionary, Envelope):
55
55
 
56
- def __init__(self, envelope: Dict[str, Any] = None,
56
+ def __init__(self, envelope: Dict = None,
57
57
  sender: ID = None, receiver: Optional[ID] = None, time: Optional[DateTime] = None):
58
58
  if envelope is None:
59
59
  # 1. new envelope with sender, receiver & time
@@ -80,21 +80,24 @@ class MessageEnvelope(Dictionary, Envelope):
80
80
 
81
81
  @property # Override
82
82
  def sender(self) -> ID:
83
- if self.__sender is None:
84
- identifier = self.get('sender')
85
- self.__sender = ID.parse(identifier=identifier)
86
- return self.__sender
83
+ did = self.__sender
84
+ if did is None:
85
+ did = self.get('sender')
86
+ did = ID.parse(identifier=did)
87
+ assert did is not None, 'message sender error: %s' % self.dictionary
88
+ self.__sender = did
89
+ return did
87
90
 
88
91
  @property # Override
89
92
  def receiver(self) -> ID:
90
- if self.__receiver is None:
91
- identifier = self.get('receiver')
92
- identifier = ID.parse(identifier=identifier)
93
- if identifier is None:
94
- self.__receiver = ANYONE
95
- else:
96
- self.__receiver = identifier
97
- return self.__receiver
93
+ did = self.__receiver
94
+ if did is None:
95
+ did = self.get('receiver')
96
+ did = ID.parse(identifier=did)
97
+ if did is None:
98
+ did = ANYONE
99
+ self.__receiver = did
100
+ return did
98
101
 
99
102
  @property # Override
100
103
  def time(self) -> Optional[DateTime]: