oceanprotocol-job-details 0.3.1__tar.gz → 0.3.3__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.
- {oceanprotocol_job_details-0.3.1 → oceanprotocol_job_details-0.3.3}/PKG-INFO +25 -38
- {oceanprotocol_job_details-0.3.1 → oceanprotocol_job_details-0.3.3}/README.md +24 -37
- oceanprotocol_job_details-0.3.3/oceanprotocol_job_details/__init__.py +4 -0
- oceanprotocol_job_details-0.3.3/oceanprotocol_job_details/helpers.py +29 -0
- {oceanprotocol_job_details-0.3.1 → oceanprotocol_job_details-0.3.3}/oceanprotocol_job_details/loaders/impl/files.py +2 -6
- {oceanprotocol_job_details-0.3.1 → oceanprotocol_job_details-0.3.3}/oceanprotocol_job_details/settings.py +9 -3
- {oceanprotocol_job_details-0.3.1 → oceanprotocol_job_details-0.3.3}/pyproject.toml +1 -1
- oceanprotocol_job_details-0.3.1/oceanprotocol_job_details/__init__.py +0 -4
- {oceanprotocol_job_details-0.3.1 → oceanprotocol_job_details-0.3.3}/.gitignore +0 -0
- {oceanprotocol_job_details-0.3.1 → oceanprotocol_job_details-0.3.3}/LICENSE +0 -0
- {oceanprotocol_job_details-0.3.1 → oceanprotocol_job_details-0.3.3}/oceanprotocol_job_details/di.py +0 -0
- {oceanprotocol_job_details-0.3.1 → oceanprotocol_job_details-0.3.3}/oceanprotocol_job_details/domain.py +0 -0
- {oceanprotocol_job_details-0.3.1 → oceanprotocol_job_details-0.3.3}/oceanprotocol_job_details/loaders/__init__.py +0 -0
- {oceanprotocol_job_details-0.3.1 → oceanprotocol_job_details-0.3.3}/oceanprotocol_job_details/loaders/impl/__init__.py +0 -0
- {oceanprotocol_job_details-0.3.1 → oceanprotocol_job_details-0.3.3}/oceanprotocol_job_details/loaders/impl/ddo.py +0 -0
- {oceanprotocol_job_details-0.3.1 → oceanprotocol_job_details-0.3.3}/oceanprotocol_job_details/loaders/impl/job_details.py +0 -0
- {oceanprotocol_job_details-0.3.1 → oceanprotocol_job_details-0.3.3}/oceanprotocol_job_details/loaders/loader.py +0 -0
- {oceanprotocol_job_details-0.3.1 → oceanprotocol_job_details-0.3.3}/oceanprotocol_job_details/ocean.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: oceanprotocol-job-details
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.3
|
|
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
|
|
@@ -30,24 +30,29 @@ A Python package to get details from OceanProtocol jobs
|
|
|
30
30
|
|
|
31
31
|
## Installation
|
|
32
32
|
|
|
33
|
-
```
|
|
33
|
+
```bash
|
|
34
34
|
pip install oceanprotocol-job-details
|
|
35
35
|
```
|
|
36
36
|
|
|
37
|
-
|
|
37
|
+
```bash
|
|
38
|
+
uv add oceanprotocol-job-details
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Usage
|
|
38
42
|
|
|
39
|
-
As a simple library, we only need to import `
|
|
43
|
+
As a simple library, we only need to import `load_job_details` and run it. It will:
|
|
40
44
|
|
|
41
|
-
1. Fetch the needed parameters to populate the `JobDetails` instance from the environment variables or use the passed values to the
|
|
45
|
+
1. Fetch the needed parameters to populate the `JobDetails` instance from the environment variables or use the passed values to the function.
|
|
42
46
|
1. Look for the files corresponding to the passed DIDs in the filesystem according to the [Ocean Protocol Structure](#oceanprotocol-structure) and load them into the `JobDetails` instance.
|
|
43
47
|
|
|
44
|
-
|
|
45
48
|
### Minimal Example
|
|
46
49
|
|
|
47
50
|
```python
|
|
48
|
-
from oceanprotocol_job_details import
|
|
51
|
+
from oceanprotocol_job_details import load_job_details
|
|
49
52
|
|
|
50
|
-
|
|
53
|
+
class InputParameters(BaseModel): ...
|
|
54
|
+
|
|
55
|
+
job_details = load_job_details({}, InputParameters)
|
|
51
56
|
```
|
|
52
57
|
|
|
53
58
|
### Custom Input Parameters
|
|
@@ -55,58 +60,40 @@ job_details = JobDetails.load()
|
|
|
55
60
|
If our algorithm has custom input parameters and we want to load them into our algorithm, we can do it as follows:
|
|
56
61
|
|
|
57
62
|
```python
|
|
58
|
-
from
|
|
59
|
-
from oceanprotocol_job_details import
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
@dataclass
|
|
63
|
-
class InputParameters:
|
|
64
|
-
foobar: str
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
job_details = JobDetails[InputParameters].load(InputParameters)
|
|
68
|
-
|
|
69
|
-
# Usage
|
|
70
|
-
job_details.input_parameters.foobar
|
|
71
|
-
```
|
|
72
|
-
|
|
73
|
-
```python
|
|
74
|
-
from dataclasses import dataclass
|
|
75
|
-
from oceanprotocol_job_details import JobDetails
|
|
63
|
+
from pydantic import BaseModel
|
|
64
|
+
from oceanprotocol_job_details import load_job_details
|
|
76
65
|
|
|
77
66
|
|
|
78
|
-
|
|
79
|
-
class Foo:
|
|
67
|
+
class Foo(BaseModel):
|
|
80
68
|
bar: str
|
|
81
69
|
|
|
82
70
|
|
|
83
|
-
|
|
84
|
-
class InputParameters:
|
|
71
|
+
class InputParameters(BaseModel):
|
|
85
72
|
# Allows for nested types
|
|
86
73
|
foo: Foo
|
|
87
74
|
|
|
88
75
|
|
|
89
|
-
job_details =
|
|
76
|
+
job_details = load_job_details({}, InputParameters)
|
|
90
77
|
|
|
91
78
|
# Usage
|
|
79
|
+
job_details.input_parameters.foo
|
|
92
80
|
job_details.input_parameters.foo.bar
|
|
93
81
|
```
|
|
94
82
|
|
|
95
|
-
The values to fill the custom `InputParameters` will be parsed from the `algoCustomData.json` located next to the input data directories.
|
|
83
|
+
The values to fill the custom `InputParameters` will be parsed from the `algoCustomData.json` located next to the input data directories.
|
|
96
84
|
|
|
97
85
|
### Iterating Input Files the clean way
|
|
98
86
|
|
|
99
87
|
```python
|
|
100
|
-
from oceanprotocol_job_details import
|
|
88
|
+
from oceanprotocol_job_details import load_job_details
|
|
101
89
|
|
|
102
90
|
|
|
103
|
-
job_details =
|
|
91
|
+
job_details = load_job_details
|
|
104
92
|
|
|
105
|
-
for idx, file_path in job_details.
|
|
93
|
+
for idx, file_path in job_details.inputs():
|
|
106
94
|
...
|
|
107
95
|
|
|
108
|
-
|
|
109
|
-
_, file_path = job_details.next_file()
|
|
96
|
+
_, file_path = next(job_details.inputs())
|
|
110
97
|
```
|
|
111
98
|
|
|
112
99
|
## OceanProtocol Structure
|
|
@@ -124,4 +111,4 @@ data # Root /data directory
|
|
|
124
111
|
└── outputs # Algorithm output files dir
|
|
125
112
|
```
|
|
126
113
|
|
|
127
|
-
> **_Note:_** Even though it's possible that the algorithm is passed multiple datasets, right now the implementation only allows to use **one dataset** per algorithm execution, so **normally** the executing job will only have **one ddo**, **one dir** inside inputs, and **one data file** named `0`.
|
|
114
|
+
> **_Note:_** Even though it's possible that the algorithm is passed multiple datasets, right now the implementation only allows to use **one dataset** per algorithm execution, so **normally** the executing job will only have **one ddo**, **one dir** inside inputs, and **one data file** named `0`.
|
|
@@ -4,24 +4,29 @@ A Python package to get details from OceanProtocol jobs
|
|
|
4
4
|
|
|
5
5
|
## Installation
|
|
6
6
|
|
|
7
|
-
```
|
|
7
|
+
```bash
|
|
8
8
|
pip install oceanprotocol-job-details
|
|
9
9
|
```
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
```bash
|
|
12
|
+
uv add oceanprotocol-job-details
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Usage
|
|
12
16
|
|
|
13
|
-
As a simple library, we only need to import `
|
|
17
|
+
As a simple library, we only need to import `load_job_details` and run it. It will:
|
|
14
18
|
|
|
15
|
-
1. Fetch the needed parameters to populate the `JobDetails` instance from the environment variables or use the passed values to the
|
|
19
|
+
1. Fetch the needed parameters to populate the `JobDetails` instance from the environment variables or use the passed values to the function.
|
|
16
20
|
1. Look for the files corresponding to the passed DIDs in the filesystem according to the [Ocean Protocol Structure](#oceanprotocol-structure) and load them into the `JobDetails` instance.
|
|
17
21
|
|
|
18
|
-
|
|
19
22
|
### Minimal Example
|
|
20
23
|
|
|
21
24
|
```python
|
|
22
|
-
from oceanprotocol_job_details import
|
|
25
|
+
from oceanprotocol_job_details import load_job_details
|
|
23
26
|
|
|
24
|
-
|
|
27
|
+
class InputParameters(BaseModel): ...
|
|
28
|
+
|
|
29
|
+
job_details = load_job_details({}, InputParameters)
|
|
25
30
|
```
|
|
26
31
|
|
|
27
32
|
### Custom Input Parameters
|
|
@@ -29,58 +34,40 @@ job_details = JobDetails.load()
|
|
|
29
34
|
If our algorithm has custom input parameters and we want to load them into our algorithm, we can do it as follows:
|
|
30
35
|
|
|
31
36
|
```python
|
|
32
|
-
from
|
|
33
|
-
from oceanprotocol_job_details import
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
@dataclass
|
|
37
|
-
class InputParameters:
|
|
38
|
-
foobar: str
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
job_details = JobDetails[InputParameters].load(InputParameters)
|
|
42
|
-
|
|
43
|
-
# Usage
|
|
44
|
-
job_details.input_parameters.foobar
|
|
45
|
-
```
|
|
46
|
-
|
|
47
|
-
```python
|
|
48
|
-
from dataclasses import dataclass
|
|
49
|
-
from oceanprotocol_job_details import JobDetails
|
|
37
|
+
from pydantic import BaseModel
|
|
38
|
+
from oceanprotocol_job_details import load_job_details
|
|
50
39
|
|
|
51
40
|
|
|
52
|
-
|
|
53
|
-
class Foo:
|
|
41
|
+
class Foo(BaseModel):
|
|
54
42
|
bar: str
|
|
55
43
|
|
|
56
44
|
|
|
57
|
-
|
|
58
|
-
class InputParameters:
|
|
45
|
+
class InputParameters(BaseModel):
|
|
59
46
|
# Allows for nested types
|
|
60
47
|
foo: Foo
|
|
61
48
|
|
|
62
49
|
|
|
63
|
-
job_details =
|
|
50
|
+
job_details = load_job_details({}, InputParameters)
|
|
64
51
|
|
|
65
52
|
# Usage
|
|
53
|
+
job_details.input_parameters.foo
|
|
66
54
|
job_details.input_parameters.foo.bar
|
|
67
55
|
```
|
|
68
56
|
|
|
69
|
-
The values to fill the custom `InputParameters` will be parsed from the `algoCustomData.json` located next to the input data directories.
|
|
57
|
+
The values to fill the custom `InputParameters` will be parsed from the `algoCustomData.json` located next to the input data directories.
|
|
70
58
|
|
|
71
59
|
### Iterating Input Files the clean way
|
|
72
60
|
|
|
73
61
|
```python
|
|
74
|
-
from oceanprotocol_job_details import
|
|
62
|
+
from oceanprotocol_job_details import load_job_details
|
|
75
63
|
|
|
76
64
|
|
|
77
|
-
job_details =
|
|
65
|
+
job_details = load_job_details
|
|
78
66
|
|
|
79
|
-
for idx, file_path in job_details.
|
|
67
|
+
for idx, file_path in job_details.inputs():
|
|
80
68
|
...
|
|
81
69
|
|
|
82
|
-
|
|
83
|
-
_, file_path = job_details.next_file()
|
|
70
|
+
_, file_path = next(job_details.inputs())
|
|
84
71
|
```
|
|
85
72
|
|
|
86
73
|
## OceanProtocol Structure
|
|
@@ -98,4 +85,4 @@ data # Root /data directory
|
|
|
98
85
|
└── outputs # Algorithm output files dir
|
|
99
86
|
```
|
|
100
87
|
|
|
101
|
-
> **_Note:_** Even though it's possible that the algorithm is passed multiple datasets, right now the implementation only allows to use **one dataset** per algorithm execution, so **normally** the executing job will only have **one ddo**, **one dir** inside inputs, and **one data file** named `0`.
|
|
88
|
+
> **_Note:_** Even though it's possible that the algorithm is passed multiple datasets, right now the implementation only allows to use **one dataset** per algorithm execution, so **normally** the executing job will only have **one ddo**, **one dir** inside inputs, and **one data file** named `0`.
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
from typing import Any, Dict, Type, TypeVar
|
|
2
|
+
|
|
3
|
+
from pydantic import BaseModel, JsonValue
|
|
4
|
+
|
|
5
|
+
from oceanprotocol_job_details.di import Container
|
|
6
|
+
from oceanprotocol_job_details.ocean import JobDetails
|
|
7
|
+
from oceanprotocol_job_details.settings import JobSettings
|
|
8
|
+
|
|
9
|
+
InputParametersT = TypeVar("InputParametersT", bound=BaseModel)
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def create_container(config: Dict[str, Any]) -> Container[InputParametersT]: # type: ignore[explicit-any]
|
|
13
|
+
"""Return a fully configured Container from a config dict."""
|
|
14
|
+
container = Container[InputParametersT]()
|
|
15
|
+
settings = JobSettings(**config)
|
|
16
|
+
container.config.from_pydantic(settings)
|
|
17
|
+
return container
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def load_job_details(
|
|
21
|
+
config: Dict[str, JsonValue],
|
|
22
|
+
input_type: Type[InputParametersT],
|
|
23
|
+
) -> JobDetails[InputParametersT]:
|
|
24
|
+
"""
|
|
25
|
+
Load JobDetails for a given input_type using the config.
|
|
26
|
+
Returns a fully initialized JobDetails instance.
|
|
27
|
+
"""
|
|
28
|
+
container: Container[InputParametersT] = create_container(config)
|
|
29
|
+
return container.job_details_loader(input_type=input_type).load()
|
|
@@ -20,14 +20,10 @@ class FilesLoader:
|
|
|
20
20
|
dids: list[str]
|
|
21
21
|
"""Input DIDs"""
|
|
22
22
|
|
|
23
|
-
transformation_did:
|
|
23
|
+
transformation_did: str
|
|
24
24
|
"""DID for the transformation algorithm"""
|
|
25
25
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
def __post_init__(self, transformation_did: str | None) -> None:
|
|
29
|
-
object.__setattr__(self, "_transformation_did", transformation_did)
|
|
30
|
-
|
|
26
|
+
def __post_init__(self) -> None:
|
|
31
27
|
assert self.dids, "Missing input DIDs"
|
|
32
28
|
|
|
33
29
|
def calculate_path(self, did: str, path_type: Literal["input", "ddo"]) -> Path:
|
|
@@ -1,22 +1,22 @@
|
|
|
1
1
|
# mypy: disable-error-code=call-overload
|
|
2
2
|
from logging import Logger, getLogger
|
|
3
3
|
from pathlib import Path
|
|
4
|
+
from typing import Self
|
|
4
5
|
|
|
5
6
|
import orjson
|
|
6
|
-
from pydantic import Field, field_validator
|
|
7
|
+
from pydantic import Field, field_validator, model_validator
|
|
7
8
|
from pydantic_settings import BaseSettings, SettingsConfigDict
|
|
8
9
|
|
|
9
10
|
|
|
10
11
|
class JobSettings(BaseSettings): # type: ignore[explicit-any]
|
|
11
12
|
base_dir: Path = Field(alias="BASE_DIR")
|
|
12
|
-
dids: list[str] = Field(alias="DIDS")
|
|
13
|
+
dids: list[str] = Field(default_factory=list, alias="DIDS")
|
|
13
14
|
transformation_did: str = Field(alias="TRANSFORMATION_DID")
|
|
14
15
|
secret: str | None = Field(default=None, alias="SECRET")
|
|
15
16
|
logger: Logger = Field(default_factory=lambda: getLogger(__name__))
|
|
16
17
|
|
|
17
18
|
model_config = SettingsConfigDict(
|
|
18
19
|
extra="forbid",
|
|
19
|
-
validate_default=True,
|
|
20
20
|
populate_by_name=True,
|
|
21
21
|
arbitrary_types_allowed=True,
|
|
22
22
|
)
|
|
@@ -29,3 +29,9 @@ class JobSettings(BaseSettings): # type: ignore[explicit-any]
|
|
|
29
29
|
assert isinstance(data, list)
|
|
30
30
|
return data
|
|
31
31
|
return v
|
|
32
|
+
|
|
33
|
+
@model_validator(mode="after")
|
|
34
|
+
def validate_dids(self) -> Self:
|
|
35
|
+
if not self.dids:
|
|
36
|
+
self.dids.extend([f.name for f in (self.base_dir / "ddos").glob("*")])
|
|
37
|
+
return self
|
|
File without changes
|
|
File without changes
|
{oceanprotocol_job_details-0.3.1 → oceanprotocol_job_details-0.3.3}/oceanprotocol_job_details/di.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|