From e92a577e59dce1a02817f69aa2a5df8e6e63a5c7 Mon Sep 17 00:00:00 2001 From: Leonardo Schwarz Date: Wed, 9 Oct 2024 11:01:46 +0200 Subject: [PATCH] app_interface cli "inputs list" does not fail anymore if resources have no "name" field value --- docs/changelog.md | 3 ++- .../experimental/app_interface/cli/inputs.py | 3 ++- .../app_interface/input_preparation/_spec.py | 18 +++++++++++++++++- .../app_interface/input_preparation/prepare.py | 8 +++++--- 4 files changed, 26 insertions(+), 6 deletions(-) diff --git a/docs/changelog.md b/docs/changelog.md index 4e7622c7..9484268a 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -12,12 +12,13 @@ Versioning currently follows `X.Y.Z` where ### Added -- (experimental) EntityLookupCache that allows to cache entity lookups in a script to avoid redundant requests. - Relationship: `ExternalJob.executable` +- (experimental) EntityLookupCache that allows to cache entity lookups in a script to avoid redundant requests. ### Fixed - `Entity.find_all` returns no values when an empty list is passed as an argument. +- (experimental) app_interface cli "inputs list" does not fail anymore if resources have no "name" field value. ## \[1.13.8\] - 2024-10-03 diff --git a/src/bfabric/experimental/app_interface/cli/inputs.py b/src/bfabric/experimental/app_interface/cli/inputs.py index 83c37851..7ffafeac 100644 --- a/src/bfabric/experimental/app_interface/cli/inputs.py +++ b/src/bfabric/experimental/app_interface/cli/inputs.py @@ -65,4 +65,5 @@ def list( ) -> None: """Lists the input files for an app.""" setup_script_logging() - print_input_files_list(inputs_yaml=inputs_yaml, target_folder=target_folder) + client = Bfabric.from_config() + print_input_files_list(inputs_yaml=inputs_yaml, target_folder=target_folder, client=client) diff --git a/src/bfabric/experimental/app_interface/input_preparation/_spec.py b/src/bfabric/experimental/app_interface/input_preparation/_spec.py index 0a546648..df6b75df 100644 --- a/src/bfabric/experimental/app_interface/input_preparation/_spec.py +++ b/src/bfabric/experimental/app_interface/input_preparation/_spec.py @@ -1,14 +1,19 @@ from __future__ import annotations from pathlib import Path -from typing import Annotated, Literal, Union +from typing import Annotated, Literal, Union, TYPE_CHECKING import yaml from pydantic import BaseModel, ConfigDict, Field, Discriminator +from bfabric.entities import Resource + # ":" are not allowed, as well as absolute paths (starting with "/") RelativeFilePath = Annotated[str, Field(pattern=r"^[^/][^:]*$")] +if TYPE_CHECKING: + from bfabric.bfabric import Bfabric + class ResourceSpec(BaseModel): model_config = ConfigDict(extra="forbid") @@ -18,6 +23,13 @@ class ResourceSpec(BaseModel): filename: RelativeFilePath | None = None check_checksum: bool = True + def resolve_filename(self, client: Bfabric) -> str: + if self.filename: + return self.filename + else: + resource = Resource.find(id=self.id, client=client) + return resource["name"] + class DatasetSpec(BaseModel): model_config = ConfigDict(extra="forbid") @@ -26,9 +38,13 @@ class DatasetSpec(BaseModel): id: int filename: RelativeFilePath separator: Literal[",", "\t"] = "," + # has_header: bool # invalid_characters: str = "" + def resolve_filename(self, client: Bfabric) -> str: + return self.filename + InputSpecType = Annotated[Union[ResourceSpec, DatasetSpec], Discriminator("type")] diff --git a/src/bfabric/experimental/app_interface/input_preparation/prepare.py b/src/bfabric/experimental/app_interface/input_preparation/prepare.py index 8876e9b0..17cff05d 100644 --- a/src/bfabric/experimental/app_interface/input_preparation/prepare.py +++ b/src/bfabric/experimental/app_interface/input_preparation/prepare.py @@ -83,8 +83,8 @@ def prepare_dataset(self, spec: DatasetSpec) -> None: target_path.write_text(tmp_file.read().decode()) def clean_resource(self, spec: ResourceSpec) -> None: - name = spec.filename if spec.filename else Resource.find(id=spec.id, client=self._client)["name"] - path = self._working_dir / name + filename = spec.resolve_filename(client=self._client) + path = self._working_dir / filename if path.exists(): logger.info(f"Removing {path}") path.unlink() @@ -124,6 +124,7 @@ def prepare_folder( def print_input_files_list( inputs_yaml: Path, target_folder: Path, + client: Bfabric, ) -> None: """Prints a list of inputs and whether they exist locally.""" specs_list = InputsSpec.read_yaml(inputs_yaml) @@ -133,7 +134,8 @@ def print_input_files_list( Column("Exists Locally"), ) for spec in specs_list: - path = target_folder / spec.filename if target_folder else Path(spec.filename) + filename = spec.resolve_filename(client=client) + path = target_folder / filename if target_folder else Path(filename) table.add_row( str(path), "Resource" if isinstance(spec, ResourceSpec) else "Dataset",