oceanprotocol-job-details 0.0.1__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-0.0.1.dist-info/LICENSE +7 -0
- oceanprotocol_job_details-0.0.1.dist-info/METADATA +31 -0
- oceanprotocol_job_details-0.0.1.dist-info/RECORD +27 -0
- oceanprotocol_job_details-0.0.1.dist-info/WHEEL +4 -0
- src/oceanprotocol_job_details/__init__.py +0 -0
- src/oceanprotocol_job_details/dataclasses/__init__.py +0 -0
- src/oceanprotocol_job_details/dataclasses/__pycache__/__init__.cpython-313.pyc +0 -0
- src/oceanprotocol_job_details/dataclasses/__pycache__/__init__.cpython-39.pyc +0 -0
- src/oceanprotocol_job_details/dataclasses/__pycache__/constants.cpython-313.pyc +0 -0
- src/oceanprotocol_job_details/dataclasses/__pycache__/constants.cpython-39.pyc +0 -0
- src/oceanprotocol_job_details/dataclasses/__pycache__/job_details.cpython-313.pyc +0 -0
- src/oceanprotocol_job_details/dataclasses/__pycache__/job_details.cpython-39.pyc +0 -0
- src/oceanprotocol_job_details/dataclasses/constants.py +38 -0
- src/oceanprotocol_job_details/dataclasses/job_details.py +35 -0
- src/oceanprotocol_job_details/job_details.py +20 -0
- src/oceanprotocol_job_details/loaders/__init__.py +0 -0
- src/oceanprotocol_job_details/loaders/__pycache__/__init__.cpython-313.pyc +0 -0
- src/oceanprotocol_job_details/loaders/__pycache__/__init__.cpython-39.pyc +0 -0
- src/oceanprotocol_job_details/loaders/__pycache__/loader.cpython-313.pyc +0 -0
- src/oceanprotocol_job_details/loaders/__pycache__/loader.cpython-39.pyc +0 -0
- src/oceanprotocol_job_details/loaders/impl/__init__.py +0 -0
- src/oceanprotocol_job_details/loaders/impl/__pycache__/__init__.cpython-313.pyc +0 -0
- src/oceanprotocol_job_details/loaders/impl/__pycache__/__init__.cpython-39.pyc +0 -0
- src/oceanprotocol_job_details/loaders/impl/__pycache__/environment.cpython-313.pyc +0 -0
- src/oceanprotocol_job_details/loaders/impl/__pycache__/environment.cpython-39.pyc +0 -0
- src/oceanprotocol_job_details/loaders/impl/environment.py +98 -0
- src/oceanprotocol_job_details/loaders/loader.py +15 -0
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
Copyright 2025 Agrospai
|
|
2
|
+
|
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
4
|
+
|
|
5
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
6
|
+
|
|
7
|
+
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
Metadata-Version: 2.3
|
|
2
|
+
Name: oceanprotocol-job-details
|
|
3
|
+
Version: 0.0.1
|
|
4
|
+
Summary: A Python package to get details from OceanProtocol jobs
|
|
5
|
+
License: Copyright 2025 Agrospai
|
|
6
|
+
|
|
7
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
8
|
+
|
|
9
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
10
|
+
|
|
11
|
+
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
12
|
+
Author: Christian López García
|
|
13
|
+
Author-email: christian.lopez@udl.cat
|
|
14
|
+
Requires-Python: >=3.9
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Operating System :: OS Independent
|
|
17
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
18
|
+
Requires-Dist: pytest (>=8.3.4,<9.0.0)
|
|
19
|
+
Project-URL: Homepage, https://github.com/AgrospAI/oceanprotocol-job-details
|
|
20
|
+
Project-URL: Issues, https://github.com/AgrospAI/oceanprotocol-job-details/issues
|
|
21
|
+
Description-Content-Type: text/markdown
|
|
22
|
+
|
|
23
|
+
A Python package to get details from OceanProtocol jobs
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## Installation
|
|
28
|
+
|
|
29
|
+
```
|
|
30
|
+
pip install oceanprotocol-job-details
|
|
31
|
+
```
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
src/oceanprotocol_job_details/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
+
src/oceanprotocol_job_details/dataclasses/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
3
|
+
src/oceanprotocol_job_details/dataclasses/__pycache__/__init__.cpython-313.pyc,sha256=0ONMfxi9YdNbrlvd7HHyKh2D2cclkF8_sfHxnk4QPT4,210
|
|
4
|
+
src/oceanprotocol_job_details/dataclasses/__pycache__/__init__.cpython-39.pyc,sha256=7IaVhvOAnm2gtr5G8j5exCNzoBYsr7hcEbDmAEEqTro,214
|
|
5
|
+
src/oceanprotocol_job_details/dataclasses/__pycache__/constants.cpython-313.pyc,sha256=_7cahtV77VBhIQRsHzVXEkdJy-hZcJfbx50EAvwhrB8,1886
|
|
6
|
+
src/oceanprotocol_job_details/dataclasses/__pycache__/constants.cpython-39.pyc,sha256=CKNB_CwiQ3ovpftAPEeQF1ZvZgz7OmpNYN7DGA94yZM,1428
|
|
7
|
+
src/oceanprotocol_job_details/dataclasses/__pycache__/job_details.cpython-313.pyc,sha256=kUxopSviCQSMPQCP5YcApB9TXUwR6XN9BI9m3rE-UKo,1369
|
|
8
|
+
src/oceanprotocol_job_details/dataclasses/__pycache__/job_details.cpython-39.pyc,sha256=C3n5BqEo0ZQo4DYXqWvMj3NYW-XKVFxWtec7dbUpJ6k,1042
|
|
9
|
+
src/oceanprotocol_job_details/dataclasses/constants.py,sha256=CWkWtBgKjI8xyHPKIwJ2lStpyCTDnfnWXvcXlIFYWig,773
|
|
10
|
+
src/oceanprotocol_job_details/dataclasses/job_details.py,sha256=7y8LoiPmAPsS71HRzm6pWbB7TwV9qIwe1Cd2Dgd4liE,860
|
|
11
|
+
src/oceanprotocol_job_details/job_details.py,sha256=w0SKnmNlAj7rBRx3uqZ3VkxFcLK15tzDKV-a2ZjJLio,765
|
|
12
|
+
src/oceanprotocol_job_details/loaders/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
13
|
+
src/oceanprotocol_job_details/loaders/__pycache__/__init__.cpython-313.pyc,sha256=caqlfFNy8aRS-NJB1cTGZcxYpTtEN-jo3ko3URP0xnA,206
|
|
14
|
+
src/oceanprotocol_job_details/loaders/__pycache__/__init__.cpython-39.pyc,sha256=pc23pM8sGE4f260FM8sT-M0Qql660vUDjtrt7phY4W8,210
|
|
15
|
+
src/oceanprotocol_job_details/loaders/__pycache__/loader.cpython-313.pyc,sha256=vHfalXDEN178-qFNfAqPhkFTSB8JhlBG_lRcpPbddUU,827
|
|
16
|
+
src/oceanprotocol_job_details/loaders/__pycache__/loader.cpython-39.pyc,sha256=tXChWYmZnyBtRgPQoHGP3i3dHMpPmxP-f_rCz92i1Gk,693
|
|
17
|
+
src/oceanprotocol_job_details/loaders/impl/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
18
|
+
src/oceanprotocol_job_details/loaders/impl/__pycache__/__init__.cpython-313.pyc,sha256=SfhHqoTLJUeOLvPm9_x4niYNVumJaP4L4ilj8GNLbR0,211
|
|
19
|
+
src/oceanprotocol_job_details/loaders/impl/__pycache__/__init__.cpython-39.pyc,sha256=zeCeX-1xNkV2K7Wc-pxUiqiA6YGSzxHtrX0MwHvs46g,215
|
|
20
|
+
src/oceanprotocol_job_details/loaders/impl/__pycache__/environment.cpython-313.pyc,sha256=hWSoqiSjFPAPuPZTiagjcHQpKDvHJU0feETedMVXenM,5628
|
|
21
|
+
src/oceanprotocol_job_details/loaders/impl/__pycache__/environment.cpython-39.pyc,sha256=jRusbU4hEZNwAceFjicor38yipl3_768zeUnOHuy5BA,3824
|
|
22
|
+
src/oceanprotocol_job_details/loaders/impl/environment.py,sha256=Eej428jnf2XX3Tv_K4sGFBKG-ZYIyDqN6e4m3_gF1JI,3041
|
|
23
|
+
src/oceanprotocol_job_details/loaders/loader.py,sha256=JwR6OSkzIQQkeeyAU-ad_F89W9WNvoRwvHQY7Q3zIXI,256
|
|
24
|
+
oceanprotocol_job_details-0.0.1.dist-info/LICENSE,sha256=ni3ix7P_GxK1W3VGC4fJ3o6QoCngCEpSuTJwO4nkpbw,1055
|
|
25
|
+
oceanprotocol_job_details-0.0.1.dist-info/METADATA,sha256=4BJ-6XobKtaD-c0lBVGGLQhxV-qdppugIIFP0DHwkY8,1857
|
|
26
|
+
oceanprotocol_job_details-0.0.1.dist-info/WHEEL,sha256=IYZQI976HJqqOpQU6PHkJ8fb3tMNBFjg-Cn-pwAbaFM,88
|
|
27
|
+
oceanprotocol_job_details-0.0.1.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
from dataclasses import dataclass
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
@dataclass(frozen=True)
|
|
6
|
+
class _DidKeys:
|
|
7
|
+
"""Common keys inside the DIDs"""
|
|
8
|
+
|
|
9
|
+
SERVICE: str = "service"
|
|
10
|
+
SERVICE_TYPE: str = "type"
|
|
11
|
+
ATTRIBUTES: str = "attributes"
|
|
12
|
+
MAIN: str = "main"
|
|
13
|
+
FILES: str = "files"
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@dataclass(frozen=True)
|
|
17
|
+
class _ServiceType:
|
|
18
|
+
"""Service types inside the DIDs"""
|
|
19
|
+
|
|
20
|
+
METADATA: str = "metadata"
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
@dataclass(frozen=True)
|
|
24
|
+
class _Paths:
|
|
25
|
+
"""Common paths used in the Ocean Protocol directories"""
|
|
26
|
+
|
|
27
|
+
DATA: Path = Path("data")
|
|
28
|
+
INPUTS: Path = DATA / "inputs"
|
|
29
|
+
DDOS: Path = DATA / "ddos"
|
|
30
|
+
OUTPUTS: Path = DATA / "outputs"
|
|
31
|
+
LOGS: Path = DATA / "logs"
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
DidKeys = _DidKeys()
|
|
35
|
+
ServiceType = _ServiceType()
|
|
36
|
+
Paths = _Paths()
|
|
37
|
+
|
|
38
|
+
del _DidKeys, _ServiceType, _Paths
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
from dataclasses import dataclass
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
from typing import Any, Mapping, Optional, Sequence
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
@dataclass(frozen=True)
|
|
7
|
+
class Algorithm:
|
|
8
|
+
did: str
|
|
9
|
+
"""The DID of the algorithm used to process the data"""
|
|
10
|
+
|
|
11
|
+
ddo: Path
|
|
12
|
+
"""The DDO path of the algorithm used to process the data"""
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
@dataclass(frozen=True)
|
|
16
|
+
class JobDetails:
|
|
17
|
+
"""Details of the current job, such as the used inputs and algorithm"""
|
|
18
|
+
|
|
19
|
+
root: Path
|
|
20
|
+
"""The root folder of the Ocean Protocol directories"""
|
|
21
|
+
|
|
22
|
+
dids: Optional[Sequence[Path]]
|
|
23
|
+
"""Identifiers for the inputs"""
|
|
24
|
+
|
|
25
|
+
metadata: Mapping[str, Any]
|
|
26
|
+
"""TODO: To define"""
|
|
27
|
+
|
|
28
|
+
files: Mapping[str, Sequence[Path]]
|
|
29
|
+
"""Paths to the input files"""
|
|
30
|
+
|
|
31
|
+
secret: Optional[str]
|
|
32
|
+
"""The secret used to process the data"""
|
|
33
|
+
|
|
34
|
+
algorithm: Optional[Algorithm]
|
|
35
|
+
"""Details of the used algorithm"""
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
from typing import Literal, Optional
|
|
2
|
+
from src.oceanprotocol_job_details.dataclasses.job_details import JobDetails
|
|
3
|
+
from src.oceanprotocol_job_details.loaders.loader import Loader
|
|
4
|
+
from src.oceanprotocol_job_details.loaders.impl.environment import EnvironmentLoader
|
|
5
|
+
|
|
6
|
+
_Implementations = Literal["env"]
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class OceanProtocolJobDetails(Loader[JobDetails]):
|
|
10
|
+
"""Decorator that loads the JobDetails from the given implementation"""
|
|
11
|
+
|
|
12
|
+
def __init__(self, implementation: Optional[_Implementations], *args, **kwargs):
|
|
13
|
+
# As there are not more implementations, we can use the EnvironmentLoader directly
|
|
14
|
+
self._loader = lambda: EnvironmentLoader(*args, **kwargs)
|
|
15
|
+
|
|
16
|
+
def load(self) -> JobDetails:
|
|
17
|
+
return self._loader().load()
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
del _Implementations
|
|
File without changes
|
|
Binary file
|
|
Binary file
|
|
File without changes
|
|
Binary file
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
"""Loads the current Job Details from the environment variables, could be abstracted to a more general 'mapper loader' but won't, since right now it fits our needs"""
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
from collections.abc import Mapping, Sequence
|
|
5
|
+
from dataclasses import dataclass
|
|
6
|
+
from json import load, loads
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
from typing import Optional, final
|
|
9
|
+
|
|
10
|
+
from src.oceanprotocol_job_details.dataclasses.constants import (
|
|
11
|
+
DidKeys,
|
|
12
|
+
Paths,
|
|
13
|
+
ServiceType,
|
|
14
|
+
)
|
|
15
|
+
from src.oceanprotocol_job_details.dataclasses.job_details import Algorithm, JobDetails
|
|
16
|
+
from src.oceanprotocol_job_details.loaders.loader import Loader
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
@dataclass(frozen=True)
|
|
20
|
+
class _Keys:
|
|
21
|
+
"""Environment keys passed to the algorithm"""
|
|
22
|
+
|
|
23
|
+
ROOT: str = "ROOT_FOLDER"
|
|
24
|
+
SECRET: str = "secret"
|
|
25
|
+
ALGORITHM: str = "TRANSFORMATION_DID"
|
|
26
|
+
DIDS: str = "DIDS"
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
Keys = _Keys()
|
|
30
|
+
del _Keys
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
@final
|
|
34
|
+
class EnvironmentLoader(Loader[JobDetails]):
|
|
35
|
+
"""Loads the current Job Details from the environment variables"""
|
|
36
|
+
|
|
37
|
+
def __init__(self, mapper: Mapping[str, str] = os.environ):
|
|
38
|
+
super().__init__()
|
|
39
|
+
self.mapper = mapper
|
|
40
|
+
|
|
41
|
+
def load(self, *args, **kwargs) -> JobDetails:
|
|
42
|
+
root, dids = self._root(), self._dids()
|
|
43
|
+
|
|
44
|
+
return JobDetails(
|
|
45
|
+
root=root,
|
|
46
|
+
dids=dids,
|
|
47
|
+
metadata=self._metadata(),
|
|
48
|
+
files=self._files(root, dids),
|
|
49
|
+
algorithm=self._algorithm(root=root),
|
|
50
|
+
secret=self._secret(),
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
def _root(self) -> Path:
|
|
54
|
+
return Path(self.mapper.get(Keys.ROOT, ""))
|
|
55
|
+
|
|
56
|
+
def _dids(self) -> Sequence[str]:
|
|
57
|
+
return loads(self.mapper.get(Keys.DIDS)) if Keys.DIDS in self.mapper else []
|
|
58
|
+
|
|
59
|
+
def _files(
|
|
60
|
+
self,
|
|
61
|
+
root: Path,
|
|
62
|
+
dids: Optional[Sequence[Path]],
|
|
63
|
+
) -> Mapping[str, Sequence[Path]]:
|
|
64
|
+
files: Mapping[str, Sequence[Path]] = {}
|
|
65
|
+
for did in dids:
|
|
66
|
+
# Retrieve DDO from disk
|
|
67
|
+
file = root / Paths.DDOS / did
|
|
68
|
+
with open(file, "r") as f:
|
|
69
|
+
ddo = load(f)
|
|
70
|
+
for service in ddo[DidKeys.SERVICE]:
|
|
71
|
+
if service[DidKeys.SERVICE_TYPE] == ServiceType.METADATA:
|
|
72
|
+
base_path = root / Paths.INPUTS / did
|
|
73
|
+
files[did] = [
|
|
74
|
+
base_path / str(idx)
|
|
75
|
+
for idx in range(
|
|
76
|
+
len(
|
|
77
|
+
service[DidKeys.ATTRIBUTES][DidKeys.MAIN][
|
|
78
|
+
DidKeys.FILES
|
|
79
|
+
]
|
|
80
|
+
)
|
|
81
|
+
)
|
|
82
|
+
]
|
|
83
|
+
return files
|
|
84
|
+
|
|
85
|
+
def _metadata(self) -> Mapping[str, str]:
|
|
86
|
+
return {}
|
|
87
|
+
|
|
88
|
+
def _algorithm(self, root: Path) -> Algorithm:
|
|
89
|
+
did = self.mapper.get(Keys.ALGORITHM, None)
|
|
90
|
+
if not did:
|
|
91
|
+
return None
|
|
92
|
+
return Algorithm(
|
|
93
|
+
did=did,
|
|
94
|
+
ddo=root / Paths.DDOS / did,
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
def _secret(self) -> str:
|
|
98
|
+
return self.mapper.get(Keys.SECRET, "")
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
from abc import ABC, abstractmethod
|
|
2
|
+
from typing import Generic, TypeVar
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
T = TypeVar("T")
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class Loader(ABC, Generic[T]):
|
|
9
|
+
@abstractmethod
|
|
10
|
+
def load(self, *args, **kwargs) -> T:
|
|
11
|
+
"""Load an instance of the given type"""
|
|
12
|
+
pass
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
del T
|