|
8 | 8 | # nor does it submit to any jurisdiction. |
9 | 9 |
|
10 | 10 |
|
| 11 | +import logging |
| 12 | +from pathlib import Path |
11 | 13 | from typing import Any |
12 | 14 | from typing import TypeVar |
13 | 15 |
|
14 | 16 | from anemoi.inference.context import Context |
15 | 17 |
|
| 18 | +LOG = logging.getLogger("anemoi.inference") |
| 19 | + |
16 | 20 | MARKER = object() |
17 | 21 | F = TypeVar("F", bound=type) |
18 | 22 |
|
@@ -64,3 +68,67 @@ def __init__(wrapped_cls, context: Context, main: object = MARKER, *args: Any, * |
64 | 68 | super().__init__(context, *args, **kwargs) |
65 | 69 |
|
66 | 70 | return type(cls.__name__, (WrappedClass,), {}) |
| 71 | + |
| 72 | + |
| 73 | +class ensure_path: |
| 74 | + """Decorator to ensure a path argument is a Path object and optionally exists. |
| 75 | +
|
| 76 | + If `is_dir` is True, the path is treated as a directory, if not for files, the parent directory is treated as a directory. |
| 77 | + If `must_exist` is True, the directory must exist. |
| 78 | + If `create` is True, the directory will be created if it doesn't exist. |
| 79 | +
|
| 80 | + For example: |
| 81 | + ``` |
| 82 | + @ensure_path("dir", create=True) |
| 83 | + class GribOutput |
| 84 | + def __init__(context, dir=None, archive_requests=None): |
| 85 | + ... |
| 86 | + """ |
| 87 | + |
| 88 | + def __init__(self, arg: str, is_dir: bool = False, create: bool = True, must_exist: bool = False): |
| 89 | + self.arg = arg |
| 90 | + self.is_dir = is_dir |
| 91 | + self.create = create |
| 92 | + self.must_exist = must_exist |
| 93 | + |
| 94 | + def __call__(self, cls: F) -> F: |
| 95 | + """Decorate the object to ensure the path argument is a Path object.""" |
| 96 | + |
| 97 | + class WrappedClass(cls): |
| 98 | + def __init__(wrapped_cls, context: Context, *args: Any, **kwargs: Any) -> None: |
| 99 | + if self.arg not in kwargs: |
| 100 | + LOG.debug(f"Argument '{self.arg}' not found in kwargs, cannot ensure path.") |
| 101 | + super().__init__(context, *args, **kwargs) |
| 102 | + return |
| 103 | + |
| 104 | + path = kwargs[self.arg] = Path(kwargs[self.arg]) |
| 105 | + if not self.is_dir: |
| 106 | + path = path.parent |
| 107 | + |
| 108 | + if self.must_exist: |
| 109 | + if not path.exists(): |
| 110 | + raise FileNotFoundError(f"Path '{path}' does not exist.") |
| 111 | + if self.create: |
| 112 | + path.mkdir(parents=True, exist_ok=True) |
| 113 | + |
| 114 | + super().__init__(context, *args, **kwargs) |
| 115 | + |
| 116 | + return type(cls.__name__, (WrappedClass,), {}) |
| 117 | + |
| 118 | + |
| 119 | +class ensure_dir(ensure_path): |
| 120 | + """Decorator to ensure a directory path argument is a Path object and optionally exists. |
| 121 | +
|
| 122 | + If `must_exist` is True, the directory must exist. |
| 123 | + If `create` is True, the directory will be created if it doesn't exist. |
| 124 | +
|
| 125 | + For example: |
| 126 | + ``` |
| 127 | + @ensure_dir("dir", create=True) |
| 128 | + class PlotOutput |
| 129 | + def __init__(context, dir=None, ...): |
| 130 | + ... |
| 131 | + """ |
| 132 | + |
| 133 | + def __init__(self, arg: str, create: bool = True, must_exist: bool = False): |
| 134 | + super().__init__(arg, is_dir=True, create=create, must_exist=must_exist) |
0 commit comments