oceanprotocol-job-details 0.0.7__py3-none-any.whl → 0.0.9__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.
@@ -2,7 +2,9 @@ from dataclasses import dataclass
2
2
  from pathlib import Path
3
3
 
4
4
 
5
- @dataclass(frozen=True)
5
+ @dataclass(
6
+ frozen=True,
7
+ )
6
8
  class _DidKeys:
7
9
  """Common keys inside the DIDs"""
8
10
 
@@ -13,18 +15,20 @@ class _DidKeys:
13
15
  FILES: str = "files"
14
16
 
15
17
 
16
- @dataclass(frozen=True)
18
+ @dataclass(
19
+ frozen=True,
20
+ )
17
21
  class _ServiceType:
18
22
  """Service types inside the DIDs"""
19
23
 
20
24
  METADATA: str = "metadata"
21
25
 
22
26
 
23
- @dataclass(frozen=True)
27
+ @dataclass()
24
28
  class _Paths:
25
29
  """Common paths used in the Ocean Protocol directories"""
26
30
 
27
- DATA: Path = Path("data")
31
+ DATA: Path = Path("/data")
28
32
 
29
33
  INPUTS: Path = DATA / "inputs"
30
34
  DDOS: Path = DATA / "ddos"
@@ -12,7 +12,9 @@ _MetadataType = Mapping[str, Any]
12
12
  logger = logging.getLogger(__name__)
13
13
 
14
14
 
15
- @dataclass(frozen=True)
15
+ @dataclass(
16
+ frozen=True,
17
+ )
16
18
  class Parameters:
17
19
  """Custom data for the algorithm, such as the algorithm's parameters"""
18
20
 
@@ -20,7 +22,9 @@ class Parameters:
20
22
  """The parameters used by the algorithm"""
21
23
 
22
24
 
23
- @dataclass(frozen=True)
25
+ @dataclass(
26
+ frozen=True,
27
+ )
24
28
  class Algorithm:
25
29
  """Details of the algorithm used to process the data"""
26
30
 
@@ -35,9 +39,6 @@ class Algorithm:
35
39
  class JobDetails:
36
40
  """Details of the current job, such as the used inputs and algorithm"""
37
41
 
38
- root: Path
39
- """The root folder of the Ocean Protocol directories"""
40
-
41
42
  dids: Sequence[Path]
42
43
  """Identifiers for the inputs"""
43
44
 
@@ -53,22 +54,28 @@ class JobDetails:
53
54
  # Cache parameters, should not be included as _fields_ of the class
54
55
  _parameters: InitVar[Optional[_MetadataType]] = None
55
56
 
56
- def __post_init__(self, _):
57
- os.makedirs(self.root / Paths.LOGS, exist_ok=True)
57
+ def __post_init__(
58
+ self,
59
+ _,
60
+ ):
61
+ os.makedirs(Paths.LOGS, exist_ok=True)
58
62
 
59
63
  logging.getLogger().addHandler(
60
64
  logging.FileHandler(
61
- self.root / Paths.LOGS / "job_details.log",
65
+ Paths.LOGS / "job_details.log",
62
66
  mode="w",
63
67
  )
64
68
  )
65
69
 
66
70
  @property
67
- def parameters(self, parameters: Optional[Path] = None) -> _MetadataType:
71
+ def parameters(
72
+ self,
73
+ parameters: Optional[Path] = None,
74
+ ) -> _MetadataType:
68
75
  """Parameters for algorithm job, read from default path"""
69
76
 
70
77
  if parameters is None:
71
- parameters = self.root / Paths.ALGORITHM_CUSTOM_PARAMETERS
78
+ parameters = Paths.ALGORITHM_CUSTOM_PARAMETERS
72
79
 
73
80
  if self._parameters is None:
74
81
  if not parameters.exists():
