oceanprotocol-job-details 0.3.2__tar.gz → 0.3.9__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.2 → oceanprotocol_job_details-0.3.9}/PKG-INFO +6 -8
  2. {oceanprotocol_job_details-0.3.2 → oceanprotocol_job_details-0.3.9}/README.md +5 -7
  3. {oceanprotocol_job_details-0.3.2 → oceanprotocol_job_details-0.3.9}/oceanprotocol_job_details/di.py +2 -1
  4. {oceanprotocol_job_details-0.3.2 → oceanprotocol_job_details-0.3.9}/oceanprotocol_job_details/helpers.py +3 -3
  5. {oceanprotocol_job_details-0.3.2 → oceanprotocol_job_details-0.3.9}/oceanprotocol_job_details/loaders/impl/files.py +2 -6
  6. {oceanprotocol_job_details-0.3.2 → oceanprotocol_job_details-0.3.9}/oceanprotocol_job_details/loaders/impl/job_details.py +2 -1
  7. {oceanprotocol_job_details-0.3.2 → oceanprotocol_job_details-0.3.9}/oceanprotocol_job_details/ocean.py +11 -14
  8. oceanprotocol_job_details-0.3.9/oceanprotocol_job_details/py.typed +0 -0
  9. {oceanprotocol_job_details-0.3.2 → oceanprotocol_job_details-0.3.9}/oceanprotocol_job_details/settings.py +15 -4
  10. {oceanprotocol_job_details-0.3.2 → oceanprotocol_job_details-0.3.9}/pyproject.toml +5 -2
  11. {oceanprotocol_job_details-0.3.2 → oceanprotocol_job_details-0.3.9}/.gitignore +0 -0
  12. {oceanprotocol_job_details-0.3.2 → oceanprotocol_job_details-0.3.9}/LICENSE +0 -0
  13. {oceanprotocol_job_details-0.3.2 → oceanprotocol_job_details-0.3.9}/oceanprotocol_job_details/__init__.py +0 -0
  14. {oceanprotocol_job_details-0.3.2 → oceanprotocol_job_details-0.3.9}/oceanprotocol_job_details/domain.py +0 -0
  15. {oceanprotocol_job_details-0.3.2 → oceanprotocol_job_details-0.3.9}/oceanprotocol_job_details/loaders/__init__.py +0 -0
  16. {oceanprotocol_job_details-0.3.2 → oceanprotocol_job_details-0.3.9}/oceanprotocol_job_details/loaders/impl/__init__.py +0 -0
  17. {oceanprotocol_job_details-0.3.2 → oceanprotocol_job_details-0.3.9}/oceanprotocol_job_details/loaders/impl/ddo.py +0 -0
  18. {oceanprotocol_job_details-0.3.2 → oceanprotocol_job_details-0.3.9}/oceanprotocol_job_details/loaders/loader.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: oceanprotocol-job-details
3
- Version: 0.3.2
3
+ Version: 0.3.9
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
@@ -42,17 +42,15 @@ uv add oceanprotocol-job-details
42
42
 
43
43
  As a simple library, we only need to import `load_job_details` and run it. It will:
44
44
 
