@@ -219,6 +219,75 @@ def parse_mars_request(file_or_str: IO | str, strict: bool = False) -> list[Mars
219219 return requests
220220
221221
222+ def parse_key (
223+ keyword : str ,
224+ value : str | int | list ,
225+ verb : str = "retrieve" ,
226+ context : "MarsRequest | dict | None" = None ,
227+ strict : bool = False ,
228+ ) -> list [str ]:
229+ """Parse/normalise the values of a single MARS key, without building a full request.
230+
231+ Applies the MARS language rules for ``keyword``: range syntax such as
232+ ``"1/to/10/by/1"`` is expanded, and per-key normalisation is performed (e.g.
233+ ``date="-1"`` resolves to a ``yyyymmdd`` date, ``time="6"`` to ``"0600"``).
234+
235+ Context-sensitive keys (e.g. those whose interpretation depends on other
236+ keys) consult ``context``. Supply the relevant neighbouring keys there, e.g.
237+ ``parse_key("levelist", "1/to/10", context={"levtype": "ml"})``.
238+
239+ Note: this performs single-pass expansion only. Second-pass, rule-based
240+ resolution (e.g. ``param``) and default inheritance are not applied; use
241+ :meth:`MarsRequest.expand` on a (scoped) request for those.
242+
243+ Params
244+ ------
245+ keyword: name of the MARS key to parse (canonical, alias or unambiguous prefix)
246+ value: values to expand, as a ``"a/b/c"`` string or a list of tokens
247+ verb: MARS verb whose language defines the key (defaults to "retrieve")
248+ context: optional MarsRequest or dict of neighbouring keys for context-sensitive keys
249+ strict: if True, raise an error on invalid values
250+
251+ Returns
252+ -------
253+ list of expanded/normalised string values
254+
255+ Examples
256+ --------
257+ >>> parse_key("step", "1/to/10/by/1")
258+ ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10']
259+ """
260+ if isinstance (value , (list , tuple )):
261+ value = "/" .join (str (v ) for v in value )
262+ else :
263+ value = str (value )
264+
265+ context_c = ffi .NULL
266+ if context is not None :
267+ if isinstance (context , dict ):
268+ context = MarsRequest (** context )
269+ context_c = context .ctype ()
270+
271+ it_c = ffi .new ("metkit_paramiterator_t **" )
272+ lib .metkit_parse_key (
273+ ffi_encode (verb ),
274+ ffi_encode (keyword ),
275+ ffi_encode (value ),
276+ context_c ,
277+ strict ,
278+ it_c ,
279+ )
280+ it = ffi .gc (it_c [0 ], lib .metkit_paramiterator_delete )
281+
282+ values = []
283+ while lib .metkit_paramiterator_next (it ) == lib .METKIT_ITERATOR_SUCCESS :
284+ cvalue = ffi .new ("const char **" )
285+ lib .metkit_paramiterator_current (it , cvalue )
286+ values .append (ffi_decode (cvalue [0 ]))
287+
288+ return values
289+
290+
222291class MetKitException (RuntimeError ):
223292 """Raised when MetKit library throws exception"""
224293
0 commit comments