@@ -18,7 +18,9 @@ logging.basicConfig(
18
18
  _Implementations = Literal["env"]
19
19
 
20
20
 
21
- class OceanProtocolJobDetails(Loader[JobDetails]):
21
+ class OceanProtocolJobDetails(
22
+ Loader[JobDetails],
23
+ ):
22
24
  """Decorator that loads the JobDetails from the given implementation"""
23
25
 
24
26
  def __init__(
@@ -31,11 +33,18 @@ class OceanProtocolJobDetails(Loader[JobDetails]):
31
33
  ):
32
34
  if implementation == "map":
33
35
  # As there are not more implementations, we can use the EnvironmentLoader directly
34
- self._loader = lambda: Map(mapper=mapper, keys=keys, *args, **kwargs)
36
+ self._loader = lambda: Map(
37
+ mapper=mapper,
38
+ keys=keys,
39
+ *args,
40
+ **kwargs,
41
+ )
35
42
  else:
36
43
  raise NotImplementedError(f"Implementation {implementation} not supported")
37
44
 
38
- def load(self) -> JobDetails:
45
+ def load(
46
+ self,
47
+ ) -> JobDetails:
39
48
  return self._loader().load()
40
49
 
41
50
 
@@ -1,6 +1,6 @@
1
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
2
 
3
- from dataclasses import dataclass
3
+ from dataclasses import dataclass, asdict
4
4
  from json import JSONDecodeError, load, loads
5
5
  from logging import getLogger
6
6
  from pathlib import Path
@@ -13,46 +13,66 @@ from oceanprotocol_job_details.loaders.loader import Loader
13
13
  logger = getLogger(__name__)
14
14
 
15
15
 
16
- @dataclass(frozen=True)
16
+ @dataclass(
17
+ frozen=True,
18
+ )
17
19
  class Keys:
18
20
  """Environment keys passed to the algorithm"""
19
21
 
20
- ROOT: str = "ROOT_FOLDER"
22
+ ROOT_FOLDER = "ROOT_FOLDER"
21
23
  SECRET: str = "secret"
22
24
  ALGORITHM: str = "TRANSFORMATION_DID"
23
25
  DIDS: str = "DIDS"
24
26
 
25
27
 
26
28
  @final
27
- class Map(Loader[JobDetails]):
29
+ class Map(
30
+ Loader[JobDetails],
31
+ ):
28
32
  """Loads the current Job Details from the environment variables"""
29
33
 
30
- def __init__(self, mapper: Mapping[str, str], keys: Keys, *args, **kwargs):
34
+ def __init__(
35
+ self,
36
+ mapper: Mapping[str, str],
37
+ keys: Keys,
38
+ *args,
39
+ **kwargs,
40
+ ) -> None:
31
41
  super().__init__(*args, **kwargs)
32
42
 
33
43
  self._mapper = mapper
34
44
  self._keys = keys
35
45
 
36
- def load(self, *args, **kwargs) -> JobDetails:
37
- root, dids = self._root(), self._dids()
46
+ # Update the default Paths if the user has passed a root folder
47
+ if Keys.ROOT_FOLDER in self._mapper:
48
+ root = self._mapper[Keys.ROOT_FOLDER]
49
+
50
+ # Update the rest of paths
51
+ Paths.DATA = Path(root) / "data"
52
+ Paths.INPUTS = Paths.DATA / "inputs"
53
+ Paths.DDOS = Paths.DATA / "ddos"
54
+ Paths.OUTPUTS = Paths.DATA / "outputs"
55
+ Paths.LOGS = Paths.DATA / "logs"
56
+ Paths.ALGORITHM_CUSTOM_PARAMETERS = Paths.INPUTS / "algoCustomData.json"
57
+
58
+
59
+ def load(
60
+ self,
61
+ *args,
62
+ **kwargs,
63
+ ) -> JobDetails:
64
+ dids = self._dids()
38
65
 
39
66
  return JobDetails(
40
- root=root,
41
67
  dids=dids,
42
- files=self._files(root, dids),
43
- algorithm=self._algorithm(root),
68
+ files=self._files(dids),
69
+ algorithm=self._algorithm(),
44
70
  secret=self._secret(),
45
71
  )
46
72
 
47
- def _root(self) -> Path:
48
- root = Path(self._mapper.get(self._keys.ROOT, Path.home()))
49
-
50
- if not root.exists():
51
- raise FileNotFoundError(f"Root folder {root} does not exist")
52
-
53
- return root
54
-
55
- def _dids(self) -> Sequence[Path]:
73
+ def _dids(
74
+ self,
75
+ ) -> Sequence[Path]:
56
76
  return (
57
77
  loads(self._mapper.get(self._keys.DIDS))
58
78
  if self._keys.DIDS in self._mapper
@@ -61,15 +81,13 @@ class Map(Loader[JobDetails]):
61
81
 
62
82
  def _files(
63
83
  self,
64
- root: Path,
65
84
  dids: Optional[Sequence[Path]],
66
85
  ) -> Mapping[str, Sequence[Path]]:
67
-
68
86
  files: Mapping[str, Sequence[Path]] = {}
69
87
 
70
88
  for did in dids:
71
89
  # Retrieve DDO from disk
72
- file_path = root / Paths.DDOS / did
90
+ file_path = Paths.DDOS / did
73
91
  if not file_path.exists():
74
92
  raise FileNotFoundError(f"DDO file {file_path} does not exist")
75
93
 
@@ -84,7 +102,7 @@ class Map(Loader[JobDetails]):
84
102
  if service[DidKeys.SERVICE_TYPE] != ServiceType.METADATA:
85
103
  continue
86
104
 
87
- did_path = root / Paths.INPUTS / did
105
+ did_path = Paths.INPUTS / did
88
106
  files[did] = [
89
107
  did_path / str(idx)
90
108
  for idx in range(
@@ -96,17 +114,21 @@ class Map(Loader[JobDetails]):
96
114
 
97
115
  return files
98
116
 
99
- def _algorithm(self, root: Path) -> Optional[Algorithm]:
117
+ def _algorithm(
118
+ self,
119
+ ) -> Optional[Algorithm]:
100
120
  did = self._mapper.get(self._keys.ALGORITHM, None)
101
121
 
102
122
  if not did:
103
123
  return None
104
124
 
105
- ddo = root / Paths.DDOS / did
125
+ ddo = Paths.DDOS / did
106
126
  if not ddo.exists():
107
127
  raise FileNotFoundError(f"DDO file {ddo} does not exist")
108
128
 
109
129
  return Algorithm(did, ddo)
110
130
 
111
- def _secret(self) -> Optional[str]:
131
+ def _secret(
132
+ self,
133
+ ) -> Optional[str]:
112
134
  return self._mapper.get(self._keys.SECRET, None)
@@ -5,9 +5,16 @@ from typing import Generic, TypeVar
5
5
  T = TypeVar("T")
6
6
 
7
7
 
8
- class Loader(ABC, Generic[T]):
8
+ class Loader(
9
+ ABC,
10
+ Generic[T],
11
+ ):
9
12
  @abstractmethod
10
- def load(self, *args, **kwargs) -> T:
13
+ def load(
14
+ self,
15
+ *args,
16
+ **kwargs,
17
+ ) -> T:
11
18
  """Load an instance of the given type"""
12
19
  pass
13
20
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: oceanprotocol-job-details
3
- Version: 0.0.7
3
+ Version: 0.0.9
4
4
  Summary: A Python package to get details from OceanProtocol jobs
5
5
  License: Copyright 2025 Agrospai
6
6
 
@@ -41,6 +41,15 @@ from oceanprotocol_job_details.job_details import OceanProtocolJobDetails
41
41
  job_details = OceanProtocolJobDetails().load()
42
42
  ```
43
43
 
44
+ Assumes the following directory structure:
45
+ ```
46
+ <ROOT_FOLDER>
47
+ └───data
48
+ ├───ddos
49
+ ├───inputs
50
+ └───logs
51
+ ```
52
+
44
53
  ### Advanced Usage (not recommended)
45
54
 
46
55
  If instead of the environment variables, we want to use another kind of mapping, can pass it as a parameter and it will work as long as it has the same key values (Can be implemented in a more generic way, but there is no need right now).
@@ -51,9 +60,9 @@ from oceanprotocol_job_details.loaders.impl.environment import Keys
51
60
 
52
61
  # Fill in with values that will be used instead of env
53
62
  custom_mapper = {
63
+ Keys.ROOT_FOLDER: " ... ", # Use when you don't want the algorithm to take '/' as base Path
54
64
  Keys.ALGORITHM: " ... ",
55
65
  Keys.DIDS: " ... ",
56
- Keys.ROOT: " ... ",
57
66
  Keys.SECRET: " ... ",
58
67
  }
59
68
 
@@ -0,0 +1,13 @@
1
+ oceanprotocol_job_details/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
+ oceanprotocol_job_details/dataclasses/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
+ oceanprotocol_job_details/dataclasses/constants.py,sha256=4bUtp5JA4Sp22CW7L3oLrGG2SmYpAEOCXd59k5rKFyg,850
4
+ oceanprotocol_job_details/dataclasses/job_details.py,sha256=iH52jd6XCplP2Z40qDO0lbFCTm7suVNPyLVgYkeOtQ0,2640
5
+ oceanprotocol_job_details/job_details.py,sha256=E5z_4ZlvSJSi1IJslSTi3X36UI_FHeaZkOyfCxxeJXw,1366
6
+ oceanprotocol_job_details/loaders/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
7
+ oceanprotocol_job_details/loaders/impl/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
8
+ oceanprotocol_job_details/loaders/impl/map.py,sha256=c3GNrLk14Hc3vu8OJFwcUb_23ZVzbkG3iaJ4rVi4sZs,3861
9
+ oceanprotocol_job_details/loaders/loader.py,sha256=ZedS7sA3K3uAIvc-yLRjgHIAen6_XyHO6sXhqm55kYo,298
10
+ oceanprotocol_job_details-0.0.9.dist-info/LICENSE,sha256=ni3ix7P_GxK1W3VGC4fJ3o6QoCngCEpSuTJwO4nkpbw,1055
11
+ oceanprotocol_job_details-0.0.9.dist-info/METADATA,sha256=Zd2nclEtjLf62kw2GTNNqI9Z0FDsQSfESePhoRaIQ0E,3013
12
+ oceanprotocol_job_details-0.0.9.dist-info/WHEEL,sha256=IYZQI976HJqqOpQU6PHkJ8fb3tMNBFjg-Cn-pwAbaFM,88
13
+ oceanprotocol_job_details-0.0.9.dist-info/RECORD,,
@@ -1,13 +0,0 @@
1
- oceanprotocol_job_details/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- oceanprotocol_job_details/dataclasses/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
- oceanprotocol_job_details/dataclasses/constants.py,sha256=0hUnY2ccbvbRmxwgJC3GYaN7yoG6fccLqjxQWkH88Bo,846
4
- oceanprotocol_job_details/dataclasses/job_details.py,sha256=pnbNvCg0jg5rx8K9B8qbHPFetTGaMdXK94qP4PvGilw,2692
5
- oceanprotocol_job_details/job_details.py,sha256=efY8Er97k_R-dRPbxd2gcCyp0l0oyHLL8FxQ8ldB6ms,1265
6
- oceanprotocol_job_details/loaders/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
7
- oceanprotocol_job_details/loaders/impl/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
8
- oceanprotocol_job_details/loaders/impl/map.py,sha256=F6AxfRpPeRVdXtgS6jhZZM13EcGed0SszPPT5NVJmOo,3508
9
- oceanprotocol_job_details/loaders/loader.py,sha256=JwR6OSkzIQQkeeyAU-ad_F89W9WNvoRwvHQY7Q3zIXI,256
10
- oceanprotocol_job_details-0.0.7.dist-info/LICENSE,sha256=ni3ix7P_GxK1W3VGC4fJ3o6QoCngCEpSuTJwO4nkpbw,1055
11
- oceanprotocol_job_details-0.0.7.dist-info/METADATA,sha256=UOhOCZTuyaIK6lxSGF9T2gEL25FL05GvOt_K8SIjRzQ,2793
12
- oceanprotocol_job_details-0.0.7.dist-info/WHEEL,sha256=IYZQI976HJqqOpQU6PHkJ8fb3tMNBFjg-Cn-pwAbaFM,88
13
- oceanprotocol_job_details-0.0.7.dist-info/RECORD,,