dimp 2.4.0__tar.gz → 2.4.1__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.
- {dimp-2.4.0 → dimp-2.4.1}/PKG-INFO +19 -7
- {dimp-2.4.0 → dimp-2.4.1}/README.md +18 -6
- {dimp-2.4.0 → dimp-2.4.1}/dimp/dkd/base.py +1 -1
- {dimp-2.4.0 → dimp-2.4.1}/dimp/dkd/envelope.py +2 -2
- {dimp-2.4.0 → dimp-2.4.1}/dimp/dkd/instant.py +3 -3
- {dimp-2.4.0 → dimp-2.4.1}/dimp/dkd/reliable.py +3 -3
- {dimp-2.4.0 → dimp-2.4.1}/dimp/dkd/secure.py +3 -3
- {dimp-2.4.0 → dimp-2.4.1}/dimp/format/base.py +6 -2
- {dimp-2.4.0 → dimp-2.4.1}/dimp/format/data.py +4 -4
- {dimp-2.4.0 → dimp-2.4.1}/dimp/format/duri.py +11 -10
- {dimp-2.4.0 → dimp-2.4.1}/dimp/format/embed.py +2 -2
- {dimp-2.4.0 → dimp-2.4.1}/dimp/format/file.py +72 -21
- {dimp-2.4.0 → dimp-2.4.1}/dimp/format/file_wrapper.py +48 -15
- {dimp-2.4.0 → dimp-2.4.1}/dimp/mkm/docs.py +4 -4
- {dimp-2.4.0 → dimp-2.4.1}/dimp/mkm/document.py +12 -12
- {dimp-2.4.0 → dimp-2.4.1}/dimp/mkm/meta.py +9 -7
- {dimp-2.4.0 → dimp-2.4.1}/dimp/protocol/assets.py +30 -9
- {dimp-2.4.0 → dimp-2.4.1}/dimp/protocol/base.py +41 -13
- {dimp-2.4.0 → dimp-2.4.1}/dimp/protocol/commands.py +19 -8
- {dimp-2.4.0 → dimp-2.4.1}/dimp/protocol/contents.py +60 -18
- {dimp-2.4.0 → dimp-2.4.1}/dimp/protocol/docs.py +27 -9
- {dimp-2.4.0 → dimp-2.4.1}/dimp/protocol/files.py +61 -21
- {dimp-2.4.0 → dimp-2.4.1}/dimp/protocol/forward.py +22 -10
- {dimp-2.4.0 → dimp-2.4.1}/dimp/protocol/groups.py +8 -2
- {dimp-2.4.0 → dimp-2.4.1}/dimp/protocol/quote.py +30 -9
- {dimp-2.4.0 → dimp-2.4.1}/dimp/protocol/receipt.py +19 -7
- {dimp-2.4.0 → dimp-2.4.1}/dimp.egg-info/PKG-INFO +19 -7
- dimp-2.4.1/dimp.egg-info/requires.txt +2 -0
- {dimp-2.4.0 → dimp-2.4.1}/setup.py +3 -3
- dimp-2.4.0/dimp.egg-info/requires.txt +0 -2
- {dimp-2.4.0 → dimp-2.4.1}/LICENSE +0 -0
- {dimp-2.4.0 → dimp-2.4.1}/dimp/__init__.py +0 -0
- {dimp-2.4.0 → dimp-2.4.1}/dimp/crypto/__init__.py +0 -0
- {dimp-2.4.0 → dimp-2.4.1}/dimp/crypto/algorithms.py +0 -0
- {dimp-2.4.0 → dimp-2.4.1}/dimp/dkd/__init__.py +0 -0
- {dimp-2.4.0 → dimp-2.4.1}/dimp/ext/__init__.py +0 -0
- {dimp-2.4.0 → dimp-2.4.1}/dimp/format/__init__.py +0 -0
- {dimp-2.4.0 → dimp-2.4.1}/dimp/format/pnf.py +0 -0
- {dimp-2.4.0 → dimp-2.4.1}/dimp/format/pnf_wrapper.py +0 -0
- {dimp-2.4.0 → dimp-2.4.1}/dimp/mkm/__init__.py +0 -0
- {dimp-2.4.0 → dimp-2.4.1}/dimp/protocol/__init__.py +0 -0
- {dimp-2.4.0 → dimp-2.4.1}/dimp/protocol/types.py +0 -0
- {dimp-2.4.0 → dimp-2.4.1}/dimp/protocol/version.py +0 -0
- {dimp-2.4.0 → dimp-2.4.1}/dimp.egg-info/SOURCES.txt +0 -0
- {dimp-2.4.0 → dimp-2.4.1}/dimp.egg-info/dependency_links.txt +0 -0
- {dimp-2.4.0 → dimp-2.4.1}/dimp.egg-info/top_level.txt +0 -0
- {dimp-2.4.0 → dimp-2.4.1}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: dimp
|
|
3
|
-
Version: 2.4.
|
|
3
|
+
Version: 2.4.1
|
|
4
4
|
Summary: Decentralized Instant Messaging Protocol
|
|
5
5
|
Home-page: https://github.com/dimchat/core-py
|
|
6
6
|
Author: Albert Moky
|
|
@@ -91,17 +91,23 @@ class HandshakeCommand(Command, ABC):
|
|
|
91
91
|
@property
|
|
92
92
|
@abstractmethod
|
|
93
93
|
def title(self) -> str:
|
|
94
|
-
raise
|
|
94
|
+
raise NotImplementedError(
|
|
95
|
+
f'Not implemented: {type(self).__module__}.{type(self).__name__}.title getter'
|
|
96
|
+
)
|
|
95
97
|
|
|
96
98
|
@property
|
|
97
99
|
@abstractmethod
|
|
98
100
|
def session(self) -> Optional[str]:
|
|
99
|
-
raise
|
|
101
|
+
raise NotImplementedError(
|
|
102
|
+
f'Not implemented: {type(self).__module__}.{type(self).__name__}.session getter'
|
|
103
|
+
)
|
|
100
104
|
|
|
101
105
|
@property
|
|
102
106
|
@abstractmethod
|
|
103
107
|
def state(self) -> HandshakeState:
|
|
104
|
-
raise
|
|
108
|
+
raise NotImplementedError(
|
|
109
|
+
f'Not implemented: {type(self).__module__}.{type(self).__name__}.state getter'
|
|
110
|
+
)
|
|
105
111
|
|
|
106
112
|
#
|
|
107
113
|
# Factories
|
|
@@ -198,7 +204,9 @@ class AppContent(Content, ABC):
|
|
|
198
204
|
@abstractmethod
|
|
199
205
|
def application(self) -> str:
|
|
200
206
|
""" App ID """
|
|
201
|
-
raise
|
|
207
|
+
raise NotImplementedError(
|
|
208
|
+
f'Not implemented: {type(self).__module__}.{type(self).__name__}.application getter'
|
|
209
|
+
)
|
|
202
210
|
|
|
203
211
|
|
|
204
212
|
class CustomizedContent(Content, ABC):
|
|
@@ -221,13 +229,17 @@ class CustomizedContent(Content, ABC):
|
|
|
221
229
|
@abstractmethod
|
|
222
230
|
def module(self) -> str:
|
|
223
231
|
""" Module Name """
|
|
224
|
-
raise
|
|
232
|
+
raise NotImplementedError(
|
|
233
|
+
f'Not implemented: {type(self).__module__}.{type(self).__name__}.module getter'
|
|
234
|
+
)
|
|
225
235
|
|
|
226
236
|
@property
|
|
227
237
|
@abstractmethod
|
|
228
238
|
def action(self) -> str:
|
|
229
239
|
""" Action Name """
|
|
230
|
-
raise
|
|
240
|
+
raise NotImplementedError(
|
|
241
|
+
f'Not implemented: {type(self).__module__}.{type(self).__name__}.action getter'
|
|
242
|
+
)
|
|
231
243
|
|
|
232
244
|
#
|
|
233
245
|
# Factory method
|
|
@@ -77,17 +77,23 @@ class HandshakeCommand(Command, ABC):
|
|
|
77
77
|
@property
|
|
78
78
|
@abstractmethod
|
|
79
79
|
def title(self) -> str:
|
|
80
|
-
raise
|
|
80
|
+
raise NotImplementedError(
|
|
81
|
+
f'Not implemented: {type(self).__module__}.{type(self).__name__}.title getter'
|
|
82
|
+
)
|
|
81
83
|
|
|
82
84
|
@property
|
|
83
85
|
@abstractmethod
|
|
84
86
|
def session(self) -> Optional[str]:
|
|
85
|
-
raise
|
|
87
|
+
raise NotImplementedError(
|
|
88
|
+
f'Not implemented: {type(self).__module__}.{type(self).__name__}.session getter'
|
|
89
|
+
)
|
|
86
90
|
|
|
87
91
|
@property
|
|
88
92
|
@abstractmethod
|
|
89
93
|
def state(self) -> HandshakeState:
|
|
90
|
-
raise
|
|
94
|
+
raise NotImplementedError(
|
|
95
|
+
f'Not implemented: {type(self).__module__}.{type(self).__name__}.state getter'
|
|
96
|
+
)
|
|
91
97
|
|
|
92
98
|
#
|
|
93
99
|
# Factories
|
|
@@ -184,7 +190,9 @@ class AppContent(Content, ABC):
|
|
|
184
190
|
@abstractmethod
|
|
185
191
|
def application(self) -> str:
|
|
186
192
|
""" App ID """
|
|
187
|
-
raise
|
|
193
|
+
raise NotImplementedError(
|
|
194
|
+
f'Not implemented: {type(self).__module__}.{type(self).__name__}.application getter'
|
|
195
|
+
)
|
|
188
196
|
|
|
189
197
|
|
|
190
198
|
class CustomizedContent(Content, ABC):
|
|
@@ -207,13 +215,17 @@ class CustomizedContent(Content, ABC):
|
|
|
207
215
|
@abstractmethod
|
|
208
216
|
def module(self) -> str:
|
|
209
217
|
""" Module Name """
|
|
210
|
-
raise
|
|
218
|
+
raise NotImplementedError(
|
|
219
|
+
f'Not implemented: {type(self).__module__}.{type(self).__name__}.module getter'
|
|
220
|
+
)
|
|
211
221
|
|
|
212
222
|
@property
|
|
213
223
|
@abstractmethod
|
|
214
224
|
def action(self) -> str:
|
|
215
225
|
""" Action Name """
|
|
216
|
-
raise
|
|
226
|
+
raise NotImplementedError(
|
|
227
|
+
f'Not implemented: {type(self).__module__}.{type(self).__name__}.action getter'
|
|
228
|
+
)
|
|
217
229
|
|
|
218
230
|
#
|
|
219
231
|
# Factory method
|
|
@@ -67,7 +67,7 @@ class BaseMessage(Dictionary, Message):
|
|
|
67
67
|
msg = head.to_dict()
|
|
68
68
|
else:
|
|
69
69
|
# 2. message info from network
|
|
70
|
-
assert head is None, 'params error:
|
|
70
|
+
assert head is None, f'params error: {msg}, {head}'
|
|
71
71
|
super().__init__(dictionary=msg)
|
|
72
72
|
# lazy
|
|
73
73
|
self.__envelope = head
|
|
@@ -56,7 +56,7 @@ class MessageEnvelope(Dictionary, Envelope):
|
|
|
56
56
|
sender: ID = None, receiver: Optional[ID] = None, time: Optional[DateTime] = None):
|
|
57
57
|
if envelope is None:
|
|
58
58
|
# 1. new envelope with sender, receiver & time
|
|
59
|
-
assert sender is not None, 'envelope error:
|
|
59
|
+
assert sender is not None, f'envelope error: {receiver}, {time}'
|
|
60
60
|
if receiver is None:
|
|
61
61
|
receiver = ANYONE
|
|
62
62
|
if time is None:
|
|
@@ -69,7 +69,7 @@ class MessageEnvelope(Dictionary, Envelope):
|
|
|
69
69
|
else:
|
|
70
70
|
# 2. envelope info from network
|
|
71
71
|
assert sender is None and receiver is None and time is None, \
|
|
72
|
-
'params error:
|
|
72
|
+
f'params error: {envelope}, {sender}, {receiver}, {time}'
|
|
73
73
|
# initialize with envelope info
|
|
74
74
|
super().__init__(dictionary=envelope)
|
|
75
75
|
# lazy load
|
|
@@ -61,12 +61,12 @@ class PlainMessage(BaseMessage, InstantMessage):
|
|
|
61
61
|
head: Envelope = None, body: Content = None):
|
|
62
62
|
if msg is None:
|
|
63
63
|
# 1. new instant message with envelope & content
|
|
64
|
-
assert head is not None and body is not None, 'instant message error:
|
|
64
|
+
assert head is not None and body is not None, f'instant message error: {head}, {body}'
|
|
65
65
|
super().__init__(None, head)
|
|
66
66
|
# self['content'] = body.to_dict()
|
|
67
67
|
else:
|
|
68
68
|
# 2. message info from network
|
|
69
|
-
assert head is None and body is None, 'params error:
|
|
69
|
+
assert head is None and body is None, f'params error: {msg}, {head}, {body}'
|
|
70
70
|
super().__init__(msg, head)
|
|
71
71
|
# lazy
|
|
72
72
|
self.__content = body
|
|
@@ -93,7 +93,7 @@ class PlainMessage(BaseMessage, InstantMessage):
|
|
|
93
93
|
if body is None:
|
|
94
94
|
info = self.get('content')
|
|
95
95
|
body = Content.parse(content=info)
|
|
96
|
-
assert body is not None, 'message content error:
|
|
96
|
+
assert body is not None, f'message content error: {self.to_dict()}'
|
|
97
97
|
self.__content = body
|
|
98
98
|
return body
|
|
99
99
|
|
|
@@ -72,9 +72,9 @@ class NetworkMessage(EncryptedMessage, ReliableMessage):
|
|
|
72
72
|
ted = self.__signature
|
|
73
73
|
if ted is None:
|
|
74
74
|
base64 = self.get('signature')
|
|
75
|
-
assert base64 is not None, 'message signature cannot be empty:
|
|
75
|
+
assert base64 is not None, f'message signature cannot be empty: {self}'
|
|
76
76
|
ted = TransportableData.parse(base64)
|
|
77
|
-
assert ted is not None, 'failed to decode message signature:
|
|
77
|
+
assert ted is not None, f'failed to decode message signature: {base64}'
|
|
78
78
|
self.__signature = ted
|
|
79
|
-
assert ted is not None, 'message signature error:
|
|
79
|
+
assert ted is not None, f'message signature error: {self.get("signature")}'
|
|
80
80
|
return ted
|
|
@@ -83,9 +83,9 @@ class EncryptedMessage(BaseMessage, SecureMessage):
|
|
|
83
83
|
# so return the string data directly
|
|
84
84
|
ted = PlainData.create(string=text) # JsON
|
|
85
85
|
else:
|
|
86
|
-
assert False, 'content data error:
|
|
86
|
+
assert False, f'content data error: {text}'
|
|
87
87
|
self.__data = ted
|
|
88
|
-
assert ted is not None, 'message data error:
|
|
88
|
+
assert ted is not None, f'message data error: {self.get("data")}'
|
|
89
89
|
return ted
|
|
90
90
|
|
|
91
91
|
@property # Override
|
|
@@ -96,6 +96,6 @@ class EncryptedMessage(BaseMessage, SecureMessage):
|
|
|
96
96
|
if isinstance(keys, Dict):
|
|
97
97
|
self.__keys = keys
|
|
98
98
|
else:
|
|
99
|
-
assert keys is None, 'message keys error:
|
|
99
|
+
assert keys is None, f'message keys error: {keys}'
|
|
100
100
|
# TODO: get from 'key'
|
|
101
101
|
return keys
|
|
@@ -101,7 +101,8 @@ class BaseString(Stringer):
|
|
|
101
101
|
def __repr__(self) -> str:
|
|
102
102
|
""" Return repr(self). """
|
|
103
103
|
clazz = self.__class__.__name__
|
|
104
|
-
|
|
104
|
+
text = self.to_str()
|
|
105
|
+
return f'<{clazz}>{text}</{clazz}>'
|
|
105
106
|
|
|
106
107
|
|
|
107
108
|
class BaseData(BaseString, TransportableData, ABC):
|
|
@@ -118,7 +119,10 @@ class BaseData(BaseString, TransportableData, ABC):
|
|
|
118
119
|
# Override
|
|
119
120
|
@abstractmethod
|
|
120
121
|
def to_str(self) -> str:
|
|
121
|
-
|
|
122
|
+
""" Convert to string """
|
|
123
|
+
raise NotImplementedError(
|
|
124
|
+
f'Not implemented: {type(self).__module__}.{type(self).__name__}.to_str()'
|
|
125
|
+
)
|
|
122
126
|
|
|
123
127
|
@property
|
|
124
128
|
def is_empty(self) -> bool:
|
|
@@ -44,7 +44,7 @@ class Base64Data(BaseData):
|
|
|
44
44
|
data = self._binary
|
|
45
45
|
if data is None:
|
|
46
46
|
base64 = self._string
|
|
47
|
-
assert base64 is not None, 'Base64Data error:
|
|
47
|
+
assert base64 is not None, f'Base64Data error: {self}'
|
|
48
48
|
data = base64_decode(string=base64)
|
|
49
49
|
self._binary = data
|
|
50
50
|
return data
|
|
@@ -54,7 +54,7 @@ class Base64Data(BaseData):
|
|
|
54
54
|
base64 = self._string
|
|
55
55
|
if base64 is None or len(base64) == 0:
|
|
56
56
|
data = self._binary
|
|
57
|
-
assert data is not None, 'Base64Data error:
|
|
57
|
+
assert data is not None, f'Base64Data error: {self}'
|
|
58
58
|
base64 = base64_encode(data=data)
|
|
59
59
|
self._string = base64
|
|
60
60
|
return base64
|
|
@@ -82,7 +82,7 @@ class PlainData(BaseData):
|
|
|
82
82
|
data = self._binary
|
|
83
83
|
if data is None:
|
|
84
84
|
txt = self._string
|
|
85
|
-
assert txt is not None, 'PlainData error:
|
|
85
|
+
assert txt is not None, f'PlainData error: {self}'
|
|
86
86
|
data = utf8_encode(string=txt)
|
|
87
87
|
self._binary = data
|
|
88
88
|
return data
|
|
@@ -92,7 +92,7 @@ class PlainData(BaseData):
|
|
|
92
92
|
txt = self._string
|
|
93
93
|
if txt is None or len(txt) == 0:
|
|
94
94
|
data = self._binary
|
|
95
|
-
assert data is not None, 'PlainData error:
|
|
95
|
+
assert data is not None, f'PlainData error: {self}'
|
|
96
96
|
txt = utf8_decode(data=data)
|
|
97
97
|
self._string = txt
|
|
98
98
|
return txt
|
|
@@ -112,7 +112,8 @@ class Header:
|
|
|
112
112
|
if extra is not None:
|
|
113
113
|
for key in extra:
|
|
114
114
|
value = extra[key]
|
|
115
|
-
|
|
115
|
+
# TODO: encode(value)
|
|
116
|
+
pair = f'{key}={value}'
|
|
116
117
|
items.append(pair)
|
|
117
118
|
#
|
|
118
119
|
# 3. 'encoding'
|
|
@@ -139,7 +140,7 @@ class Header:
|
|
|
139
140
|
if end < 6:
|
|
140
141
|
# header empty
|
|
141
142
|
return Header(mime_type='')
|
|
142
|
-
assert end < len(uri) - 1, 'data URI error:
|
|
143
|
+
assert end < len(uri) - 1, f'data URI error: {uri}'
|
|
143
144
|
array = uri[5:end].split(';')
|
|
144
145
|
# split main info
|
|
145
146
|
mime_type: str = None
|
|
@@ -148,14 +149,14 @@ class Header:
|
|
|
148
149
|
extra: Dict[str, str] = None
|
|
149
150
|
for item in array:
|
|
150
151
|
if len(item) == 0:
|
|
151
|
-
# assert False, 'header error:
|
|
152
|
+
# assert False, f'header error: {uri}'
|
|
152
153
|
continue
|
|
153
154
|
#
|
|
154
155
|
# 2. extra info: 'charset' or 'filename'
|
|
155
156
|
#
|
|
156
157
|
pos = item.find('=')
|
|
157
158
|
if pos >= 0:
|
|
158
|
-
assert 0 < pos < len(item) - 1, 'header error:
|
|
159
|
+
assert 0 < pos < len(item) - 1, f'header error: {item}'
|
|
159
160
|
if extra is None:
|
|
160
161
|
extra = {}
|
|
161
162
|
name = item[:pos].lower()
|
|
@@ -167,14 +168,14 @@ class Header:
|
|
|
167
168
|
#
|
|
168
169
|
pos = item.find('/')
|
|
169
170
|
if pos >= 0:
|
|
170
|
-
assert 0 < pos < len(item) - 1, 'header error:
|
|
171
|
-
assert mime_type is None, 'duplicate mime-type:
|
|
171
|
+
assert 0 < pos < len(item) - 1, f'header error: {item}'
|
|
172
|
+
assert mime_type is None, f'duplicate mime-type: {uri}'
|
|
172
173
|
mime_type = item
|
|
173
174
|
continue
|
|
174
175
|
#
|
|
175
176
|
# 3. 'encoding'
|
|
176
177
|
#
|
|
177
|
-
assert encoding is None, 'duplicate encoding:
|
|
178
|
+
assert encoding is None, f'duplicate encoding: {uri}'
|
|
178
179
|
encoding = item
|
|
179
180
|
# OK
|
|
180
181
|
if mime_type is None:
|
|
@@ -258,9 +259,9 @@ class DataURI:
|
|
|
258
259
|
if text is None:
|
|
259
260
|
header = self.head.to_str()
|
|
260
261
|
if len(header) == 0:
|
|
261
|
-
text = 'data
|
|
262
|
+
text = f'data:,{self.body}'
|
|
262
263
|
else:
|
|
263
|
-
text = 'data
|
|
264
|
+
text = f'data:{header},{self.body}'
|
|
264
265
|
self.__uri_string = text
|
|
265
266
|
return text
|
|
266
267
|
|
|
@@ -277,7 +278,7 @@ class DataURI:
|
|
|
277
278
|
return None
|
|
278
279
|
pos = uri.find(',')
|
|
279
280
|
if pos < 0:
|
|
280
|
-
# assert False, 'data URI error:
|
|
281
|
+
# assert False, f'data URI error: {uri}'
|
|
281
282
|
return None
|
|
282
283
|
head = Header.split_header(uri=uri, end=pos)
|
|
283
284
|
body = uri[pos+1:]
|
|
@@ -158,8 +158,8 @@ class EmbedData(BaseData):
|
|
|
158
158
|
if extra is not None:
|
|
159
159
|
for key in extra:
|
|
160
160
|
value = extra[key]
|
|
161
|
-
header += '
|
|
162
|
-
txt = 'data
|
|
161
|
+
header += f';{key}={value}'
|
|
162
|
+
txt = f'data:{header};base64,{body}'
|
|
163
163
|
# self._string = txt
|
|
164
164
|
# parse for data URI
|
|
165
165
|
uri = DataURI.parse(uri=txt)
|
|
@@ -63,22 +63,34 @@ class TransportableFile(Mapper, TransportableResource, ABC):
|
|
|
63
63
|
@property
|
|
64
64
|
@abstractmethod
|
|
65
65
|
def data(self) -> Optional[TransportableData]:
|
|
66
|
-
|
|
66
|
+
""" Get file data """
|
|
67
|
+
raise NotImplementedError(
|
|
68
|
+
f'Not implemented: {type(self).__module__}.{type(self).__name__}.data getter'
|
|
69
|
+
)
|
|
67
70
|
|
|
68
71
|
@data.setter
|
|
69
72
|
@abstractmethod
|
|
70
73
|
def data(self, content: Optional[TransportableData]):
|
|
71
|
-
|
|
74
|
+
""" Set file data """
|
|
75
|
+
raise NotImplementedError(
|
|
76
|
+
f'Not implemented: {type(self).__module__}.{type(self).__name__}.data setter'
|
|
77
|
+
)
|
|
72
78
|
|
|
73
79
|
@property
|
|
74
80
|
@abstractmethod
|
|
75
81
|
def filename(self) -> Optional[str]:
|
|
76
|
-
|
|
82
|
+
""" Get filename """
|
|
83
|
+
raise NotImplementedError(
|
|
84
|
+
f'Not implemented: {type(self).__module__}.{type(self).__name__}.filename getter'
|
|
85
|
+
)
|
|
77
86
|
|
|
78
87
|
@filename.setter
|
|
79
88
|
@abstractmethod
|
|
80
89
|
def filename(self, string: Optional[str]):
|
|
81
|
-
|
|
90
|
+
""" Set filename """
|
|
91
|
+
raise NotImplementedError(
|
|
92
|
+
f'Not implemented: {type(self).__module__}.{type(self).__name__}.filename setter'
|
|
93
|
+
)
|
|
82
94
|
|
|
83
95
|
#
|
|
84
96
|
# Download URL
|
|
@@ -86,13 +98,18 @@ class TransportableFile(Mapper, TransportableResource, ABC):
|
|
|
86
98
|
@property
|
|
87
99
|
@abstractmethod
|
|
88
100
|
def url(self) -> Optional[URI]:
|
|
89
|
-
|
|
90
|
-
raise
|
|
101
|
+
""" Get download URL from CDN """
|
|
102
|
+
raise NotImplementedError(
|
|
103
|
+
f'Not implemented: {type(self).__module__}.{type(self).__name__}.url getter'
|
|
104
|
+
)
|
|
91
105
|
|
|
92
106
|
@url.setter
|
|
93
107
|
@abstractmethod
|
|
94
108
|
def url(self, string: Optional[URI]):
|
|
95
|
-
|
|
109
|
+
""" Set URL """
|
|
110
|
+
raise NotImplementedError(
|
|
111
|
+
f'Not implemented: {type(self).__module__}.{type(self).__name__}.url setter'
|
|
112
|
+
)
|
|
96
113
|
|
|
97
114
|
#
|
|
98
115
|
# Password for decrypting the downloaded data from CDN,
|
|
@@ -101,12 +118,18 @@ class TransportableFile(Mapper, TransportableResource, ABC):
|
|
|
101
118
|
@property
|
|
102
119
|
@abstractmethod
|
|
103
120
|
def password(self) -> Optional[DecryptKey]:
|
|
104
|
-
|
|
121
|
+
""" Get password """
|
|
122
|
+
raise NotImplementedError(
|
|
123
|
+
f'Not implemented: {type(self).__module__}.{type(self).__name__}.password getter'
|
|
124
|
+
)
|
|
105
125
|
|
|
106
126
|
@password.setter
|
|
107
127
|
@abstractmethod
|
|
108
128
|
def password(self, key: Optional[DecryptKey]):
|
|
109
|
-
|
|
129
|
+
""" Set password """
|
|
130
|
+
raise NotImplementedError(
|
|
131
|
+
f'Not implemented: {type(self).__module__}.{type(self).__name__}.password setter'
|
|
132
|
+
)
|
|
110
133
|
|
|
111
134
|
# Override
|
|
112
135
|
@abstractmethod
|
|
@@ -116,13 +139,17 @@ class TransportableFile(Mapper, TransportableResource, ABC):
|
|
|
116
139
|
|
|
117
140
|
:return: 'URL', or JSON string: '{...}'
|
|
118
141
|
"""
|
|
119
|
-
raise
|
|
142
|
+
raise NotImplementedError(
|
|
143
|
+
f'Not implemented: {type(self).__module__}.{type(self).__name__}.__str__()'
|
|
144
|
+
)
|
|
120
145
|
|
|
121
146
|
# Override
|
|
122
147
|
@abstractmethod
|
|
123
148
|
def to_dict(self) -> Dict:
|
|
124
|
-
"""
|
|
125
|
-
raise
|
|
149
|
+
""" Serialize to map """
|
|
150
|
+
raise NotImplementedError(
|
|
151
|
+
f'Not implemented: {type(self).__module__}.{type(self).__name__}.to_dict()'
|
|
152
|
+
)
|
|
126
153
|
|
|
127
154
|
# Override
|
|
128
155
|
@abstractmethod
|
|
@@ -132,7 +159,9 @@ class TransportableFile(Mapper, TransportableResource, ABC):
|
|
|
132
159
|
|
|
133
160
|
:return: str or dict
|
|
134
161
|
"""
|
|
135
|
-
|
|
162
|
+
raise NotImplementedError(
|
|
163
|
+
f'Not implemented: {type(self).__module__}.{type(self).__name__}.serialize()'
|
|
164
|
+
)
|
|
136
165
|
|
|
137
166
|
#
|
|
138
167
|
# Factory methods
|
|
@@ -183,7 +212,9 @@ class TransportableFileFactory(ABC):
|
|
|
183
212
|
:param password: decrypt key for downloaded data
|
|
184
213
|
:return: PNF object
|
|
185
214
|
"""
|
|
186
|
-
raise
|
|
215
|
+
raise NotImplementedError(
|
|
216
|
+
f'Not implemented: {type(self).__module__}.{type(self).__name__}.create_transportable_file()'
|
|
217
|
+
)
|
|
187
218
|
|
|
188
219
|
@abstractmethod
|
|
189
220
|
def parse_transportable_file(self, pnf: Dict) -> Optional[TransportableFile]:
|
|
@@ -193,7 +224,9 @@ class TransportableFileFactory(ABC):
|
|
|
193
224
|
:param pnf: PNF info
|
|
194
225
|
:return: PNF object
|
|
195
226
|
"""
|
|
196
|
-
raise
|
|
227
|
+
raise NotImplementedError(
|
|
228
|
+
f'Not implemented: {type(self).__module__}.{type(self).__name__}.parse_transportable_file()'
|
|
229
|
+
)
|
|
197
230
|
|
|
198
231
|
|
|
199
232
|
# -----------------------------------------------------------------------------
|
|
@@ -206,31 +239,49 @@ class TransportableFileHelper(ABC):
|
|
|
206
239
|
|
|
207
240
|
@abstractmethod
|
|
208
241
|
def set_transportable_file_factory(self, factory: TransportableFileFactory):
|
|
209
|
-
|
|
242
|
+
""" Set PNF factory """
|
|
243
|
+
raise NotImplementedError(
|
|
244
|
+
f'Not implemented: {type(self).__module__}.{type(self).__name__}.set_transportable_file_factory()'
|
|
245
|
+
)
|
|
210
246
|
|
|
211
247
|
@abstractmethod
|
|
212
248
|
def get_transportable_file_factory(self) -> Optional[TransportableFileFactory]:
|
|
213
|
-
|
|
249
|
+
""" Get PNF factory """
|
|
250
|
+
raise NotImplementedError(
|
|
251
|
+
f'Not implemented: {type(self).__module__}.{type(self).__name__}.get_transportable_file_factory()'
|
|
252
|
+
)
|
|
214
253
|
|
|
215
254
|
@abstractmethod
|
|
216
255
|
def create_transportable_file(self, data: Optional[TransportableData], filename: Optional[str],
|
|
217
256
|
url: Optional[URI], password: Optional[DecryptKey]) -> TransportableFile:
|
|
218
|
-
|
|
257
|
+
""" Create PNF """
|
|
258
|
+
raise NotImplementedError(
|
|
259
|
+
f'Not implemented: {type(self).__module__}.{type(self).__name__}.create_transportable_file()'
|
|
260
|
+
)
|
|
219
261
|
|
|
220
262
|
@abstractmethod
|
|
221
263
|
def parse_transportable_file(self, pnf: Any) -> Optional[TransportableFile]:
|
|
222
|
-
|
|
264
|
+
""" Parse any object to PNF """
|
|
265
|
+
raise NotImplementedError(
|
|
266
|
+
f'Not implemented: {type(self).__module__}.{type(self).__name__}.parse_transportable_file()'
|
|
267
|
+
)
|
|
223
268
|
|
|
224
269
|
|
|
225
270
|
class TransportableFileExtension:
|
|
226
271
|
|
|
227
272
|
@property
|
|
228
273
|
def pnf_helper(self) -> Optional[TransportableFileHelper]:
|
|
229
|
-
|
|
274
|
+
""" Get PNF helper """
|
|
275
|
+
raise NotImplementedError(
|
|
276
|
+
f'Not implemented: {type(self).__module__}.{type(self).__name__}.pnf_helper getter'
|
|
277
|
+
)
|
|
230
278
|
|
|
231
279
|
@pnf_helper.setter
|
|
232
280
|
def pnf_helper(self, helper: TransportableFileHelper):
|
|
233
|
-
|
|
281
|
+
""" Set PNF helper """
|
|
282
|
+
raise NotImplementedError(
|
|
283
|
+
f'Not implemented: {type(self).__module__}.{type(self).__name__}.pnf_helper setter'
|
|
284
|
+
)
|
|
234
285
|
|
|
235
286
|
|
|
236
287
|
shared_format_extensions.pnf_helper: Optional[TransportableFileHelper] = None
|