45
- 1. Fetch the needed parameters to populate the `JobDetails` instance from the environment variables or use the passed values to the function.
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.
45
+ 1. Read from disk the needed parameters to populate the `JobDetails` from the given `base_dir`. Looking for the files corresponding to the passed DIDs in the filesystem according to the [Ocean Protocol Structure](#oceanprotocol-structure).
46
+ 2. If given a `InputParameters` type that inherits from `pydantic.BaseModel`, it will create an instance from the environment variables.
47
47
 
48
48
  ### Minimal Example
49
49
 
50
50
  ```python
51
51
  from oceanprotocol_job_details import load_job_details
52
52
 
53
- class InputParameters(BaseModel): ...
54
-
55
- job_details = load_job_details({}, InputParameters)
53
+ job_details = load_job_details({"base_dir": "...", "transformation_did": "..."})
56
54
  ```
57
55
 
58
56
  ### Custom Input Parameters
@@ -73,7 +71,7 @@ class InputParameters(BaseModel):
73
71
  foo: Foo
74
72
 
75
73
 
76
- job_details = load_job_details({}, InputParameters)
74
+ job_details = load_job_details({"base_dir": "...", "transformation_did": "..."}, InputParameters)
77
75
 
78
76
  # Usage
79
77
  job_details.input_parameters.foo
@@ -88,7 +86,7 @@ The values to fill the custom `InputParameters` will be parsed from the `algoCus
88
86
  from oceanprotocol_job_details import load_job_details
89
87
 
90
88
 
91
- job_details = load_job_details
89
+ job_details = load_job_details(...)
92
90
 
93
91
  for idx, file_path in job_details.inputs():
94
92
  ...
@@ -16,17 +16,15 @@ uv add oceanprotocol-job-details
16
16
 
17
17
  As a simple library, we only need to import `load_job_details` and run it. It will:
18
18
 
19
- 1. Fetch the needed parameters to populate the `JobDetails` instance from the environment variables or use the passed values to the function.
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.
19
+ 1. Read from disk the needed parameters to populate the `JobDetails` from the given `base_dir`. Looking for the files corresponding to the passed DIDs in the filesystem according to the [Ocean Protocol Structure](#oceanprotocol-structure).
20
+ 2. If given a `InputParameters` type that inherits from `pydantic.BaseModel`, it will create an instance from the environment variables.
21
21
 
22
22
  ### Minimal Example
23
23
 
24
24
  ```python
25
25
  from oceanprotocol_job_details import load_job_details
26
26
 
27
- class InputParameters(BaseModel): ...
28
-
29
- job_details = load_job_details({}, InputParameters)
27
+ job_details = load_job_details({"base_dir": "...", "transformation_did": "..."})
30
28
  ```
31
29
 
32
30
  ### Custom Input Parameters
@@ -47,7 +45,7 @@ class InputParameters(BaseModel):
47
45
  foo: Foo
48
46
 
49
47
 
50
- job_details = load_job_details({}, InputParameters)
48
+ job_details = load_job_details({"base_dir": "...", "transformation_did": "..."}, InputParameters)
51
49
 
52
50
  # Usage
53
51
  job_details.input_parameters.foo
@@ -62,7 +60,7 @@ The values to fill the custom `InputParameters` will be parsed from the `algoCus
62
60
  from oceanprotocol_job_details import load_job_details
63
61
 
64
62
 
65
- job_details = load_job_details
63
+ job_details = load_job_details(...)
66
64
 
67
65
  for idx, file_path in job_details.inputs():
68
66
  ...
@@ -1,3 +1,4 @@
1
+ from types import NoneType
1
2
  from typing import Generic, TypeVar
2
3
  from dependency_injector import containers, providers
3
4
  from pydantic import BaseModel
@@ -8,7 +9,7 @@ from oceanprotocol_job_details.loaders.impl.job_details import JobDetailsLoader
8
9
  from oceanprotocol_job_details.domain import Paths
9
10
 
10
11
 
11
- InputParametersT = TypeVar("InputParametersT", bound=BaseModel)
12
+ InputParametersT = TypeVar("InputParametersT", BaseModel, None)
12
13
 
13
14
 
14
15
  class Container(containers.DeclarativeContainer, Generic[InputParametersT]):
@@ -6,7 +6,7 @@ from oceanprotocol_job_details.di import Container
6
6
  from oceanprotocol_job_details.ocean import JobDetails
7
7
  from oceanprotocol_job_details.settings import JobSettings
8
8
 
9
- InputParametersT = TypeVar("InputParametersT", bound=BaseModel)
9
+ InputParametersT = TypeVar("InputParametersT", BaseModel, None)
10
10
 
11
11
 
12
12
  def create_container(config: Dict[str, Any]) -> Container[InputParametersT]: # type: ignore[explicit-any]
@@ -18,8 +18,8 @@ def create_container(config: Dict[str, Any]) -> Container[InputParametersT]: #
18
18
 
19
19
 
20
20
  def load_job_details(
21
- config: Dict[str, JsonValue],
22
- input_type: Type[InputParametersT],
21
+ config: Dict[str, JsonValue] = {},
22
+ input_type: Type[InputParametersT] | None = None,
23
23
  ) -> JobDetails[InputParametersT]:
24
24
  """
25
25
  Load JobDetails for a given input_type using the config.
@@ -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,4 +1,5 @@
1
1
  from dataclasses import dataclass, field
2
+ from types import NoneType
2
3
  from typing import Generic, Type, TypeVar, final
3
4
 
4
5
  from pydantic import BaseModel
@@ -6,7 +7,7 @@ from pydantic import BaseModel
6
7
  from oceanprotocol_job_details.domain import DDO, Files, Paths
7
8
  from oceanprotocol_job_details.ocean import JobDetails
8
9
 
9
- T = TypeVar("T", bound=BaseModel)
10
+ T = TypeVar("T", BaseModel, None)
10
11
 
11
12
 
12
13
  @final
@@ -3,33 +3,27 @@ from __future__ import annotations
3
3
  import asyncio
4
4
  from functools import cached_property
5
5
  from pathlib import Path
6
+ from types import NoneType
6
7
  from typing import Generator, Generic, Tuple, Type, TypeVar, final
7
8
 
8
9
  import aiofiles
9
- from pydantic import BaseModel, ConfigDict, Secret, model_validator
10
+ from pydantic import BaseModel, ConfigDict, Secret
10
11
 
11
12
  from oceanprotocol_job_details.domain import DDO, Files, Paths
12
13
 
13
- InputParemetersT = TypeVar("InputParemetersT", bound=BaseModel)
14
+ InputParametersT = TypeVar("InputParametersT", BaseModel, None)
14
15
 
15
16
 
16
17
  @final
17
- class JobDetails(BaseModel, Generic[InputParemetersT]): # type: ignore[explicit-any]
18
+ class JobDetails(BaseModel, Generic[InputParametersT]): # type: ignore[explicit-any]
18
19
  files: Files
19
20
  ddos: list[DDO]
20
21
  paths: Paths
21
- input_type: Type[InputParemetersT]
22
+ input_type: Type[InputParametersT] | None
22
23
  secret: Secret[str] | None = None
23
24
 
24
25
  model_config = ConfigDict(arbitrary_types_allowed=True, frozen=True)
25
26
 
26
- @model_validator(mode="after")
27
- def validate_type(self) -> JobDetails[InputParemetersT]:
28
- assert issubclass(self.input_type, BaseModel), (
29
- f"{self.input_type} must be subtype of pydantic.BaseModel"
30
- )
31
- return self
32
-
33
27
  def inputs(self) -> Generator[Tuple[int, Path], None, None]:
34
28
  yield from (
35
29
  (idx, file)
@@ -38,14 +32,17 @@ class JobDetails(BaseModel, Generic[InputParemetersT]): # type: ignore[explicit
38
32
  )
39
33
 
40
34
  @cached_property
41
- def input_parameters(self) -> InputParemetersT:
35
+ def input_parameters(self) -> InputParametersT | None:
42
36
  return asyncio.run(self.ainput_parameters())
43
37
 
44
- async def ainput_parameters(self) -> InputParemetersT:
38
+ async def ainput_parameters(self) -> InputParametersT | None:
39
+ if self.input_type is None:
40
+ return None
41
+
45
42
  path = self.paths.algorithm_custom_parameters
46
43
  async with aiofiles.open(path) as f:
47
44
  raw = await f.read()
48
45
 
49
46
  raw = raw.strip()
50
47
  assert raw is not None, f"Empty file {path}"
51
- return self.input_type.model_validate_json(raw)
48
+ return self.input_type.model_validate_json(raw) # type: ignore
@@ -1,31 +1,42 @@
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
  )
23
23
 
24
24
  @field_validator("dids", mode="before")
25
25
  @classmethod
26
- def split_dids(cls, v: list[str] | str) -> list[str]:
26
+ def split_dids(cls, v: list[str] | str | None) -> list[str]:
27
+ if v is None:
28
+ return []
29
+
27
30
  if isinstance(v, str):
28
31
  data = orjson.loads(v)
29
32
  assert isinstance(data, list)
30
33
  return data
31
34
  return v
35
+
36
+ @model_validator(mode="after")
37
+ def validate_dids(self) -> Self:
38
+ if not self.dids:
39
+ self.dids.extend(
40
+ [f.name for f in (self.base_dir / "ddos").glob("*") if f.is_file()]
41
+ )
42
+ return self
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "oceanprotocol-job-details"
3
- version = "0.3.2"
3
+ version = "0.3.9"
4
4
  description = "A Python package to get details from OceanProtocol jobs"
5
5
  authors = [
6
6
  { name = "Agrospai", email = "agrospai@udl.cat" },
@@ -39,7 +39,10 @@ build-backend = "hatchling.build"
39
39
  include = ["oceanprotocol_job_details"]
40
40
 
41
41
  [tool.hatch.build.targets.wheel]
42
- include = ["oceanprotocol_job_details"]
42
+ packages = ["oceanprotocol_job_details"]
43
+
44
+ [tool.hatch.build.targets.wheel.package-data]
45
+ oceanprotocol_job_details = ["py.typed"]
43
46
 
44
47
  [tool.mypy]
45
48
  plugins = ["pydantic.mypy"]