|
12 | 12 | logger = logging.getLogger(__name__) |
13 | 13 | logger.setLevel(logging.INFO) |
14 | 14 |
|
| 15 | +# Date range validation constants |
| 16 | +NEAREST_OPTIONS = ("nd", "np") |
| 17 | +DATE_RANGE_OPTIONS = ("p", "h", "d", "l", *NEAREST_OPTIONS) |
| 18 | + |
15 | 19 |
|
16 | 20 | class DependencyConfigReader: |
17 | 21 | """Dependency configuration reader. |
@@ -153,12 +157,15 @@ def validate_node(self, node: list) -> bool: |
153 | 157 | - h - hourly |
154 | 158 | - d - days |
155 | 159 | - l - last_processed |
156 | | - - n - nearest |
| 160 | + - nd - nearest day |
| 161 | + - np - nearest pointing |
| 162 | +
|
157 | 163 | past and future should end with one of these options. Eg. |
158 | 164 | ("-3p", "3pm") means 3 pointing |
159 | 165 | ("-3d", "5d") means 5 days |
160 | 166 | ("-2h", "2h") means 2 hours |
161 | 167 | ("1l",) means last processed |
| 168 | + ("6np",) means nearest 6 pointing |
162 | 169 |
|
163 | 170 | Validation is performed for each field. |
164 | 171 |
|
@@ -234,32 +241,55 @@ def _validate_date_range(self, date_range) -> None: |
234 | 241 | if not date_range: |
235 | 242 | return |
236 | 243 |
|
237 | | - if not isinstance(date_range, (list)) or len(date_range) != 2: |
| 244 | + if not isinstance(date_range, (list)) or 2 <= len(date_range) < 1: |
238 | 245 | raise ValueError( |
239 | | - "Date range must be a list of 2 elements (past, future), " |
| 246 | + "Date range must be a list of 1-2 elements (past) or (past, future), " |
240 | 247 | f"got {date_range}" |
241 | 248 | ) |
242 | 249 |
|
243 | | - past, future = date_range |
244 | | - date_range_options = ["p", "h", "d", "l", "n"] |
245 | | - past_option = past[-1] if past else None |
246 | | - future_option = future[-1] if future else None |
247 | | - past_int = int(past[:-1]) if past else None |
248 | | - future_int = int(future[:-1]) if future else None |
| 250 | + # Handle both single-element and two-element lists |
| 251 | + past = date_range[0] if len(date_range) > 0 else None |
| 252 | + future = date_range[1] if len(date_range) > 1 else None |
| 253 | + |
| 254 | + if past is None and future is None: |
| 255 | + return |
| 256 | + |
| 257 | + is_nearest = past.endswith(NEAREST_OPTIONS) if past else False |
| 258 | + |
| 259 | + # Validate past if provided |
| 260 | + if is_nearest: |
| 261 | + past_option = "np" if past.endswith("np") else "nd" |
| 262 | + past_int = int(past[:-2]) if past[:-2] else None |
| 263 | + else: |
| 264 | + past_option = past[-1] if past else None |
| 265 | + past_int = int(past[:-1]) if past else None |
249 | 266 |
|
250 | | - if (past_option and past_option not in date_range_options) or ( |
251 | | - past_int and past_int > 0 |
| 267 | + # Validate past option and its integer value |
| 268 | + if (past_option not in DATE_RANGE_OPTIONS) or ( |
| 269 | + past_option not in NEAREST_OPTIONS and past_int > 0 |
252 | 270 | ): |
253 | 271 | raise ValueError( |
254 | 272 | f"Invalid past '{past}'. Must end with " |
255 | | - f"{date_range_options} and be negative." |
| 273 | + f"{DATE_RANGE_OPTIONS} and must be negative." |
256 | 274 | ) |
257 | | - if (future_option and future_option not in date_range_options) or ( |
258 | | - future_int and future_int < 0 |
259 | | - ): |
| 275 | + |
| 276 | + # Validate future if provided |
| 277 | + if future is None: |
| 278 | + return |
| 279 | + elif future.endswith(NEAREST_OPTIONS): |
| 280 | + raise ValueError( |
| 281 | + "Nearest need to be in this format, (<int><option>, ). " |
| 282 | + "Eg. ('6np',) or ('6nd',)" |
| 283 | + ) |
| 284 | + else: |
| 285 | + future_option = future[-1] if future else None |
| 286 | + future_int = int(future[:-1]) if future else None |
| 287 | + |
| 288 | + # Validate future option and integer value |
| 289 | + if (future_option not in DATE_RANGE_OPTIONS) or (future_int < 0): |
260 | 290 | raise ValueError( |
261 | 291 | f"Invalid future '{future}'. Must end with " |
262 | | - f"{date_range_options} and be positive." |
| 292 | + f"{DATE_RANGE_OPTIONS} and be positive." |
263 | 293 | ) |
264 | 294 |
|
265 | 295 | def _validate_source(self, source: str) -> None: |
|
0 commit comments