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.
Files changed (18) hide show
  1. {oceanprotocol_job_details-0.3.1 → oceanprotocol_job_details-0.3.3}/PKG-INFO +25 -38
  2. {oceanprotocol_job_details-0.3.1 → oceanprotocol_job_details-0.3.3}/README.md +24 -37
  3. oceanprotocol_job_details-0.3.3/oceanprotocol_job_details/__init__.py +4 -0
  4. oceanprotocol_job_details-0.3.3/oceanprotocol_job_details/helpers.py +29 -0
  5. {oceanprotocol_job_details-0.3.1 → oceanprotocol_job_details-0.3.3}/oceanprotocol_job_details/loaders/impl/files.py +2 -6
  6. {oceanprotocol_job_details-0.3.1 → oceanprotocol_job_details-0.3.3}/oceanprotocol_job_details/settings.py +9 -3
  7. {oceanprotocol_job_details-0.3.1 → oceanprotocol_job_details-0.3.3}/pyproject.toml +1 -1
  8. oceanprotocol_job_details-0.3.1/oceanprotocol_job_details/__init__.py +0 -4
  9. {oceanprotocol_job_details-0.3.1 → oceanprotocol_job_details-0.3.3}/.gitignore +0 -0
  10. {oceanprotocol_job_details-0.3.1 → oceanprotocol_job_details-0.3.3}/LICENSE +0 -0
  11. {oceanprotocol_job_details-0.3.1 → oceanprotocol_job_details-0.3.3}/oceanprotocol_job_details/di.py +0 -0
  12. {oceanprotocol_job_details-0.3.1 → oceanprotocol_job_details-0.3.3}/oceanprotocol_job_details/domain.py +0 -0
  13. {oceanprotocol_job_details-0.3.1 → oceanprotocol_job_details-0.3.3}/oceanprotocol_job_details/loaders/__init__.py +0 -0
  14. {oceanprotocol_job_details-0.3.1 → oceanprotocol_job_details-0.3.3}/oceanprotocol_job_details/loaders/impl/__init__.py +0 -0
  15. {oceanprotocol_job_details-0.3.1 → oceanprotocol_job_details-0.3.3}/oceanprotocol_job_details/loaders/impl/ddo.py +0 -0
  16. {oceanprotocol_job_details-0.3.1 → oceanprotocol_job_details-0.3.3}/oceanprotocol_job_details/loaders/impl/job_details.py +0 -0
  17. {oceanprotocol_job_details-0.3.1 → oceanprotocol_job_details-0.3.3}/oceanprotocol_job_details/loaders/loader.py +0 -0
  18. {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.1
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
- ## Usage
37
+ ```bash
38
+ uv add oceanprotocol-job-details
39
+ ```
40
+
41
+ ## Usage
38
42
 
39
- As a simple library, we only need to import `JobDetails` and load it, it will:
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 `load()` method.
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 JobDetails
51
+ from oceanprotocol_job_details import load_job_details
49
52
 
50
- job_details = JobDetails.load()
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 dataclasses import dataclass
59
- from oceanprotocol_job_details import JobDetails
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
- @dataclass
79
- class Foo:
67
+ class Foo(BaseModel):
80
68
  bar: str
81
69
 
82
70
 
83
- @dataclass
84
- class InputParameters:
71
+ class InputParameters(BaseModel):
85
72
  # Allows for nested types
86
73
  foo: Foo
87
74
 
88
75
 
89
- job_details = JobDetails[InputParameters].load(InputParameters)
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 JobDetails
88
+ from oceanprotocol_job_details import load_job_details
101
89
 
102
90
 
103
- job_details = JobDetails.load()
91
+ job_details = load_job_details
104
92
 
105
- for idx, file_path in job_details.next_file():
93
+ for idx, file_path in job_details.inputs():
106
94
  ...
107
95
 
108
- # Or if you just want one file path
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
- ## Usage
11
+ ```bash
12
+ uv add oceanprotocol-job-details
13
+ ```
14
+
15
+ ## Usage
12
16
 
13
- As a simple library, we only need to import `JobDetails` and load it, it will:
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 `load()` method.
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 JobDetails
25
+ from oceanprotocol_job_details import load_job_details
23
26
 
24
- job_details = JobDetails.load()
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 dataclasses import dataclass
33
- from oceanprotocol_job_details import JobDetails
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
- @dataclass
53
- class Foo:
41
+ class Foo(BaseModel):
54
42
  bar: str
55
43
 
56
44
 
57
- @dataclass
58
- class InputParameters:
45
+ class InputParameters(BaseModel):
59
46
  # Allows for nested types
60
47
  foo: Foo
61
48
 
62
49
 
63
- job_details = JobDetails[InputParameters].load(InputParameters)
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 JobDetails
62
+ from oceanprotocol_job_details import load_job_details
75
63
 
76
64
 
77
- job_details = JobDetails.load()
65
+ job_details = load_job_details
78
66
 
79
- for idx, file_path in job_details.next_file():
67
+ for idx, file_path in job_details.inputs():
80
68
  ...
81
69
 
82
- # Or if you just want one file path
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,4 @@
1
+ from .helpers import create_container, load_job_details
2
+ from .ocean import JobDetails
3
+
4
+ __all__ = [JobDetails, load_job_details, create_container] # type: ignore
@@ -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: InitVar[str | None] = None
23
+ transformation_did: str
24
24
  """DID for the transformation algorithm"""
25
25
 
26
- _transformation_did: str = field(init=False)
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
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "oceanprotocol-job-details"
3
- version = "0.3.1"
3
+ version = "0.3.3"
4
4
  description = "A Python package to get details from OceanProtocol jobs"
5
5
  authors = [
6
6
  { name = "Agrospai", email = "agrospai@udl.cat" },
@@ -1,4 +0,0 @@
1
- from .ocean import JobDetails
2
-
3
-
4
- __all__ = [JobDetails] # type: ignore