elody 0.0.220__py3-none-any.whl → 0.0.221__py3-none-any.whl
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.
- elody/job.py +47 -71
- elody/object_configurations/job_configuration.py +196 -2
- elody/util.py +13 -2
- {elody-0.0.220.dist-info → elody-0.0.221.dist-info}/METADATA +1 -1
- {elody-0.0.220.dist-info → elody-0.0.221.dist-info}/RECORD +8 -8
- {elody-0.0.220.dist-info → elody-0.0.221.dist-info}/WHEEL +0 -0
- {elody-0.0.220.dist-info → elody-0.0.221.dist-info}/licenses/LICENSE +0 -0
- {elody-0.0.220.dist-info → elody-0.0.221.dist-info}/top_level.txt +0 -0
elody/job.py
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
|
-
|
|
2
|
-
from
|
|
1
|
+
try:
|
|
2
|
+
from config import get_object_configuration_mapper
|
|
3
3
|
|
|
4
|
-
_config =
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
_config = get_object_configuration_mapper().get("job")
|
|
5
|
+
except ModuleNotFoundError:
|
|
6
|
+
from elody.object_configurations.job_configuration import JobConfiguration
|
|
7
|
+
|
|
8
|
+
_config = JobConfiguration()
|
|
7
9
|
|
|
8
10
|
|
|
9
11
|
def add_document_to_job(
|
|
@@ -12,18 +14,11 @@ def add_document_to_job(
|
|
|
12
14
|
*,
|
|
13
15
|
get_rabbit,
|
|
14
16
|
):
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
document = {
|
|
21
|
-
"id": id,
|
|
22
|
-
"patch": {
|
|
23
|
-
"relations": (relations),
|
|
24
|
-
},
|
|
25
|
-
}
|
|
26
|
-
_post_crud_hook(crud="update", document=document, get_rabbit=get_rabbit)
|
|
17
|
+
_config.crud()["add_document_to_job"](
|
|
18
|
+
id=id,
|
|
19
|
+
id_of_document_job_was_initiated_for=id_of_document_job_was_initiated_for,
|
|
20
|
+
get_rabbit=get_rabbit,
|
|
21
|
+
)
|
|
27
22
|
|
|
28
23
|
|
|
29
24
|
def init_job(
|
|
@@ -35,76 +30,57 @@ def init_job(
|
|
|
35
30
|
user_email=None,
|
|
36
31
|
parent_id=None,
|
|
37
32
|
id_of_document_job_was_initiated_for=None,
|
|
33
|
+
track_async_children: bool | None = None,
|
|
38
34
|
) -> str:
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
{
|
|
49
|
-
"metadata": [
|
|
50
|
-
{"key": "name", "value": name},
|
|
51
|
-
{"key": "status", "value": "queued"},
|
|
52
|
-
{"key": "type", "value": job_type},
|
|
53
|
-
],
|
|
54
|
-
"relations": relations,
|
|
55
|
-
"type": "job",
|
|
56
|
-
},
|
|
57
|
-
get_user_context=get_user_context
|
|
58
|
-
or (lambda: type("UserContext", (object,), {"email": user_email})()),
|
|
35
|
+
return _config.crud()["init_job"](
|
|
36
|
+
name=name,
|
|
37
|
+
job_type=job_type,
|
|
38
|
+
get_rabbit=get_rabbit,
|
|
39
|
+
get_user_context=get_user_context,
|
|
40
|
+
user_email=user_email,
|
|
41
|
+
parent_id=parent_id,
|
|
42
|
+
id_of_document_job_was_initiated_for=id_of_document_job_was_initiated_for,
|
|
43
|
+
track_async_children=track_async_children,
|
|
59
44
|
)
|
|
60
45
|
|
|
61
|
-
_post_crud_hook(
|
|
62
|
-
crud="create", document=job, parent_id=parent_id, get_rabbit=get_rabbit
|
|
63
|
-
)
|
|
64
|
-
return job["_id"]
|
|
65
|
-
|
|
66
46
|
|
|
67
47
|
def start_job(
|
|
68
48
|
id,
|
|
69
|
-
id_of_document_job_was_initiated_for=None,
|
|
70
49
|
*,
|
|
71
50
|
get_rabbit,
|
|
72
51
|
):
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
"metadata": [{"key": "status", "value": "running"}],
|
|
78
|
-
"relations": ([] if id_of_document_job_was_initiated_for else []),
|
|
79
|
-
},
|
|
80
|
-
}
|
|
81
|
-
_post_crud_hook(crud="update", document=document, get_rabbit=get_rabbit)
|
|
52
|
+
_config.crud()["start_job"](
|
|
53
|
+
id=id,
|
|
54
|
+
get_rabbit=get_rabbit,
|
|
55
|
+
)
|
|
82
56
|
|
|
83
57
|
|
|
84
58
|
def finish_job(
|
|
85
59
|
id,
|
|
86
|
-
id_of_document_job_was_initiated_for=None,
|
|
87
60
|
*,
|
|
88
61
|
get_rabbit,
|
|
89
62
|
):
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
63
|
+
_config.crud()["finish_job"](
|
|
64
|
+
id=id,
|
|
65
|
+
get_rabbit=get_rabbit,
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def soft_finish_job(
|
|
70
|
+
id,
|
|
71
|
+
*,
|
|
72
|
+
get_rabbit,
|
|
73
|
+
):
|
|
74
|
+
_config.crud()["soft_finish_job"](id=id, get_rabbit=get_rabbit)
|
|
98
75
|
|
|
99
76
|
|
|
100
77
|
def fail_job(id, exception_message, *, get_rabbit):
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
_post_crud_hook(crud="update", document=document, get_rabbit=get_rabbit)
|
|
78
|
+
_config.crud()["fail_job"](
|
|
79
|
+
id=id, exception_message=exception_message, get_rabbit=get_rabbit
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def handle_parent_job_finished(id, parent_child_status, *, get_rabbit):
|
|
84
|
+
_config.crud()["handle_parent_job_finished"](
|
|
85
|
+
id=id, parent_child_status=parent_child_status, get_rabbit=get_rabbit
|
|
86
|
+
)
|
|
@@ -1,8 +1,20 @@
|
|
|
1
|
+
from datetime import datetime, timezone
|
|
2
|
+
from enum import Enum
|
|
3
|
+
from os import getenv
|
|
4
|
+
from typing import Literal
|
|
5
|
+
|
|
1
6
|
from elody.object_configurations.elody_configuration import (
|
|
2
7
|
ElodyConfiguration,
|
|
3
8
|
)
|
|
4
9
|
from elody.util import send_cloudevent
|
|
5
|
-
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class Status(str, Enum):
|
|
13
|
+
QUEUED = "queued"
|
|
14
|
+
RUNNING = "running"
|
|
15
|
+
FINISHED = "finished"
|
|
16
|
+
FAILED = "failed"
|
|
17
|
+
WARNING = "warning"
|
|
6
18
|
|
|
7
19
|
|
|
8
20
|
class JobConfiguration(ElodyConfiguration):
|
|
@@ -10,7 +22,23 @@ class JobConfiguration(ElodyConfiguration):
|
|
|
10
22
|
SCHEMA_VERSION = 1
|
|
11
23
|
|
|
12
24
|
def crud(self):
|
|
13
|
-
crud = {
|
|
25
|
+
crud = {
|
|
26
|
+
"collection": "jobs",
|
|
27
|
+
"collection_history": "",
|
|
28
|
+
"add_document_to_job": lambda *args, **kwargs: self._add_document_to_job(
|
|
29
|
+
*args, **kwargs
|
|
30
|
+
),
|
|
31
|
+
"init_job": lambda *args, **kwargs: self._init_job(*args, **kwargs),
|
|
32
|
+
"start_job": lambda *args, **kwargs: self._start_job(*args, **kwargs),
|
|
33
|
+
"finish_job": lambda *args, **kwargs: self._finish_job(*args, **kwargs),
|
|
34
|
+
"finish_job_with_warning": lambda *args, **kwargs: self._finish_job_with_warning(
|
|
35
|
+
*args, **kwargs
|
|
36
|
+
),
|
|
37
|
+
"fail_job": lambda *args, **kwargs: self._fail_job(*args, **kwargs),
|
|
38
|
+
"handle_parent_job_finished": lambda *args, **kwargs: self._handle_parent_job_finished(
|
|
39
|
+
*args, **kwargs
|
|
40
|
+
),
|
|
41
|
+
}
|
|
14
42
|
return {**super().crud(), **crud}
|
|
15
43
|
|
|
16
44
|
def document_info(self):
|
|
@@ -49,3 +77,169 @@ class JobConfiguration(ElodyConfiguration):
|
|
|
49
77
|
"dams.job_changed",
|
|
50
78
|
document,
|
|
51
79
|
)
|
|
80
|
+
|
|
81
|
+
def _add_document_to_job(
|
|
82
|
+
self,
|
|
83
|
+
id,
|
|
84
|
+
id_of_document_job_was_initiated_for,
|
|
85
|
+
*,
|
|
86
|
+
get_rabbit,
|
|
87
|
+
):
|
|
88
|
+
relations = []
|
|
89
|
+
if id_of_document_job_was_initiated_for:
|
|
90
|
+
relations.append(
|
|
91
|
+
{"key": id_of_document_job_was_initiated_for, "type": "isJobFor"}
|
|
92
|
+
)
|
|
93
|
+
document = {
|
|
94
|
+
"id": id,
|
|
95
|
+
"patch": {
|
|
96
|
+
"relations": (relations),
|
|
97
|
+
},
|
|
98
|
+
}
|
|
99
|
+
self._post_crud_hook(crud="update", document=document, get_rabbit=get_rabbit)
|
|
100
|
+
|
|
101
|
+
def _init_job(
|
|
102
|
+
self,
|
|
103
|
+
name,
|
|
104
|
+
job_type,
|
|
105
|
+
*,
|
|
106
|
+
get_rabbit,
|
|
107
|
+
get_user_context=None,
|
|
108
|
+
user_email=None,
|
|
109
|
+
parent_id=None,
|
|
110
|
+
id_of_document_job_was_initiated_for=None,
|
|
111
|
+
track_async_children: bool | None = None,
|
|
112
|
+
) -> str:
|
|
113
|
+
relations = []
|
|
114
|
+
if parent_id:
|
|
115
|
+
relations.append({"key": parent_id, "type": "hasParentJob"})
|
|
116
|
+
if id_of_document_job_was_initiated_for:
|
|
117
|
+
relations.append(
|
|
118
|
+
{"key": id_of_document_job_was_initiated_for, "type": "isJobFor"}
|
|
119
|
+
)
|
|
120
|
+
|
|
121
|
+
metadata = [
|
|
122
|
+
{"key": "name", "value": name},
|
|
123
|
+
{"key": "status", "value": Status.QUEUED.value},
|
|
124
|
+
{"key": "type", "value": job_type},
|
|
125
|
+
]
|
|
126
|
+
|
|
127
|
+
if track_async_children:
|
|
128
|
+
metadata.append(
|
|
129
|
+
{
|
|
130
|
+
"key": "child_jobs",
|
|
131
|
+
"value": {
|
|
132
|
+
Status.QUEUED.value: 0,
|
|
133
|
+
Status.RUNNING.value: 0,
|
|
134
|
+
Status.FAILED.value: 0,
|
|
135
|
+
Status.FINISHED.value: 0,
|
|
136
|
+
Status.WARNING.value: 0,
|
|
137
|
+
},
|
|
138
|
+
}
|
|
139
|
+
)
|
|
140
|
+
|
|
141
|
+
job = self.crud()["creator"](
|
|
142
|
+
{
|
|
143
|
+
"metadata": metadata,
|
|
144
|
+
"relations": relations,
|
|
145
|
+
"type": "job",
|
|
146
|
+
},
|
|
147
|
+
get_user_context=get_user_context
|
|
148
|
+
or (lambda: type("UserContext", (object,), {"email": user_email})()),
|
|
149
|
+
)
|
|
150
|
+
|
|
151
|
+
self._post_crud_hook(
|
|
152
|
+
crud="create", document=job, parent_id=parent_id, get_rabbit=get_rabbit
|
|
153
|
+
)
|
|
154
|
+
return job["_id"]
|
|
155
|
+
|
|
156
|
+
def _start_job(
|
|
157
|
+
self,
|
|
158
|
+
id,
|
|
159
|
+
*,
|
|
160
|
+
get_rabbit,
|
|
161
|
+
):
|
|
162
|
+
document = {
|
|
163
|
+
"id": id,
|
|
164
|
+
"patch": {
|
|
165
|
+
"started_at": datetime.now(timezone.utc),
|
|
166
|
+
"metadata": [{"key": "status", "value": Status.RUNNING.value}],
|
|
167
|
+
},
|
|
168
|
+
}
|
|
169
|
+
self._post_crud_hook(crud="update", document=document, get_rabbit=get_rabbit)
|
|
170
|
+
|
|
171
|
+
def _finish_job(
|
|
172
|
+
self,
|
|
173
|
+
id,
|
|
174
|
+
*,
|
|
175
|
+
get_rabbit,
|
|
176
|
+
):
|
|
177
|
+
document = {
|
|
178
|
+
"id": id,
|
|
179
|
+
"patch": {
|
|
180
|
+
"metadata": [{"key": "status", "value": Status.FINISHED.value}],
|
|
181
|
+
},
|
|
182
|
+
}
|
|
183
|
+
self._post_crud_hook(crud="update", document=document, get_rabbit=get_rabbit)
|
|
184
|
+
|
|
185
|
+
def _finish_job_with_warning(
|
|
186
|
+
self,
|
|
187
|
+
id,
|
|
188
|
+
*,
|
|
189
|
+
get_rabbit,
|
|
190
|
+
info_message=None,
|
|
191
|
+
):
|
|
192
|
+
document = {
|
|
193
|
+
"id": id,
|
|
194
|
+
"patch": {
|
|
195
|
+
"metadata": [
|
|
196
|
+
{"key": "status", "value": Status.FINISHED.value},
|
|
197
|
+
{"key": "info", "value": info_message},
|
|
198
|
+
],
|
|
199
|
+
},
|
|
200
|
+
}
|
|
201
|
+
self._post_crud_hook(crud="update", document=document, get_rabbit=get_rabbit)
|
|
202
|
+
|
|
203
|
+
def _fail_job(self, id, exception_message, *, get_rabbit):
|
|
204
|
+
|
|
205
|
+
status, message = self.__handle_error_warnings(exception_message)
|
|
206
|
+
|
|
207
|
+
document = {
|
|
208
|
+
"id": id,
|
|
209
|
+
"patch": {
|
|
210
|
+
"metadata": [
|
|
211
|
+
{"key": "info", "value": message},
|
|
212
|
+
{
|
|
213
|
+
"key": "status",
|
|
214
|
+
"value": (status.value),
|
|
215
|
+
},
|
|
216
|
+
]
|
|
217
|
+
},
|
|
218
|
+
}
|
|
219
|
+
self._post_crud_hook(crud="update", document=document, get_rabbit=get_rabbit)
|
|
220
|
+
|
|
221
|
+
def _handle_parent_job_finished(self, id, parent_child_status, *, get_rabbit):
|
|
222
|
+
|
|
223
|
+
child_jobs_failed = parent_child_status[Status.FAILED.value]
|
|
224
|
+
child_jobs_warning = parent_child_status[Status.WARNING.value]
|
|
225
|
+
|
|
226
|
+
if child_jobs_failed == 0:
|
|
227
|
+
if child_jobs_warning:
|
|
228
|
+
self.crud()["finish_job_with_warning"](
|
|
229
|
+
id, get_rabbit=get_rabbit, info_message="Some subjobs have warnings"
|
|
230
|
+
)
|
|
231
|
+
self.crud()["finish_job"](id, get_rabbit=get_rabbit)
|
|
232
|
+
else:
|
|
233
|
+
self.crud()["fail_job"](
|
|
234
|
+
id, exception_message="some subjobs failed", get_rabbit=get_rabbit
|
|
235
|
+
)
|
|
236
|
+
|
|
237
|
+
def __handle_error_warnings(
|
|
238
|
+
self,
|
|
239
|
+
errormessage: str,
|
|
240
|
+
) -> tuple[Literal[Status.WARNING] | Literal[Status.FAILED], str]:
|
|
241
|
+
|
|
242
|
+
if errormessage.startswith("W4009"):
|
|
243
|
+
return Status.WARNING, errormessage
|
|
244
|
+
|
|
245
|
+
return Status.FAILED, errormessage
|
elody/util.py
CHANGED
|
@@ -125,6 +125,13 @@ def get_item_metadata_value(item, key):
|
|
|
125
125
|
return ""
|
|
126
126
|
|
|
127
127
|
|
|
128
|
+
def get_item_relation_key(item, type):
|
|
129
|
+
for item in item.get("relations", []):
|
|
130
|
+
if item["type"] == type:
|
|
131
|
+
return item["key"]
|
|
132
|
+
return ""
|
|
133
|
+
|
|
134
|
+
|
|
128
135
|
def get_mimetype_from_filename(filename):
|
|
129
136
|
mime = mimetypes.guess_type(filename, False)[0]
|
|
130
137
|
return mime if mime else "application/octet-stream"
|
|
@@ -267,8 +274,12 @@ def signal_update_copyright_color_mediafile(mq_client, mediafile_id):
|
|
|
267
274
|
send_cloudevent(mq_client, "dams", "dams.update_copyright_color_mediafile", data)
|
|
268
275
|
|
|
269
276
|
|
|
270
|
-
def signal_upload_file(mq_client, upload_links, selected_folder):
|
|
271
|
-
data = {
|
|
277
|
+
def signal_upload_file(mq_client, upload_links, selected_folder, parent_job_id=None):
|
|
278
|
+
data = {
|
|
279
|
+
"upload_links": upload_links,
|
|
280
|
+
"selected_folder": selected_folder,
|
|
281
|
+
"parent_job_id": parent_job_id,
|
|
282
|
+
}
|
|
272
283
|
send_cloudevent(mq_client, "dams", "dams.upload_file", data)
|
|
273
284
|
|
|
274
285
|
|
|
@@ -4,17 +4,17 @@ elody/client.py,sha256=15SBfnLHJXXY5Vf5BnkWdjtvkH21E_AsWTzm2-zcbf0,8799
|
|
|
4
4
|
elody/csv.py,sha256=f8HphE-KC2OqKFzV0HiifWBgMHb3g0EA_Y82o_6JEiE,16761
|
|
5
5
|
elody/error_codes.py,sha256=d3wNPZU0HFMyl8xN95ciNd6QD94al1tX18h6HiqiAHo,4310
|
|
6
6
|
elody/exceptions.py,sha256=5KSw2sPCZz3lDIJX4LiR2iL9n4m4KIil04D1d3X5rd0,968
|
|
7
|
-
elody/job.py,sha256=
|
|
7
|
+
elody/job.py,sha256=EGfYozNxyx2iLC-j_L5XLzV3hUAOM9UIFuYzyqKpS1w,1908
|
|
8
8
|
elody/loader.py,sha256=yNakab07ja478gZaIC277n8Wf8SJ7_P3q-Z39BDdWQc,5419
|
|
9
9
|
elody/schemas.py,sha256=WtKdZEAX-PtEuAaRohyS3Md8H4-8yKVXMkHfCQ2SDR4,4676
|
|
10
|
-
elody/util.py,sha256=
|
|
10
|
+
elody/util.py,sha256=Qcoe49DsoJwXLFNevR67U_04iuJkmX4Pl0bcJ0Alrh0,9325
|
|
11
11
|
elody/validator.py,sha256=G7Ya538EJHCFzOxEri2OcFMabfLBCtTKxuf4os_KuNw,260
|
|
12
12
|
elody/migration/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
13
13
|
elody/migration/base_object_migrator.py,sha256=n8uvgGfjEUy60G47RD7Y-oxp1vHLOauwPMDl87LcxtU,436
|
|
14
14
|
elody/object_configurations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
15
15
|
elody/object_configurations/base_object_configuration.py,sha256=AqOE0hCbXQDOdKFnDa9dbi-A-GRTUAaBZUe6_g0-Dc0,7573
|
|
16
16
|
elody/object_configurations/elody_configuration.py,sha256=T_gyQykQWC1wdGTwQ9DujmumG8uqgQlH0vbZKmxtpfw,11049
|
|
17
|
-
elody/object_configurations/job_configuration.py,sha256
|
|
17
|
+
elody/object_configurations/job_configuration.py,sha256=T6QI2wE-u7ZcNpYE5XjmrCzIJglyKUGJsifaTn0WGyg,7512
|
|
18
18
|
elody/object_configurations/saved_search_configuration.py,sha256=ddOry4EqYOeEKRF7q2M_fHoqZv8DXpQjFq8VaZ7jhVI,732
|
|
19
19
|
elody/policies/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
20
20
|
elody/policies/helpers.py,sha256=0mlTd-hu2TKwVNH3ov4yCEV-P_f2k7XFJ7XYUtGTjXk,2239
|
|
@@ -35,13 +35,13 @@ elody/policies/authorization/mediafile_derivatives_policy.py,sha256=OwNpbS8i7-Lz
|
|
|
35
35
|
elody/policies/authorization/mediafile_download_policy.py,sha256=XMsKavBucmTh4W1kWOzpFWxJ_ZXgHVK1RS7JB4HjtQo,1979
|
|
36
36
|
elody/policies/authorization/multi_tenant_policy.py,sha256=SA9H7SBjzuh8mY3gYN7pDG8TV7hdI3GEUtNeiZeNL3M,3164
|
|
37
37
|
elody/policies/authorization/tenant_request_policy.py,sha256=dEgblwRAqwWVcE-O7Jn8hVL3OnwDlQhDEOcPlcElBrk,1185
|
|
38
|
-
elody-0.0.
|
|
38
|
+
elody-0.0.221.dist-info/licenses/LICENSE,sha256=gXf5dRMhNSbfLPYYTY_5hsZ1r7UU1OaKQEAQUhuIBkM,18092
|
|
39
39
|
tests/__init_.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
40
40
|
tests/data.py,sha256=Q3oxduf-E3m-Z5G_p3fcs8jVy6g10I7zXKL1m94UVMI,2906
|
|
41
41
|
tests/unit/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
42
42
|
tests/unit/test_csv.py,sha256=NQaOhehfQ4GuXku0Y1SA8DYjJeqqidbF50zEHAi8RZA,15923
|
|
43
43
|
tests/unit/test_utils.py,sha256=g63szcEZyHhCOtrW4BnNbcgVca3oYPIOLjBdIzNwwN0,8784
|
|
44
|
-
elody-0.0.
|
|
45
|
-
elody-0.0.
|
|
46
|
-
elody-0.0.
|
|
47
|
-
elody-0.0.
|
|
44
|
+
elody-0.0.221.dist-info/METADATA,sha256=uIEM5H42sBDimKD8UkKIatHIvjiFiNOIWfJ95lDEDVQ,23358
|
|
45
|
+
elody-0.0.221.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
46
|
+
elody-0.0.221.dist-info/top_level.txt,sha256=E0mImupLj0KmtUUCXRYEoLDRaSkuiGaOIIseAa0oQ-M,21
|
|
47
|
+
elody-0.0.221.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|