dimp 2.4.0__tar.gz → 2.4.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.
- {dimp-2.4.0 → dimp-2.4.2}/PKG-INFO +19 -7
- {dimp-2.4.0 → dimp-2.4.2}/README.md +18 -6
- {dimp-2.4.0 → dimp-2.4.2}/dimp/dkd/base.py +1 -1
- {dimp-2.4.0 → dimp-2.4.2}/dimp/dkd/envelope.py +2 -2
- {dimp-2.4.0 → dimp-2.4.2}/dimp/dkd/instant.py +3 -3
- {dimp-2.4.0 → dimp-2.4.2}/dimp/dkd/reliable.py +3 -3
- {dimp-2.4.0 → dimp-2.4.2}/dimp/dkd/secure.py +3 -4
- {dimp-2.4.0 → dimp-2.4.2}/dimp/format/base.py +6 -2
- {dimp-2.4.0 → dimp-2.4.2}/dimp/format/data.py +4 -4
- {dimp-2.4.0 → dimp-2.4.2}/dimp/format/duri.py +12 -12
- {dimp-2.4.0 → dimp-2.4.2}/dimp/format/embed.py +3 -4
- {dimp-2.4.0 → dimp-2.4.2}/dimp/format/file.py +72 -21
- {dimp-2.4.0 → dimp-2.4.2}/dimp/format/file_wrapper.py +48 -15
- {dimp-2.4.0 → dimp-2.4.2}/dimp/mkm/docs.py +4 -4
- {dimp-2.4.0 → dimp-2.4.2}/dimp/mkm/document.py +12 -12
- {dimp-2.4.0 → dimp-2.4.2}/dimp/mkm/meta.py +9 -7
- {dimp-2.4.0 → dimp-2.4.2}/dimp/protocol/assets.py +30 -9
- {dimp-2.4.0 → dimp-2.4.2}/dimp/protocol/base.py +41 -13
- {dimp-2.4.0 → dimp-2.4.2}/dimp/protocol/commands.py +19 -8
- {dimp-2.4.0 → dimp-2.4.2}/dimp/protocol/contents.py +60 -18
- {dimp-2.4.0 → dimp-2.4.2}/dimp/protocol/docs.py +27 -9
- {dimp-2.4.0 → dimp-2.4.2}/dimp/protocol/files.py +61 -21
- {dimp-2.4.0 → dimp-2.4.2}/dimp/protocol/forward.py +22 -10
- {dimp-2.4.0 → dimp-2.4.2}/dimp/protocol/groups.py +8 -2
- {dimp-2.4.0 → dimp-2.4.2}/dimp/protocol/quote.py +30 -10
- {dimp-2.4.0 → dimp-2.4.2}/dimp/protocol/receipt.py +19 -8
- {dimp-2.4.0 → dimp-2.4.2}/dimp.egg-info/PKG-INFO +19 -7
- dimp-2.4.2/dimp.egg-info/requires.txt +2 -0
- {dimp-2.4.0 → dimp-2.4.2}/setup.py +3 -3
- dimp-2.4.0/dimp.egg-info/requires.txt +0 -2
- {dimp-2.4.0 → dimp-2.4.2}/LICENSE +0 -0
- {dimp-2.4.0 → dimp-2.4.2}/dimp/__init__.py +0 -0
- {dimp-2.4.0 → dimp-2.4.2}/dimp/crypto/__init__.py +0 -0
- {dimp-2.4.0 → dimp-2.4.2}/dimp/crypto/algorithms.py +0 -0
- {dimp-2.4.0 → dimp-2.4.2}/dimp/dkd/__init__.py +0 -0
- {dimp-2.4.0 → dimp-2.4.2}/dimp/ext/__init__.py +0 -0
- {dimp-2.4.0 → dimp-2.4.2}/dimp/format/__init__.py +0 -0
- {dimp-2.4.0 → dimp-2.4.2}/dimp/format/pnf.py +0 -0
- {dimp-2.4.0 → dimp-2.4.2}/dimp/format/pnf_wrapper.py +0 -0
- {dimp-2.4.0 → dimp-2.4.2}/dimp/mkm/__init__.py +0 -0
- {dimp-2.4.0 → dimp-2.4.2}/dimp/protocol/__init__.py +0 -0
- {dimp-2.4.0 → dimp-2.4.2}/dimp/protocol/types.py +0 -0
- {dimp-2.4.0 → dimp-2.4.2}/dimp/protocol/version.py +0 -0
- {dimp-2.4.0 → dimp-2.4.2}/dimp.egg-info/SOURCES.txt +0 -0
- {dimp-2.4.0 → dimp-2.4.2}/dimp.egg-info/dependency_links.txt +0 -0
- {dimp-2.4.0 → dimp-2.4.2}/dimp.egg-info/top_level.txt +0 -0
- {dimp-2.4.0 → dimp-2.4.2}/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.2
|
|
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,5 @@ 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:
|
|
100
|
-
# TODO: get from 'key'
|
|
99
|
+
assert keys is None, f'message keys error: {keys}'
|
|
101
100
|
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
|
|
@@ -110,9 +110,9 @@ class Header:
|
|
|
110
110
|
# 2. extra info: 'charset' & 'filename'
|
|
111
111
|
#
|
|
112
112
|
if extra is not None:
|
|
113
|
-
for key in extra:
|
|
114
|
-
|
|
115
|
-
pair = '
|
|
113
|
+
for key, value in extra.items():
|
|
114
|
+
# TODO: encode(value)
|
|
115
|
+
pair = f'{key}={value}'
|
|
116
116
|
items.append(pair)
|
|
117
117
|
#
|
|
118
118
|
# 3. 'encoding'
|
|
@@ -139,7 +139,7 @@ class Header:
|
|
|
139
139
|
if end < 6:
|
|
140
140
|
# header empty
|
|
141
141
|
return Header(mime_type='')
|
|
142
|
-
assert end < len(uri) - 1, 'data URI error:
|
|
142
|
+
assert end < len(uri) - 1, f'data URI error: {uri}'
|
|
143
143
|
array = uri[5:end].split(';')
|
|
144
144
|
# split main info
|
|
145
145
|
mime_type: str = None
|
|
@@ -148,14 +148,14 @@ class Header:
|
|
|
148
148
|
extra: Dict[str, str] = None
|
|
149
149
|
for item in array:
|
|
150
150
|
if len(item) == 0:
|
|
151
|
-
# assert False, 'header error:
|
|
151
|
+
# assert False, f'header error: {uri}'
|
|
152
152
|
continue
|
|
153
153
|
#
|
|
154
154
|
# 2. extra info: 'charset' or 'filename'
|
|
155
155
|
#
|
|
156
156
|
pos = item.find('=')
|
|
157
157
|
if pos >= 0:
|
|
158
|
-
assert 0 < pos < len(item) - 1, 'header error:
|
|
158
|
+
assert 0 < pos < len(item) - 1, f'header error: {item}'
|
|
159
159
|
if extra is None:
|
|
160
160
|
extra = {}
|
|
161
161
|
name = item[:pos].lower()
|
|
@@ -167,14 +167,14 @@ class Header:
|
|
|
167
167
|
#
|
|
168
168
|
pos = item.find('/')
|
|
169
169
|
if pos >= 0:
|
|
170
|
-
assert 0 < pos < len(item) - 1, 'header error:
|
|
171
|
-
assert mime_type is None, 'duplicate mime-type:
|
|
170
|
+
assert 0 < pos < len(item) - 1, f'header error: {item}'
|
|
171
|
+
assert mime_type is None, f'duplicate mime-type: {uri}'
|
|
172
172
|
mime_type = item
|
|
173
173
|
continue
|
|
174
174
|
#
|
|
175
175
|
# 3. 'encoding'
|
|
176
176
|
#
|
|
177
|
-
assert encoding is None, 'duplicate encoding:
|
|
177
|
+
assert encoding is None, f'duplicate encoding: {uri}'
|
|
178
178
|
encoding = item
|
|
179
179
|
# OK
|
|
180
180
|
if mime_type is None:
|
|
@@ -258,9 +258,9 @@ class DataURI:
|
|
|
258
258
|
if text is None:
|
|
259
259
|
header = self.head.to_str()
|
|
260
260
|
if len(header) == 0:
|
|
261
|
-
text = 'data
|
|
261
|
+
text = f'data:,{self.body}'
|
|
262
262
|
else:
|
|
263
|
-
text = 'data
|
|
263
|
+
text = f'data:{header},{self.body}'
|
|
264
264
|
self.__uri_string = text
|
|
265
265
|
return text
|
|
266
266
|
|
|
@@ -277,7 +277,7 @@ class DataURI:
|
|
|
277
277
|
return None
|
|
278
278
|
pos = uri.find(',')
|
|
279
279
|
if pos < 0:
|
|
280
|
-
# assert False, 'data URI error:
|
|
280
|
+
# assert False, f'data URI error: {uri}'
|
|
281
281
|
return None
|
|
282
282
|
head = Header.split_header(uri=uri, end=pos)
|
|
283
283
|
body = uri[pos+1:]
|
|
@@ -156,10 +156,9 @@ class EmbedData(BaseData):
|
|
|
156
156
|
header = 'text/plain' if mime_type is None else mime_type
|
|
157
157
|
extra = self.__parameters
|
|
158
158
|
if extra is not None:
|
|
159
|
-
for key in extra:
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
txt = 'data:%s;base64,%s' % (header, body)
|
|
159
|
+
for key, value in extra.items():
|
|
160
|
+
header += f';{key}={value}'
|
|
161
|
+
txt = f'data:{header};base64,{body}'
|
|
163
162
|
# self._string = txt
|
|
164
163
|
# parse for data URI
|
|
165
164
|
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
|