oceanprotocol-job-details 0.0.10__py3-none-any.whl → 0.0.12__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.
- oceanprotocol_job_details/dataclasses/constants.py +1 -1
- oceanprotocol_job_details/dataclasses/job_details.py +5 -13
- oceanprotocol_job_details/dataclasses/ocean.py +67 -67
- oceanprotocol_job_details/job_details.py +6 -26
- oceanprotocol_job_details/loaders/impl/map.py +11 -11
- {oceanprotocol_job_details-0.0.10.dist-info → oceanprotocol_job_details-0.0.12.dist-info}/METADATA +1 -1
- oceanprotocol_job_details-0.0.12.dist-info/RECORD +15 -0
- oceanprotocol_job_details-0.0.10.dist-info/RECORD +0 -15
- {oceanprotocol_job_details-0.0.10.dist-info → oceanprotocol_job_details-0.0.12.dist-info}/WHEEL +0 -0
- {oceanprotocol_job_details-0.0.10.dist-info → oceanprotocol_job_details-0.0.12.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import json
|
|
2
1
|
import logging
|
|
3
2
|
import os
|
|
4
3
|
from dataclasses import InitVar, dataclass
|
|
5
4
|
from pathlib import Path
|
|
6
5
|
from typing import Any, Mapping, Optional, Sequence
|
|
7
6
|
|
|
7
|
+
from orjson import JSONDecodeError, loads
|
|
8
|
+
|
|
8
9
|
from oceanprotocol_job_details.dataclasses.constants import Paths
|
|
9
10
|
|
|
10
11
|
_MetadataType = Mapping[str, Any]
|
|
@@ -50,13 +51,6 @@ class JobDetails:
|
|
|
50
51
|
# Cache parameters, should not be included as _fields_ of the class
|
|
51
52
|
_parameters: InitVar[Optional[_MetadataType]] = None
|
|
52
53
|
|
|
53
|
-
def __post_init__(self, _):
|
|
54
|
-
os.makedirs(Paths.LOGS, exist_ok=True)
|
|
55
|
-
|
|
56
|
-
logging.getLogger().addHandler(
|
|
57
|
-
logging.FileHandler(Paths.LOGS / "job_details.log", mode="w")
|
|
58
|
-
)
|
|
59
|
-
|
|
60
54
|
@property
|
|
61
55
|
def parameters(self, parameters: Optional[Path] = None) -> _MetadataType:
|
|
62
56
|
"""Parameters for algorithm job, read from default path"""
|
|
@@ -66,16 +60,14 @@ class JobDetails:
|
|
|
66
60
|
|
|
67
61
|
if self._parameters is None:
|
|
68
62
|
if not parameters.exists():
|
|
69
|
-
logging.warning(
|
|
70
|
-
f"Parameters file {parameters} not found, supplying empty"
|
|
71
|
-
)
|
|
63
|
+
logging.warning(f"Missing parameters file: {parameters} not found")
|
|
72
64
|
self._parameters = {}
|
|
73
65
|
else:
|
|
74
66
|
# Load the parameters from filesystem
|
|
75
67
|
with open(parameters, "r") as f:
|
|
76
68
|
try:
|
|
77
|
-
self._parameters =
|
|
78
|
-
except
|
|
69
|
+
self._parameters = loads(f.read())
|
|
70
|
+
except JSONDecodeError as e:
|
|
79
71
|
self._parameters = {}
|
|
80
72
|
logger.warning(
|
|
81
73
|
f"Error loading parameters file {parameters}: {e}"
|
|
@@ -1,67 +1,67 @@
|
|
|
1
|
-
from dataclasses import Field
|
|
2
|
-
from datetime import datetime
|
|
3
|
-
from typing import Annotated, Any, List, Optional
|
|
4
|
-
|
|
5
|
-
from pydantic import BaseModel, HttpUrl
|
|
6
|
-
|
|
7
|
-
"""Base classes for the Ocean Protocol algorithm structure"""
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
class Credential:
|
|
11
|
-
type: Annotated[str, Field(frozen=True)]
|
|
12
|
-
values: Annotated[List[str], Field(frozen=True)]
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
class Credentials:
|
|
16
|
-
allow: Optional[Annotated[List[Credential], Field(frozen=True)]] = []
|
|
17
|
-
deny: Optional[Annotated[List[Credential], Field(frozen=True)]] = []
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
class Metadata(BaseModel):
|
|
21
|
-
"""Base class for the Metadata structure"""
|
|
22
|
-
|
|
23
|
-
description: Annotated[str, Field(frozen=True)]
|
|
24
|
-
name: Annotated[str, Field(frozen=True)]
|
|
25
|
-
type: Annotated[str, Field(frozen=True)]
|
|
26
|
-
author: Annotated[str, Field(frozen=True)]
|
|
27
|
-
license: Annotated[str, Field(frozen=True)]
|
|
28
|
-
|
|
29
|
-
algorithm: Any
|
|
30
|
-
tags: Optional[Annotated[List[str], Field(frozen=True)]] = None
|
|
31
|
-
created: Optional[Annotated[datetime, Field(frozen=True)]] = None
|
|
32
|
-
updated: Optional[Annotated[datetime, Field(frozen=True)]] = None
|
|
33
|
-
copyrightHolder: Optional[Annotated[str, Field(frozen=True)]] = None
|
|
34
|
-
links: Optional[Annotated[List[HttpUrl], Field(frozen=True)]] = None
|
|
35
|
-
contentLanguage: Optional[Annotated[str, Field(frozen=True)]] = None
|
|
36
|
-
categories: Optional[Annotated[List[str], Field(frozen=True)]] = None
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
class Service(BaseModel):
|
|
40
|
-
"""Base class for the Service structure"""
|
|
41
|
-
|
|
42
|
-
id: Annotated[str, Field(frozen=True)]
|
|
43
|
-
type: Annotated[str, Field(frozen=True)]
|
|
44
|
-
timeout: Annotated[int, Field(frozen=True)]
|
|
45
|
-
files: Annotated[str, Field(frozen=True)]
|
|
46
|
-
datatokenAddress: Annotated[str, Field(frozen=True)]
|
|
47
|
-
serviceEndpoint: Annotated[HttpUrl, Field(frozen=True)]
|
|
48
|
-
|
|
49
|
-
compute: Any
|
|
50
|
-
consumerParameters: Any
|
|
51
|
-
additionalInformation: Any
|
|
52
|
-
name: Optional[Annotated[str, Field(frozen=True)]] = None
|
|
53
|
-
description: Optional[Annotated[str, Field(frozen=True)]] = None
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
class DDO(BaseModel):
|
|
57
|
-
"""DDO structure in Ocean Protocol"""
|
|
58
|
-
|
|
59
|
-
id: Annotated[str, Field(frozen=True)]
|
|
60
|
-
context: Annotated[List[str], Field(frozen=True)]
|
|
61
|
-
version: Annotated[str, Field(frozen=True)]
|
|
62
|
-
chainId: Annotated[int, Field(frozen=True)]
|
|
63
|
-
nftAddress: Annotated[str, Field(frozen=True)]
|
|
64
|
-
metadata: Annotated[Metadata, Field(frozen=True)]
|
|
65
|
-
services: Annotated[List[Service], Field(frozen=True)]
|
|
66
|
-
|
|
67
|
-
credentials: Annotated[Optional[str], Field(frozen=True)] = None
|
|
1
|
+
from dataclasses import Field
|
|
2
|
+
from datetime import datetime
|
|
3
|
+
from typing import Annotated, Any, List, Optional
|
|
4
|
+
|
|
5
|
+
from pydantic import BaseModel, HttpUrl
|
|
6
|
+
|
|
7
|
+
"""Base classes for the Ocean Protocol algorithm structure"""
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class Credential:
|
|
11
|
+
type: Annotated[str, Field(frozen=True)]
|
|
12
|
+
values: Annotated[List[str], Field(frozen=True)]
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class Credentials:
|
|
16
|
+
allow: Optional[Annotated[List[Credential], Field(frozen=True)]] = []
|
|
17
|
+
deny: Optional[Annotated[List[Credential], Field(frozen=True)]] = []
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class Metadata(BaseModel):
|
|
21
|
+
"""Base class for the Metadata structure"""
|
|
22
|
+
|
|
23
|
+
description: Annotated[str, Field(frozen=True)]
|
|
24
|
+
name: Annotated[str, Field(frozen=True)]
|
|
25
|
+
type: Annotated[str, Field(frozen=True)]
|
|
26
|
+
author: Annotated[str, Field(frozen=True)]
|
|
27
|
+
license: Annotated[str, Field(frozen=True)]
|
|
28
|
+
|
|
29
|
+
algorithm: Any
|
|
30
|
+
tags: Optional[Annotated[List[str], Field(frozen=True)]] = None
|
|
31
|
+
created: Optional[Annotated[datetime, Field(frozen=True)]] = None
|
|
32
|
+
updated: Optional[Annotated[datetime, Field(frozen=True)]] = None
|
|
33
|
+
copyrightHolder: Optional[Annotated[str, Field(frozen=True)]] = None
|
|
34
|
+
links: Optional[Annotated[List[HttpUrl], Field(frozen=True)]] = None
|
|
35
|
+
contentLanguage: Optional[Annotated[str, Field(frozen=True)]] = None
|
|
36
|
+
categories: Optional[Annotated[List[str], Field(frozen=True)]] = None
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
class Service(BaseModel):
|
|
40
|
+
"""Base class for the Service structure"""
|
|
41
|
+
|
|
42
|
+
id: Annotated[str, Field(frozen=True)]
|
|
43
|
+
type: Annotated[str, Field(frozen=True)]
|
|
44
|
+
timeout: Annotated[int, Field(frozen=True)]
|
|
45
|
+
files: Annotated[str, Field(frozen=True)]
|
|
46
|
+
datatokenAddress: Annotated[str, Field(frozen=True)]
|
|
47
|
+
serviceEndpoint: Annotated[HttpUrl, Field(frozen=True)]
|
|
48
|
+
|
|
49
|
+
compute: Any
|
|
50
|
+
consumerParameters: Any
|
|
51
|
+
additionalInformation: Any
|
|
52
|
+
name: Optional[Annotated[str, Field(frozen=True)]] = None
|
|
53
|
+
description: Optional[Annotated[str, Field(frozen=True)]] = None
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
class DDO(BaseModel):
|
|
57
|
+
"""DDO structure in Ocean Protocol"""
|
|
58
|
+
|
|
59
|
+
id: Annotated[str, Field(frozen=True)]
|
|
60
|
+
context: Annotated[List[str], Field(frozen=True)]
|
|
61
|
+
version: Annotated[str, Field(frozen=True)]
|
|
62
|
+
chainId: Annotated[int, Field(frozen=True)]
|
|
63
|
+
nftAddress: Annotated[str, Field(frozen=True)]
|
|
64
|
+
metadata: Annotated[Metadata, Field(frozen=True)]
|
|
65
|
+
services: Annotated[List[Service], Field(frozen=True)]
|
|
66
|
+
|
|
67
|
+
credentials: Annotated[Optional[str], Field(frozen=True)] = None
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
from ctypes import ArgumentError
|
|
2
1
|
import logging
|
|
3
2
|
import os
|
|
4
3
|
from typing import Any, Literal, Mapping, Optional
|
|
@@ -14,7 +13,7 @@ logging.basicConfig(
|
|
|
14
13
|
handlers=[logging.StreamHandler()],
|
|
15
14
|
)
|
|
16
15
|
|
|
17
|
-
_Implementations = Literal["
|
|
16
|
+
_Implementations = Literal["env"]
|
|
18
17
|
|
|
19
18
|
|
|
20
19
|
class OceanProtocolJobDetails(Loader[JobDetails]):
|
|
@@ -28,33 +27,14 @@ class OceanProtocolJobDetails(Loader[JobDetails]):
|
|
|
28
27
|
*args,
|
|
29
28
|
**kwargs,
|
|
30
29
|
):
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
30
|
+
if implementation == "map":
|
|
31
|
+
# As there are not more implementations, we can use the EnvironmentLoader directly
|
|
32
|
+
self._loader = lambda: Map(mapper=mapper, keys=keys, *args, **kwargs)
|
|
33
|
+
else:
|
|
34
|
+
raise NotImplementedError(f"Implementation {implementation} not supported")
|
|
36
35
|
|
|
37
36
|
def load(self) -> JobDetails:
|
|
38
37
|
return self._loader().load()
|
|
39
38
|
|
|
40
39
|
|
|
41
40
|
del _Implementations
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
def _main():
|
|
45
|
-
"""Main function to test functionalities"""
|
|
46
|
-
|
|
47
|
-
# Re-define logging configuration
|
|
48
|
-
logging.basicConfig(
|
|
49
|
-
level=logging.DEBUG,
|
|
50
|
-
format="%(asctime)s [%(threadName)s] [%(levelname)s] %(message)s",
|
|
51
|
-
handlers=[logging.StreamHandler()],
|
|
52
|
-
force=True,
|
|
53
|
-
)
|
|
54
|
-
|
|
55
|
-
job_details = OceanProtocolJobDetails().load()
|
|
56
|
-
logging.info(f"Loaded job details: {job_details}")
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
if __name__ == "__main__":
|
|
60
|
-
_main()
|
|
@@ -41,7 +41,10 @@ def _update_paths_from_root(root: Path):
|
|
|
41
41
|
|
|
42
42
|
|
|
43
43
|
def _files_from_service(service):
|
|
44
|
-
|
|
44
|
+
files = service[DidKeys.FILES]
|
|
45
|
+
if isinstance(files, str):
|
|
46
|
+
return [files]
|
|
47
|
+
return files
|
|
45
48
|
|
|
46
49
|
|
|
47
50
|
@final
|
|
@@ -49,8 +52,6 @@ class Map(Loader[JobDetails]):
|
|
|
49
52
|
"""Loads the current Job Details from the environment variables"""
|
|
50
53
|
|
|
51
54
|
def __init__(self, mapper: Mapping[str, str], keys: Keys, *args, **kwargs) -> None:
|
|
52
|
-
super().__init__(*args, **kwargs)
|
|
53
|
-
|
|
54
55
|
self._mapper = mapper
|
|
55
56
|
self._keys = keys
|
|
56
57
|
|
|
@@ -62,7 +63,7 @@ class Map(Loader[JobDetails]):
|
|
|
62
63
|
def load(self, *args, **kwargs) -> JobDetails:
|
|
63
64
|
return self._from_dids(self._dids())
|
|
64
65
|
|
|
65
|
-
def _from_dids(self, dids: Sequence[
|
|
66
|
+
def _from_dids(self, dids: Sequence[str]) -> JobDetails:
|
|
66
67
|
return JobDetails(
|
|
67
68
|
dids=dids,
|
|
68
69
|
files=self._files(dids),
|
|
@@ -70,14 +71,14 @@ class Map(Loader[JobDetails]):
|
|
|
70
71
|
secret=self._secret(),
|
|
71
72
|
)
|
|
72
73
|
|
|
73
|
-
def _dids(self) -> Sequence[
|
|
74
|
+
def _dids(self) -> Sequence[str]:
|
|
74
75
|
return loads(self._mapper.get(self._keys.DIDS, []))
|
|
75
76
|
|
|
76
|
-
def _files(self, dids: Optional[Sequence[
|
|
77
|
+
def _files(self, dids: Optional[Sequence[str]]) -> Mapping[str, Sequence[Path]]:
|
|
77
78
|
"""Iterate through the given DIDs and retrieve their respective filepaths
|
|
78
79
|
|
|
79
80
|
:param dids: dids to read the files from
|
|
80
|
-
:type dids: Optional[Sequence[
|
|
81
|
+
:type dids: Optional[Sequence[str]]
|
|
81
82
|
:raises FileNotFoundError: if the DDO file does not exist
|
|
82
83
|
:return: _description_
|
|
83
84
|
:rtype: Mapping[str, Sequence[Path]]
|
|
@@ -86,7 +87,6 @@ class Map(Loader[JobDetails]):
|
|
|
86
87
|
files: Mapping[str, Sequence[Path]] = {}
|
|
87
88
|
for did in dids:
|
|
88
89
|
# For each given DID, check if the DDO file exists and read its metadata
|
|
89
|
-
|
|
90
90
|
ddo_path = Paths.DDOS / did
|
|
91
91
|
do(lambda: ddo_path.exists(), exc=FileNotFoundError("Missing DDO file"))
|
|
92
92
|
|
|
@@ -95,9 +95,9 @@ class Map(Loader[JobDetails]):
|
|
|
95
95
|
if not ddo:
|
|
96
96
|
continue
|
|
97
97
|
|
|
98
|
-
for service in do(lambda: ddo[DidKeys.
|
|
99
|
-
if service[DidKeys.SERVICE_TYPE] != ServiceType.METADATA:
|
|
100
|
-
|
|
98
|
+
for service in do(lambda: ddo[DidKeys.SERVICES], KeyError, default=[]):
|
|
99
|
+
# if service[DidKeys.SERVICE_TYPE] != ServiceType.METADATA:
|
|
100
|
+
# continue # Only read the metadata of the services
|
|
101
101
|
|
|
102
102
|
files_n = do(lambda: len(_files_from_service(service)), KeyError)
|
|
103
103
|
ddo_path = Paths.INPUTS / did
|
{oceanprotocol_job_details-0.0.10.dist-info → oceanprotocol_job_details-0.0.12.dist-info}/METADATA
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: oceanprotocol-job-details
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.12
|
|
4
4
|
Summary: A Python package to get details from OceanProtocol jobs
|
|
5
5
|
Project-URL: Homepage, https://github.com/AgrospAI/oceanprotocol-job-details
|
|
6
6
|
Project-URL: Issues, https://github.com/AgrospAI/oceanprotocol-job-details/issues
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
oceanprotocol_job_details/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
+
oceanprotocol_job_details/job_details.py,sha256=DfdRaoytvfFflp0nAFvCKzEm_fk4aMHHM9mC8Gs1vtU,1250
|
|
3
|
+
oceanprotocol_job_details/dataclasses/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
4
|
+
oceanprotocol_job_details/dataclasses/constants.py,sha256=GgOxQpw1_9lz4ZBuBKPQwsCBiFWN7wS0ccRQ9yv4oxk,838
|
|
5
|
+
oceanprotocol_job_details/dataclasses/job_details.py,sha256=jho4PQLyqh1iB6e5wlM9ATSZreqAo7J9hOeFdETSHgo,2311
|
|
6
|
+
oceanprotocol_job_details/dataclasses/ocean.py,sha256=u4Mc5cHPnJz9oc1a43kkWfwEqRgsFsb-Y3UP2eBpoN4,2480
|
|
7
|
+
oceanprotocol_job_details/loaders/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
8
|
+
oceanprotocol_job_details/loaders/loader.py,sha256=JwR6OSkzIQQkeeyAU-ad_F89W9WNvoRwvHQY7Q3zIXI,256
|
|
9
|
+
oceanprotocol_job_details/loaders/impl/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
10
|
+
oceanprotocol_job_details/loaders/impl/map.py,sha256=2-NscnF9saL6KTOoPBTh3UIjawvc2OdOwoGuXZpJ00U,4128
|
|
11
|
+
oceanprotocol_job_details/loaders/impl/utils.py,sha256=rxoG8PrXRSKKDYPZh-wkWOXzMfdWXrkZs0f04OfDCIs,1446
|
|
12
|
+
oceanprotocol_job_details-0.0.12.dist-info/METADATA,sha256=nNXagh8zuofDlgKUaY29XWkrghqcX-Rp1rxIn-Y-pNo,3382
|
|
13
|
+
oceanprotocol_job_details-0.0.12.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
14
|
+
oceanprotocol_job_details-0.0.12.dist-info/licenses/LICENSE,sha256=ni3ix7P_GxK1W3VGC4fJ3o6QoCngCEpSuTJwO4nkpbw,1055
|
|
15
|
+
oceanprotocol_job_details-0.0.12.dist-info/RECORD,,
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
oceanprotocol_job_details/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
-
oceanprotocol_job_details/job_details.py,sha256=dlQABSV8TQf66vaeFImyw7c4Nms417pRKiDR9d4qDhY,1668
|
|
3
|
-
oceanprotocol_job_details/dataclasses/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
4
|
-
oceanprotocol_job_details/dataclasses/constants.py,sha256=EHUhbaFpixtK5Kq2V92gbWg-jxYR-tO6ie4Ntb_FPGQ,836
|
|
5
|
-
oceanprotocol_job_details/dataclasses/job_details.py,sha256=pf8inDlS29p_PzWEeha-11HmB2f5bzpqGqVKftCkin4,2533
|
|
6
|
-
oceanprotocol_job_details/dataclasses/ocean.py,sha256=alXcGri4pgXCIGRTBbuq4XJWRlENKxrQtkswfcPTF3I,2413
|
|
7
|
-
oceanprotocol_job_details/loaders/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
8
|
-
oceanprotocol_job_details/loaders/loader.py,sha256=JwR6OSkzIQQkeeyAU-ad_F89W9WNvoRwvHQY7Q3zIXI,256
|
|
9
|
-
oceanprotocol_job_details/loaders/impl/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
10
|
-
oceanprotocol_job_details/loaders/impl/map.py,sha256=73vemnrw-PToznApzZd3BXy2znS9oSF-P1sSKw7FF38,4133
|
|
11
|
-
oceanprotocol_job_details/loaders/impl/utils.py,sha256=rxoG8PrXRSKKDYPZh-wkWOXzMfdWXrkZs0f04OfDCIs,1446
|
|
12
|
-
oceanprotocol_job_details-0.0.10.dist-info/METADATA,sha256=7VkjdCj5vY3-jfoOVekm-h3R4Xih9Fp98_ohx6W-f6M,3382
|
|
13
|
-
oceanprotocol_job_details-0.0.10.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
14
|
-
oceanprotocol_job_details-0.0.10.dist-info/licenses/LICENSE,sha256=ni3ix7P_GxK1W3VGC4fJ3o6QoCngCEpSuTJwO4nkpbw,1055
|
|
15
|
-
oceanprotocol_job_details-0.0.10.dist-info/RECORD,,
|
{oceanprotocol_job_details-0.0.10.dist-info → oceanprotocol_job_details-0.0.12.dist-info}/WHEEL
RENAMED
|
File without changes
|
|
File without changes
|