diff --git a/share/metkit/axis.yaml b/share/metkit/axis.yaml index 35192680..84d18c6d 100644 --- a/share/metkit/axis.yaml +++ b/share/metkit/axis.yaml @@ -1,6 +1,7 @@ --- axes: - class + - country - type - stream - levtype @@ -50,3 +51,7 @@ axes: - year - month - obsgroup + - bcmodel + - icmodel + - grib + diff --git a/share/metkit/language.yaml b/share/metkit/language.yaml index ce72bdc6..23ed5701 100644 --- a/share/metkit/language.yaml +++ b/share/metkit/language.yaml @@ -13,85 +13,81 @@ _field: &_field flatten: false type: enum values: - - [ai, operational aifs] - - [at, austria] - - [be, belgium] - - [c3, c3s] - - [ce, cems] - - [ch, switzerland] - - [ci, cerise] - - [co, cosmo] - - [cr, cams research] - - [cs, ecsn] - - [d1, destine] - - [de, germany] - - [dk, denmark] - - [dm, demeter] - - [dt, dts] - - [e2, e20c] - - [e4, reanalyse40] - - [e6, era6] - - [ea, era5, esat] - - [ed, eerie] - - [ef, efas] - - [ei, era interim] - - [el, eldas] - - [em, e20cm] - - [en, ensembles] - - [ep, cera-20c, cera20c] - - [er, reanalyse] - - [es, spain] - - [et, cera-sat, cerasat] - - [fi, finland] - - [fr, france] - - [gf, glofas] - - [gg, greenhouse gases] - - [gr, greece] - - [gw, global wildfire information system] - - [hr, croatia] - - [hu, hungary] - - [ie, ireland] - - [is, iceland] - - [it, italy] - - [j5, jra55] - - [l5, era5l] - - [l6, era6l] - - [la, aladin-laef, laef, lace] - - [lw, WMO lead centre wave forecast verification] - - [ma, metaps] - - [mc, macc] - - [me, mersea] - - [ml, machine learning] - - [ms, member states] - - [ng, nextgems] - - [nl, netherlands] - - ['no', norway] - - [nr, ncep 20cr, 20cr] - - [o6, 'ocean 6 reanalysis'] - - [od, operations] - - [pe, permanent experiment] - - [pt, portugal] - - [pv, provost] - - [rd, research] - - [rm, euro4m] - - [rr, regional reanalysis] - - [s2, s2s] - - [se, sweden] - - [si, slovenia] - - [sr, sreps] - - [te, test] - - [ti, tigge] - - [to, tost] - - [tr, turkey] - - [uk, united kingdom] - - [ul, ulysses] - - [ur, uerra] - - [yp, yopp] - - [yt, yotc] - - - - + - [ai, operational aifs] + - [at, austria] + - [be, belgium] + - [c3, c3s] + - [ce, cems] + - [ch, switzerland] + - [ci, cerise] + - [co, cosmo] + - [cr, cams research] + - [cs, ecsn] + - [d1, destine] + - [de, germany] + - [dk, denmark] + - [dm, demeter] + - [dt, dts] + - [e2, e20c] + - [e4, reanalyse40] + - [e6, era6] + - [ea, era5, esat] + - [ed, eerie] + - [ef, efas] + - [ei, era interim] + - [el, eldas] + - [em, e20cm] + - [en, ensembles] + - [ep, cera-20c, cera20c] + - [er, reanalyse] + - [es, spain] + - [et, cera-sat, cerasat] + - [fi, finland] + - [fr, france] + - [gf, glofas] + - [gg, greenhouse gases] + - [gr, greece] + - [gw, global wildfire information system] + - [hr, croatia] + - [hu, hungary] + - [ie, ireland] + - [is, iceland] + - [it, italy] + - [j5, jra55] + - [l5, era5l] + - [l6, era6l] + - [la, aladin-laef, laef, lace] + - [lw, WMO lead centre wave forecast verification] + - [ma, metaps] + - [mc, macc] + - [me, mersea] + - [ml, machine learning] + - [ms, member states] + - [ng, nextgems] + - [nl, netherlands] + - ['no', norway] + - [nr, ncep 20cr, 20cr] + - [o6, 'ocean 6 reanalysis'] + - [od, operations] + - [pe, permanent experiment] + - [pt, portugal] + - [pv, provost] + - [rd, research] + - [rm, euro4m] + - [rr, regional reanalysis] + - [s2, s2s] + - [se, sweden] + - [si, slovenia] + - [sr, sreps] + - [te, test] + - [ti, tigge] + - [to, tost] + - [tr, turkey] + - [uk, united kingdom] + - [ul, ulysses] + - [ur, uerra] + - [yp, yopp] + - [yt, yotc] type: category: data @@ -101,242 +97,295 @@ _field: &_field - context: _verb: [retrieve] stream: [ssmi] - val: ob + vals: [ob] warn: "Changed type=ob" flatten: false type: enum values: - - [3g, 3d variational gradients] - - [3v, 3d variational analysis] - - [4g, 4d variational gradients] - - [4i, 4d variational increments] - - [4v, 4d variational analysis] - - [ab, analysis bias] - - [af, analysis feedback] - - [ai, analysis input] - - [an, analysis] - - [as, adjoint singular vector] - - [bf, bias-corrected forecast] - - [cd, climate distribution] - - [cf, control forecast] - - [ci, clustering information] - - [cl, climatology] - - [cm, cluster means] - - [cr, cluster representative] - - [cs, cluster std deviations] - - [cv, calibration validation forecast] - - [ea, errors in analysis] - - [ed, empirical distribution] - - [ef, errors in first guess] - - [efi, extreme forecast index] - - [efic, extreme forecast index control] - - [em, ensemble mean] - - [eme, ensemble data assimilation model errors] - - [emtm, ensemble mean of temporal mean] - - [ep, event probability] - - [es, ensemble standard deviation] - - [est, ensemble statistics] - - [estdtm, ensemble standard deviation of temporal mean] - - [fa, forecast accumulation] - - [fb, feedback] - - [fc, forecast] - - [fcdfb, forecast departures feedback] - - [fcmax, forecast maximum] - - [fcmean, forecast mean] - - [fcmin, forecast minimum] - - [fcstdev, forecast standard deviation] - - [ff, flux forcing realtime] - - [fg, first guess] - - [fp, forecast probability] - - [fsoifb, forecast sensitivity to observations impact feedback] - - [fu, fill-up] - - [fx, flux forcing] - - [ga, gfas analysis] - - [gbf, bias-corrected gridbox] - - [gai, gridded analysis input] - - [go, gridded observations] - - [gsd, gridded satellite data] - - [gwt, weather type gridbox] - - [hcmean, hindcast mean] - - [ia, init. analysis] - - [icp, initial condition perturbation] - - [mpp, model physics perturbation] - - [if, interim forecast] - - [im, images] - - [me, model errors] - - [mfb, mondb feedback] - - [oai, odb analysis input] - - [ob, observations] - - [of, ocean forward] - - [ofa, odb feedback from analysis] - - [ofb, odb feedback] - - [oi, oi analysis] - - [oldim, old format images] - - [or, ocean reanalysis] - - [pa, perturbed analysis] - - [pb, probability boundary] - - [pd, probability distribution] - - [pf, perturbed forecast] - - [pfc, point values] - - [ppm, point value metrics] - - [s3, climate 30 days simulation] - - [ses, scaled ensemble standard deviation] - - [sf, sensitivity forecast] - - [sfb, summary feedback] - - [sfo, simulations with forcing] - - [sg, sensitivity gradient] - - [si, climate simulation] - - [sim, simulated images] - - [sot, shift of tails] - - [ssd, simulated satellite data] - - [sv, singular vector] - - [svar, signal variance] - - [taem, time average ensemble mean] - - [taes, time average ensemble standard deviation] - - [tpa, time processed analysis] - - [tf, trajectory forecast] - - [tu, tube] - - [wem, weighted ensemble mean] - - [wes, weighted ensemble standard deviation] - - [wp, weather parameters] + - [3g, 3d variational gradients] + - [3v, 3d variational analysis] + - [4g, 4d variational gradients] + - [4i, 4d variational increments] + - [4v, 4d variational analysis] + - [ab, analysis bias] + - [af, analysis feedback] + - [ai, analysis input] + - [an, analysis] + - [as, adjoint singular vector] + - [bf, bias-corrected forecast] + - [cd, climate distribution] + - [cf, control forecast] + - [ci, clustering information] + - [cl, climatology] + - [cm, cluster means] + - [cr, cluster representative] + - [cs, cluster std deviations] + - [cv, calibration validation forecast] + - [ea, errors in analysis] + - [ed, empirical distribution] + - [ef, errors in first guess] + - [efi, extreme forecast index] + - [efic, extreme forecast index control] + - [em, ensemble mean] + - [eme, ensemble data assimilation model errors] + - [emtm, ensemble mean of temporal mean] + - [ep, event probability] + - [es, ensemble standard deviation] + - [est, ensemble statistics] + - [estdtm, ensemble standard deviation of temporal mean] + - [fa, forecast accumulation] + - [fb, feedback] + - [fc, forecast] + - [fcdfb, forecast departures feedback] + - [fcmax, forecast maximum] + - [fcmean, forecast mean] + - [fcmin, forecast minimum] + - [fcstdev, forecast standard deviation] + - [ff, flux forcing realtime] + - [fg, first guess] + - [fp, forecast probability] + - [fsoifb, forecast sensitivity to observations impact feedback] + - [fu, fill-up] + - [fx, flux forcing] + - [ga, gfas analysis] + - [gbf, bias-corrected gridbox] + - [gai, gridded analysis input] + - [go, gridded observations] + - [gsd, gridded satellite data] + - [gwt, weather type gridbox] + - [hcmean, hindcast mean] + - [ia, init. analysis] + - [icp, initial condition perturbation] + - [mpp, model physics perturbation] + - [if, interim forecast] + - [im, images] + - [me, model errors] + - [mfb, mondb feedback] + - [oai, odb analysis input] + - [ob, observations] + - [of, ocean forward] + - [ofa, odb feedback from analysis] + - [ofb, odb feedback] + - [oi, oi analysis] + - [oldim, old format images] + - [or, ocean reanalysis] + - [pa, perturbed analysis] + - [pb, probability boundary] + - [pd, probability distribution] + - [pf, perturbed forecast] + - [pfc, point values] + - [ppm, point value metrics] + - [s3, climate 30 days simulation] + - [ses, scaled ensemble standard deviation] + - [sf, sensitivity forecast] + - [sfb, summary feedback] + - [sfo, simulations with forcing] + - [sg, sensitivity gradient] + - [si, climate simulation] + - [sim, simulated images] + - [sot, shift of tails] + - [ssd, simulated satellite data] + - [sv, singular vector] + - [svar, signal variance] + - [taem, time average ensemble mean] + - [taes, time average ensemble standard deviation] + - [tpa, time processed analysis] + - [tf, trajectory forecast] + - [tu, tube] + - [wem, weighted ensemble mean] + - [wes, weighted ensemble standard deviation] + - [wp, weather parameters] stream: category: data defaults: - - vals: [oper] + - context: + class: [ti] + vals: [enfo] + - context: + class: + op: '!' + vals: [ti] + vals: [oper] set: - context: _verb: [retrieve] stream: [ssbt, e1, ssmi] - val: oper + vals: [oper] warn: "Changed stream=oper" - context: class: [ti] type: [fc] - val: oper + vals: [oper] + flatten: false + type: enum + values: + - [amap, analysis for multianalysis project] + - [ammc, melbourne] + - [cher, ch, chernobyl] + - [clte, climate, Climate run output] + - [clmn, climate-monthly, Climate run monthly means output] + - [cnrm, meteo france climate centre] + - [cwao, montreal] + - [dacl, daily climatology] + - [dacw, daily climatology wave] + - [dahc, daily archive hindcast] + - [dcda, atmospheric model (delayed cutoff)] + - [dcwv, wave model (delayed cutoff)] + - [edmm, ensemble data assimilation monthly means] + - [edmo, ensemble data assimilation monthly means of daily means] + - [edzw, offenbach] + - [eefh, extended ensemble forecast hindcast] + - [eefo, extended ensemble prediction system] + - [eehs, extended ensemble forecast hindcast statistics] + - [efas, european flood awareness system (efas)] + - [efcl, european flood awareness system (efas) climatology] + - [efhc, ensemble forecast hindcasts (obsolete)] + - [efho, ensemble forecast hindcast overlap] + - [efhs, ensemble forecast hindcast statistics] + - [efov, ensemble forecast overlap] + - [efrf, european flood awareness system (efas) reforecasts] + - [efse, european flood awareness system (efas) seasonal forecasts] + - [efsr, european flood awareness system (efas) seasonal reforecasts] + - [egrr, exeter, bracknell] + - [ehmm, combined multi-model hindcast monthly means] + - [elda, ensemble long window data assimilation] + - [enda, ensemble data assimilation] + - [enfh, ensemble forecast hindcasts] + - [enfo, ef, ensemble prediction system] + - [enwh, ensemble forecast wave hindcasts] + - [esmm, combined multi-model monthly means] + - [espd, ensemble supplementary data] + - [ewda, ensemble wave data assimilation] + - [ewhc, wave ensemble forecast hindcast (obsolete)] + - [ewho, ensemble forecast wave hindcast overlap] + - [ewla, ensemble wave long window data assimilation] + - [ewmm, ensemble wave data assimilation monthly means] + - [ewmo, ensemble wave data assimilation monthly means of daily means] + - [fgge, fg] + - [fsob, forecast sensitivity to observations] + - [fsow, forecast sensitivity to observations wave] + - [gfas, global fire assimilation system] + - [gfra, global fire assimilation system reanalysis] + - [kwbc, washington] + - [lfpw, paris, toulouse] + - [lwda, long window daily archive] + - [lwwv, long window wave] + - [ma, means archive] + - [maed, multianalysis ensemble data] + - [mawm, wave anomaly means] + - [mawv, multianalysis wave data] + - [mdfa, monthly means of daily forecast accumulations] + - [mfam, anomaly means] + - [mfaw, wave anomalies] + - [mfhm, hindcast means] + - [mfhw, monthly forecast hindcasts wave] + - [mfwm, wave real-time means] + - [mhwm, wave hindcast means] + - [mmaf, multi-model multi-annual forecast] + - [mmam, multi-model multi-annual forecast means] + - [mmaw, multi-model multi-annual forecast wave] + - [mmsa, multi-model seasonal forecast monthly anomalies] + - [mmsf, multi-model seasonal forecast] + - [mmwm, multi-model multi-annual forecast wave means] + - [mnfa, anomalies] + - [mnfc, real-time] + - [mnfh, hindcasts] + - [mnfm, real-time means] + - [mnfw, wave real-time] + - [mnth, mo, monthly, monthly means] + - [mnvr, monthly variance and covariance data using g. boer's step function] + - [moda, monthly means of daily means] + - [mofc, monthly forecast] + - [mofm, monthly forecast means] + - [monr, monthly means using g. boer's step function] + - [mpic, max plank institute] + - [msda, monthly standard deviation and covariance of daily means] + - [msdc, mv, monthly standard deviation and covariance] + - [msmm, multi-model seasonal forecast atmospheric monthly means] + - [mswm, multi-model seasonal forecast wave monthly means] + - [ocda, ocean data assimilation] + - [ocea, ocean] + - [olda, ocean Long window data assimilation] + - [oper, da, daily archive, atmospheric model] + - [rjtd, tokyo] + - [scda, atmospheric model (short cutoff)] + - [scwv, wave model (short cutoff)] + - [seap, sensitive area prediction] + - [seas, seasonal forecast] + - [sens, sf, sensitivity forecast] + - [sfmm, seasonal forecast atmospheric monthly means] + - [smma, seasonal monthly means anomalies] + - [supd, sd, deterministic supplementary data] + - [swmm, seasonal forecast wave monthly means] + - [toga, tg] + - [ukmo, ukmo climate centre] + - [waef, we, wave ensemble forecast] + - [wamd, wave monthly means of daily means] + - [wamf, wave monthly forecast] + - [wamo, wave monthly means] + - [wams, multi-model seasonal forecast wave] + - [wasf, wave seasonal forecast] + - [wave, wv, wave model] + - [wavm, wave model (standalone)] + - [weef, wave extended ensemble forecast] + - [weeh, wave extended ensemble forecast hindcast] + - [wees, wave extended ensemble forecast hindcast statistics] + - [wehs, wave ensemble forecast hindcast statistics] + - [weov, wave ensemble forecast overlap] + - [wfas, global flood awareness system (glofas)] + - [wfcl, global flood awareness system (glofas) climatology] + - [wfrf, global flood awareness system (glofas) reforecasts] + - [wfse, global flood awareness system (glofas) seasonal forecasts] + - [wfsr, global flood awareness system (glofas) seasonal reforecasts] + - [wmfm, wave monthly forecast means] + - [wvhc, wave hindcast] + + product: + category: data + type: enum + values: + - [inst, instantaneous] + - [tims, time-series] + - [tavg, time-average] + - [tacc, time-accumulation] + - all + + section: + category: data + type: enum + values: + - [h, horizontal] + - [v, vertical] + - [z, zonal] + - [m, meridional] + - all + + range: + category: data + type: any + + + use: flatten: false + multiple: true type: enum values: - - [amap, analysis for multianalysis project] - - [ammc, melbourne] - - [cher, ch, chernobyl] - - [clte, climate, Climate run output] - - [clmn, climate-monthly, Climate run monthly means output] - - [cnrm, meteo france climate centre] - - [cwao, montreal] - - [dacl, daily climatology] - - [dacw, daily climatology wave] - - [dahc, daily archive hindcast] - - [dcda, atmospheric model (delayed cutoff)] - - [dcwv, wave model (delayed cutoff)] - - [edmm, ensemble data assimilation monthly means] - - [edmo, ensemble data assimilation monthly means of daily means] - - [edzw, offenbach] - - [eefh, extended ensemble forecast hindcast] - - [eefo, extended ensemble prediction system] - - [eehs, extended ensemble forecast hindcast statistics] - - [efas, european flood awareness system (efas)] - - [efcl, european flood awareness system (efas) climatology] - - [efhc, ensemble forecast hindcasts (obsolete)] - - [efho, ensemble forecast hindcast overlap] - - [efhs, ensemble forecast hindcast statistics] - - [efov, ensemble forecast overlap] - - [efrf, european flood awareness system (efas) reforecasts] - - [efse, european flood awareness system (efas) seasonal forecasts] - - [efsr, european flood awareness system (efas) seasonal reforecasts] - - [egrr, exeter, bracknell] - - [ehmm, combined multi-model hindcast monthly means] - - [elda, ensemble long window data assimilation] - - [enda, ensemble data assimilation] - - [enfh, ensemble forecast hindcasts] - - [enfo, ef, ensemble prediction system] - - [enwh, ensemble forecast wave hindcasts] - - [esmm, combined multi-model monthly means] - - [espd, ensemble supplementary data] - - [ewda, ensemble wave data assimilation] - - [ewhc, wave ensemble forecast hindcast (obsolete)] - - [ewho, ensemble forecast wave hindcast overlap] - - [ewla, ensemble wave long window data assimilation] - - [ewmm, ensemble wave data assimilation monthly means] - - [ewmo, ensemble wave data assimilation monthly means of daily means] - - [fgge, fg] - - [fsob, forecast sensitivity to observations] - - [fsow, forecast sensitivity to observations wave] - - [gfas, global fire assimilation system] - - [gfra, global fire assimilation system reanalysis] - - [kwbc, washington] - - [lfpw, paris, toulouse] - - [lwda, long window daily archive] - - [lwwv, long window wave] - - [ma, means archive] - - [maed, multianalysis ensemble data] - - [mawm, wave anomaly means] - - [mawv, multianalysis wave data] - - [mdfa, monthly means of daily forecast accumulations] - - [mfam, anomaly means] - - [mfaw, wave anomalies] - - [mfhm, hindcast means] - - [mfhw, monthly forecast hindcasts wave] - - [mfwm, wave real-time means] - - [mhwm, wave hindcast means] - - [mmaf, multi-model multi-annual forecast] - - [mmam, multi-model multi-annual forecast means] - - [mmaw, multi-model multi-annual forecast wave] - - [mmsa, multi-model seasonal forecast monthly anomalies] - - [mmsf, multi-model seasonal forecast] - - [mmwm, multi-model multi-annual forecast wave means] - - [mnfa, anomalies] - - [mnfc, real-time] - - [mnfh, hindcasts] - - [mnfm, real-time means] - - [mnfw, wave real-time] - - [mnth, mo, monthly, monthly means] - - [mnvr, monthly variance and covariance data using g. boer's step function] - - [moda, monthly means of daily means] - - [mofc, monthly forecast] - - [mofm, monthly forecast means] - - [monr, monthly means using g. boer's step function] - - [mpic, max plank institute] - - [msda, monthly standard deviation and covariance of daily means] - - [msdc, mv, monthly standard deviation and covariance] - - [msmm, multi-model seasonal forecast atmospheric monthly means] - - [mswm, multi-model seasonal forecast wave monthly means] - - [ocda, ocean data assimilation] - - [ocea, ocean] - - [olda, ocean Long window data assimilation] - - [oper, da, daily archive, atmospheric model] - - [rjtd, tokyo] - - [scda, atmospheric model (short cutoff)] - - [scwv, wave model (short cutoff)] - - [seap, sensitive area prediction] - - [seas, seasonal forecast] - - [sens, sf, sensitivity forecast] - - [sfmm, seasonal forecast atmospheric monthly means] - - [smma, seasonal monthly means anomalies] - - [supd, sd, deterministic supplementary data] - - [swmm, seasonal forecast wave monthly means] - - [toga, tg] - - [ukmo, ukmo climate centre] - - [waef, we, wave ensemble forecast] - - [wamd, wave monthly means of daily means] - - [wamf, wave monthly forecast] - - [wamo, wave monthly means] - - [wams, multi-model seasonal forecast wave] - - [wasf, wave seasonal forecast] - - [wave, wv, wave model] - - [wavm, wave model (standalone)] - - [weef, wave extended ensemble forecast] - - [weeh, wave extended ensemble forecast hindcast] - - [wees, wave extended ensemble forecast hindcast statistics] - - [wehs, wave ensemble forecast hindcast statistics] - - [weov, wave ensemble forecast overlap] - - [wfas, global flood awareness system (glofas)] - - [wfcl, global flood awareness system (glofas) climatology] - - [wfrf, global flood awareness system (glofas) reforecasts] - - [wfse, global flood awareness system (glofas) seasonal forecasts] - - [wfsr, global flood awareness system (glofas) seasonal reforecasts] - - [wmfm, wave monthly forecast means] - - [wvhc, wave hindcast] + - [frequent, f] + - [infrequent, i] + - [normal, n] + - compare + - [monthly run] + - intent + - disk + - [bc, boundary conditions] + - monday + - tuesday + - wednesday + - thursday + - friday + - saturday + - sunday # product: # %if LEVTYPE = DP @@ -346,6 +395,7 @@ _field: &_field # %warning "Default PRODUCT for Ocean ReAnalysis set to Instantaneous" # %set PRODUCT = INST + expver: category: data flatten: false @@ -357,63 +407,77 @@ _field: &_field class: [ti, s2, ur, rr, lw] expver: op: 'u' - val: 'prod' + vals: [prod] dataset: category: data multiple: false - type: enum - values: - - [climate-dt, Climate change adaptation digital twin] - - [extremes-dt, Weather and geophysical extremes digital twin] - - [on-demand-climate-dt, On-demand climate change adaptation digital twin] - - [on-demand-extremes-dt, On-demand weather and geophysical extremes digital twin] - unset: - - context: - class: - op: '!' - vals: [d1] + type: + - context: + class: [d1] + type: enum + values: + - [climate-dt, Climate change adaptation digital twin] + - [extremes-dt, Weather and geophysical extremes digital twin] + - [on-demand-climate-dt, On-demand climate change adaptation digital twin] + - [on-demand-extremes-dt, On-demand weather and geophysical extremes digital twin] + unset: + - context: + class: + op: '!' + vals: [d1] + - type: lowercase model: category: data - type: enum - values: - - [ecmf] - - [edzw] - - [egrr] - - [lfpw] - - [kwbc] - - [none] - - [hrm] - - [ifs, IFS, IFS with no ocean model] - - [ifs-nemo, IFS-NEMO, IFS with NEMO ocean model] - - [ifs-fesom, IFS-FESOM, IFS with FESOM ocean model] - - [icon, ICON, ICON-A with ICON-O ocean model] - - [lisflood] - - [lm] - - [aifs] - - [aifs-single] - - [aifs-single-mse] - - [aifs-ens] - - [aifs-ens-crps] - - [aifs-ens-diff] - - [alaro] - - [arome] - - [harmonie-arome] - - [global, glob] - unset: - - context: - class: [ml, ur, rr] - set: - - context: - _verb: [retrieve] - class: [ai] - model: - op: 'u' - val: aifs-single-mse - + type: + - context: + class: [ms] + country: [it] + type: enum + values: + - [lm] + - [hrm] + - [wam] + - type: enum + values: + - [ecmf] + - [edzw] + - [egrr] + - [lfpw] + - [kwbc] + - [none] + - [hrm] + - [ifs, IFS with no ocean model] + - [ifs-nemo, IFS with NEMO ocean model] + - [ifs-fesom, IFS with FESOM ocean model] + - [icon, ICON-A with ICON-O ocean model] + - [lisflood] + - [lm] + - [lam] + - [aifs] + - [aifs-single] + - [aifs-single-mse] + - [aifs-ens] + - [aifs-ens-crps] + - [aifs-ens-diff] + - [alaro] + - [arome] + - [harmonie-arome] + - [global, glob] + unset: + - context: + class: [ml, ur, rr] + set: + - context: + _verb: [retrieve] + class: [ai] + model: + op: 'u' + vals: [aifs-single-mse] georef: + category: data type: lowercase # only: # - context: @@ -431,56 +495,56 @@ _field: &_field repres: flatten: false multiple: false - defaults: - - vals: [sh] + # defaults: + # - vals: [sh] type: enum - set: - - context: - stream: - op: '!' - vals: [ssmi] - type: [im, sim, oldim] - val: sv - - context: - type: [ob, fb, ai, af, ab, ofb, mfb, oai, sfb, fsoifb, fcdfb, tf, ofa] - val: bu - - context: - stream: [ssmi] - val: bu - - context: - levtype: [sfc] - class: [od] - stream: [oper] - val: gg - - context: - levtype: [sfc] - class: [er] - stream: [oper] - type: [an, fc] - repres: - op: 'u' - val: gg - - context: - _verb: [retrieve] - type: [tu] - val: ll + # set: + # - context: + # stream: + # op: '!' + # vals: [ssmi] + # type: [im, sim, oldim] + # vals: [sv] + # - context: + # type: [ob, fb, ai, af, ab, ofb, mfb, oai, sfb, fsoifb, fcdfb, tf, ofa] + # vals: [bu] + # - context: + # stream: [ssmi] + # vals: [bu] + # - context: + # levtype: [sfc] + # class: [od] + # stream: [oper] + # vals: [gg] + # - context: + # levtype: [sfc] + # class: [er] + # stream: [oper] + # type: [an, fc] + # repres: + # op: 'u' + # vals: [gg] + # - context: + # _verb: [retrieve] + # type: [tu] + # vals: [ll] # %if LEVTYPE = SFC %and CLASS = OD %and STREAM = OPER %and (TYPE = IA %or TYPE = AN) %and DATE < 19830420 %then # %set REPRES = LL - unset: - - context: - class: [ep] - levtype: [o2d, o3d] - - context: - _verb: [read] + # unset: + # - context: + # class: [ep] + # levtype: [o2d, o3d] + # - context: + # _verb: [read] values: - - [bu, 'bufr'] - - [sh, 'spherical harmonics'] - - [ll, 'lat long grid'] - - [gg, 'gaussian grid'] - - [sv, 'space view'] - - [og, 'ocean grid'] - - [np] - - [rl] + - [bu, 'bufr'] + - [sh, 'spherical harmonics'] + - [ll, 'lat long grid'] + - [gg, 'gaussian grid'] + - [sv, 'space view'] + - [og, 'ocean grid'] + - [np] + - [rl] @@ -489,80 +553,80 @@ _field: &_field multiple: true type: enum values: - # - [conventional] - - [sat, satellite] - - [ers1] - - [trmm] - - [qscat] - - [reo3] # reo3 needs to stay for compatibility - # previously in "obsgroups.def" - - [hirs, 1, HIRS ] - - [amsua, 2, AMSUA ] - - [amsub, 3, AMSUB ] - - [mhs, 4, MHS ] - - [geos, 5, GEOS ] - - [resat, 6, RESAT ] - - [meris, 7, MERIS ] - - [gpsro, 8, GPSRO ] - - [satob, 9, SATOB ] - - [scatt, 10, SCATT ] - - [ssmi_as, 11, SSMI ALL-SKY ] - - [iasi, 12, IASI ] - - [airs, 13, AIRS ] - - [ssmis_as, 14, SSMIS ALL-SKY ] - - [tmi_as, 15, TMI ALL-SKY ] - - [amsre_as, 16, AMSRE ALL-SKY ] - - [conv, 17, CONV ] - - [smos, 19, SMOS ] - - [windsat_as, 20, WINDSAT ALL-SKY ] - - [ssmi, 21, SSMI ] - - [amsua_as, 22, AMSUA ALL-SKY ] - - [amsre, 23, AMSRE ] - - [tmi, 24, TMI ] - - [ssmis, 25, SSMIS ] - - [gbrad, 26, GBRAD ] - - [mwhs, 27, MWHS ] - - [mwts, 28, MWTS ] - - [mwri_as, 29, MWRI ALL-SKY ] - - [iras, 30, IRAS ] - - [msu, 31, MSU ] - - [ssu, 32, SSU ] - - [vtpr1, 33, VTPR1 ] - - [vtpr2, 34, VTPR2 ] - - [atms, 35, ATMS ] - - [resat_ak, 36, RESAT AVERAGING KERNELS ] - - [cris, 37, CRIS ] - - [wave_ip, 38, WAVE INTEGRATED PARAMETERS ] - - [wave_sp, 39, WAVE SPECTRA ] - - [raingg, 40, RAINGG ] - - [sfc_ms, 41, SURFACE MULTISENSOR ] - - [amsr2_as, 42, AMSR-2 ALL-SKY ] - - [saphir_as, 43, SAPHIR ALL-SKY ] - - [amsub_as, 44, AMSUB ALL-SKY ] - - [mhs_as, 45, MHS ALL-SKY ] - - [dwl, 46, DOPPLER WIND LIDAR ] - - [iris, 47, IRIS ] - - [aatsr, 49, AATSR ] - - [atms_as, 50, ATMS ALL-SKY ] - - [gmi_as, 51, GMI ALL-SKY ] - - [godae_sst, 52, GODAE SEA SURFACE TEMPERATURES ] - - [atovs_ms, 53, ATOVS MULTISENSOR ] - - [atmospheric_composition, 54, ATMOSPHERIC COMPOSITION ] - - [non_sfc_ms, 55, NON-SURFACE MULTISENSOR ] - - [mwts2, 56, MWTS2 ] - - [ssmi_1d, 57, SSMI 1DVAR TCWV CLOUDY-SKY ] - - [mwhs2_as, 58, MWHS2 ALL-SKY ] - - [ssmt2, 59, SSMT2 ] - - [smap, 60, SMAP ] - - [tovs_ms, 61, TOVS MULTISENSOR ] - - [cloud_r, 62, CLOUD REFLECTIVITY ] - - [cloud_l, 63, CLOUD LIDAR ] - - [satellite_lightning, 64, SATELLITE LIGHTNING ] - - [geos_vis, 65, GEOS VIS ] - - [oconv, 66, OCONV ] - - [mwts3_as, 67, MWTS3 All-sky ] - - [giirs, 68, GIIRS ] - - [test, 99, TEST ] + # - [conventional] + - [sat, satellite] + - [ers1] + - [trmm] + - [qscat] + - [reo3] # reo3 needs to stay for compatibility + # previously in "obsgroups.def" + - [hirs, 1] + - [amsua, 2] + - [amsub, 3] + - [mhs, 4] + - [geos, 5] + - [resat, 6] + - [meris, 7] + - [gpsro, 8] + - [satob, 9] + - [scatt, 10] + - [ssmi_as, 11, SSMI ALL-SKY] + - [iasi, 12] + - [airs, 13] + - [ssmis_as, 14, SSMIS ALL-SKY] + - [tmi_as, 15, TMI ALL-SKY] + - [amsre_as, 16, AMSRE ALL-SKY] + - [conv, 17] + - [smos, 19] + - [windsat_as, 20, WINDSAT ALL-SKY] + - [ssmi, 21] + - [amsua_as, 22, AMSUA ALL-SKY] + - [amsre, 23] + - [tmi, 24] + - [ssmis, 25] + - [gbrad, 26] + - [mwhs, 27] + - [mwts, 28] + - [mwri_as, 29, MWRI ALL-SKY] + - [iras, 30] + - [msu, 31] + - [ssu, 32] + - [vtpr1, 33] + - [vtpr2, 34] + - [atms, 35] + - [resat_ak, 36, RESAT AVERAGING KERNELS] + - [cris, 37] + - [wave_ip, 38, WAVE INTEGRATED PARAMETERS] + - [wave_sp, 39, WAVE SPECTRA] + - [raingg, 40] + - [sfc_ms, 41, SURFACE MULTISENSOR] + - [amsr2_as, 42, AMSR-2 ALL-SKY] + - [saphir_as, 43, SAPHIR ALL-SKY] + - [amsub_as, 44, AMSUB ALL-SKY] + - [mhs_as, 45, MHS ALL-SKY] + - [dwl, 46, DOPPLER WIND LIDAR] + - [iris, 47] + - [aatsr, 49] + - [atms_as, 50, ATMS ALL-SKY] + - [gmi_as, 51, GMI ALL-SKY] + - [godae_sst, 52, GODAE SEA SURFACE TEMPERATURES] + - [atovs_ms, 53, ATOVS MULTISENSOR] + - [atmospheric_composition, 54, ATMOSPHERIC COMPOSITION] + - [non_sfc_ms, 55, NON-SURFACE MULTISENSOR] + - [mwts2, 56] + - [ssmi_1d, 57, SSMI 1DVAR TCWV CLOUDY-SKY] + - [mwhs2_as, 58, MWHS2 ALL-SKY] + - [ssmt2, 59] + - [smap, 60] + - [tovs_ms, 61, TOVS MULTISENSOR] + - [cloud_r, 62, CLOUD REFLECTIVITY] + - [cloud_l, 63, CLOUD LIDAR] + - [satellite_lightning, 64, SATELLITE LIGHTNING] + - [geos_vis, 65, GEOS VIS] + - [oconv, 66] + - [mwts3_as, 67, MWTS3 All-sky] + - [giirs, 68] + - [test, 99] unset: - context: type: @@ -581,9 +645,6 @@ _field: &_field defaults: - vals: [pl] unset: - # - context: - # - type: ssd - # error: "levtype not alowded with type {type}" - context: stream: op: '!' @@ -594,25 +655,27 @@ _field: &_field - context: stream: [ssmi] flatten: false - type: enum + type: [enum, integer] values: - - [cat, category] - - [dp, depth] - - [layer] - - [al, abstract levels] - - [ml, model levels] - - [pl, pressure levels] - - [hl, height levels] - - [pt, potential temperature] - - [pv, potential vorticity] - - [sfc, surface] # sl ?? - - [sol, surface other (multi)levels] - - [wv, ocean wave] - - [o2d, ocean surface] - - [o3d, ocean model levels] + - [cat, category] + - [dp, depth] + - [layer] + - [al, abstract levels] + - [ml, model levels] + - [pl, pressure levels] + - [hl, height levels] + - [pt, potential temperature] + - [pv, potential vorticity] + - [sfc, surf, surface] # sl ?? + - [sol, surface other (multi)levels] + - [wv, ocean wave] + - [o2d, ocean surface] + - [o3d, ocean model levels] + levelist: category: data + aliases: [leve,level,levellist] multiple: true type: to-by-list-float by: 1 @@ -624,12 +687,6 @@ _field: &_field # - context: # levtype: [pl] # vals: [1000, 850, 700, 500, 400, 300] - # - context: - # - levtype: [sfc, o2d] - # error: "levelist not alowded with levtype {levtype}" - # - context: - # - type: ssd - # error: "levelist not alowded with type {type}" unset: - context: stream: @@ -669,9 +726,7 @@ _field: &_field - context: stream: [ssmi] - context: - type: [ob, fb, ai, af, ab, ofb, mfb, oai, sfb, fsoifb, fcdfb, tf] - # never: - # - type: [tf, ob] + type: [ob, fb, ai, af, ab, ofb, mfb, oai, sfb, fsoifb, fcdfb, tf, ofa] ################################################################# @@ -713,26 +768,23 @@ _field: &_field type: enum multiple: true values: - - [1, jan, January] - - [2, feb, February] - - [3, mar, March] - - [4, apr, April] - - [5, may, May] - - [6, jun, June] - - [7, jul, July] - - [8, aug, August] - - [9, sep, September] - - [10, oct, October] - - [11, nov, November] - - [12, dec, December] - - # verify - # refdate + - [1, jan, january] + - [2, feb, february] + - [3, mar, march] + - [4, apr, april] + - [5, may] + - [6, jun, june] + - [7, jul, july] + - [8, aug, august] + - [9, sep, september] + - [10, oct, october] + - [11, nov, november] + - [12, dec, december] hdate: category: data multiple: true - type: integer + type: date unset: - context: stream: @@ -766,7 +818,7 @@ _field: &_field - context: class: [dm] type: [fc] - val: 0 + vals: [0] unset: - context: type: [ab] @@ -812,8 +864,6 @@ _field: &_field op: '!' vals: [seap] - # range - step: category: data multiple: true @@ -846,6 +896,7 @@ _field: &_field anoffset: category: data + aliases: [an_offset] multiple: true type: integer unset: @@ -875,15 +926,13 @@ _field: &_field number: category: data multiple: true - aliases: - - ensemble type: to-by-list by: 1 - set: + defaults: - context: class: [ti, s2] type: [cf] - val: 0 + vals: [0] unset: - context: type: @@ -897,16 +946,13 @@ _field: &_field vals: [mofc, wamf, mofm, wmfm, seas, wasf, wamf, sfmm, smma, seap, swmm, ocea, mnfc, mnfh, mnfa, mnfw, mfhw, mfaw, mnfm, mfhm, mfam, mfwm, mhwm, mawm, mmsf, msmm, wams, mswm, mmsa, enda, ewda, edmm, edmo, ewmm, ewmo, elda, ewla, espd, mmaf, mmam, mmaw, mmwm, seas, efsr, wfsr, efse, wfse, ocda] - context: _verb: [retrieve, archive] + class: + op: '!' + vals: [ti, s2] type: [cf, em, es, ses, taem, taes] stream: op: '!' vals: [mofc, wamf, mofm, wmfm] - # only: - # - context: - # type: [pf, cr, cm, fcmean, fcmin, fcmax, fcstdev, sot, fc, wp, 4i, 4v] - # never: - # # This is to prevent number with type=fc and stream=oper - # - stream: [oper, wave] quantile: category: data @@ -923,51 +969,123 @@ _field: &_field domain: category: data defaults: - - vals: [g] - set: - context: - class: [od] - type: [cm, cs, cr] - domain: [g] - val: e - # - context: - # - dataset: [climate-dt] - # error: "domain not alowded with dataset {dataset}" - unset: + class: + op: '!' + vals: [ms] + vals: [g] + type: + - context: + class: [ms] + country: [it] + type: enum + values: + - [italy] + - [euroatl] + - [europe] + - [mediterranean] + - type: enum + set: + - context: + class: [od] + type: [cm, cs, cr] + domain: [g] + vals: [e] + # - context: + # - dataset: [climate-dt] + # error: "domain not alowded with dataset {dataset}" + unset: + - context: + class: [ep] + levtype: [o2d, o3d] + - context: + class: [d1, ng, ti, s2, ur, lw, rr, ed] + flatten: false + type: enum + values: + - [a, north west europe] + - [b, north east europe, baltic and black sea] + - [c, south west europe] + - [d, south east europe] + - [e, europe] + - [f, fastex] + - [g, globe, general european area] + - [h] + - [i] + - [j] + - [k] + - [l] + - [m, mediterranean] + - ['n', northern hemisphere] + - [o] + - [p] + - [q] + - [r] + - [s, southern hemisphere] + - [t, tropics] + - [u, tropics 2] + - [v] + - [w, western atlantic] + - [x] + - ['y'] + - [z] + + + bcmodel: + category: data + type: - context: - class: [ep] - levtype: [o2d, o3d] + class: [ms] + country: [it] + type: enum + values: + - [gme] + - [ifs] + + + icmodel: + category: data + type: enum + values: + - [gme] + - [ifs] + - [mvoi] + - [nudging] + - [3dvar] + only: - context: - class: [d1, ng, ti, s2, ur, lw, rr, ed] - flatten: false + class: [ms] + country: [it] + + country: + category: data + multiple: false + type: enum + values: + - [it] + - [de] + only: + - context: + class: [ms] + + + grib: + category: data + multiple: false type: enum + defaults: + - context: + class: [ms] + country: [it] + vals: [ecmwf] values: - - [a, north west europe] - - [b, north east europe, baltic and black sea] - - [c, south west europe] - - [d, south east europe] - - [e, europe] - - [f, fastex] - - [g, globe, general european area] - - [h] - - [i] - - [j] - - [k] - - [l] - - [m, mediterranean] - - ['n', northern hemisphere] - - [o] - - [p] - - [q] - - [r] - - [s, southern hemisphere] - - [t, tropics] - - [u, tropics 2] - - [v] - - [w, western atlantic] - - [x] - - ['y'] - - [z] + - [original] + - [ecmwf] + only: + - context: + class: [ms] + country: [it] + frequency: category: data @@ -1038,58 +1156,61 @@ _field: &_field multiple: true type: enum values: - - [aladinhuneps-omsz-eu] - - [aladinlaef-zamg-eu] - - [ammc, 1, melbourne] - - [anso] - - [aromeeps-mf-eu] - - [babj, 38, beijing] - - [cmcc] - - [cnmc, 80] - - [consensus, 255] - - [cosmodeeps-dwd-eu] - - [cosmoleps-arpasimc-eu] - - [crfc, 239, cerfacs] - - [cwao, 54, montreal] - - [dems] - - [ecmf, 98, ecmwf] - - [edzw, dwd, 78, offenbach] - - [egrr, 74, exeter, bracknell] - - [ekmi] - - [enmi, 88, oslo] - - [eswi] - - [fapr] - - [fnmo, fnmoc, 58, fleet numerical] - - [fr-ms-ec] - - [glameps-hirlamcons-eu] - - [hadc, 247, hadley centre] - - [hirlam-dmi-eu] - - [ifmk, 246] - - [ingv, 235] - - [isac] - - [knmi, 245] - - [kwbc, 7, washington] - - [lemm, 214, madrid] - - [lfpw, 84, 85, paris, toulouse] - - [lops] - - [mogreps-mo-eua] - - [nasa] - - [niwa] - - [no-ar-ce] - - [no-ar-cw] - - [no-ar-pa] - - [nzkl] - - [pearp-mf-eu] - - [rjtd, 34, tokyo] - - [rksl, 40, seoul] - - [rums] - - [sabm] - - [sbsj, 46, cptec] - - [se-al-ec] - - [sreps-aemet-eua] - - [srnwppeps-dwd-eua] - - [vabb] - - [vuwien, 244, university of vienna] + - [aladinhuneps-omsz-eu] + - [aladinlaef-zamg-eu] + - [ammc, 1, melbourne] + - [anso] + - [aromeeps-mf-eu] + - [babj, 38, beijing] + - [cmcc] + - [cnmc, 80] + - [consensus, 255] + - [cosmo] + - [cosmodeeps-dwd-eu] + - [cosmoleps-arpasimc-eu] + - [crfc, 239, cerfacs] + - [cwao, 54, montreal] + - [dems] + - [ecmf, 98, ecmwf] + - [ecmf_ea, ecmwf_ea] + - [ecmf_od, ecmwf_od] + - [edzw, dwd, 78, offenbach] + - [egrr, 74, exeter, bracknell] + - [ekmi] + - [enmi, 88, oslo] + - [eswi] + - [fapr] + - [fnmo, fnmoc, 58, fleet numerical] + - [fr-ms-ec] + - [glameps-hirlamcons-eu] + - [hadc, 247, hadley centre] + - [hirlam-dmi-eu] + - [ifmk, 246] + - [ingv, 235] + - [isac] + - [knmi, 245] + - [kwbc, 7, washington] + - [lemm, 214, madrid] + - [lfpw, 84, 85, paris, toulouse] + - [lops] + - [mogreps-mo-eua] + - [nasa] + - [niwa] + - [no-ar-ce] + - [no-ar-cw] + - [no-ar-pa] + - [nzkl] + - [pearp-mf-eu] + - [rjtd, 34, tokyo] + - [rksl, 40, seoul] + - [rums] + - [sabm] + - [sbsj, 46, cptec] + - [se-al-ec] + - [sreps-aemet-eua] + - [srnwppeps-dwd-eua] + - [vabb] + - [vuwien, 244, university of vienna] system: category: data @@ -1107,49 +1228,46 @@ _field: &_field category: data type: enum values: - - [cmip6, CMIP6, Coupled Model Intercomparison Project Phase 6] - - [scenariomip, ScenarioMIP, Scenario Model Intercomparison Project] - - [highresmip, HighResMIP, High Resolution Model Intercomparison Project] - - [story-nudging, Climate storylines by nudging to reanalysis] - - [baseline, Baseline simulations for climate model evaluation] - - [projections, Future climate projections] + - [cmip6, Coupled Model Intercomparison Project Phase 6] + - [scenariomip, Scenario Model Intercomparison Project] + - [highresmip, High Resolution Model Intercomparison Project] + - [story-nudging, Climate storylines by nudging to reanalysis] + - [baseline, Baseline simulations for climate model evaluation] + - [projections, Future climate projections] experiment: category: data type: enum values: - - [hist, Historical] - - [cont, Control] - - [amip, Atmospheric Model Intercomparison Project] - - [ssp1-1.9, SSP1-1.9, Shared Socio-economic Pathways 1-1.9] - - [ssp1-2.6, SSP1-2.6, Shared Socio-economic Pathways 1-2.6] - - [ssp2-4.5, SSP2-4.5, Shared Socio-economic Pathways 2-4.5] - - [ssp3-7.0, SSP3-7.0, Shared Socio-economic Pathways 3-7.0] - - [ssp5-8.5, SSP5-8.5, Shared Socio-economic Pathways 5-8.5] - - [tplus1.5k, Tplus1.5K, Warmer world at 1.5 degrees K above pre-industrial temperatures] - - [tplus2.0k, Tplus2.0K, Warmer world at 2.0 degrees K above pre-industrial temperatures] - - [tplus3.0k, Tplus3.0K, Warmer world at 3.0 degrees K above pre-industrial temperatures] - - [tplus4.0k, Tplus4.0K, Warmer world at 4.0 degrees K above pre-industrial temperatures] - - [abrupt4xco2, CO2 abruptly quadrupled and then held constant] - + - [hist, Historical] + - [cont, Control] + - [amip, Atmospheric Model Intercomparison Project] + - [ssp1-1.9, Shared Socio-economic Pathways 1-1.9] + - [ssp1-2.6, Shared Socio-economic Pathways 1-2.6] + - [ssp2-4.5, Shared Socio-economic Pathways 2-4.5] + - [ssp3-7.0, Shared Socio-economic Pathways 3-7.0] + - [ssp5-8.5, Shared Socio-economic Pathways 5-8.5] + - [tplus1.5k, Warmer world at 1.5 degrees K above pre-industrial temperatures] + - [tplus2.0k, Warmer world at 2.0 degrees K above pre-industrial temperatures] + - [tplus3.0k, Warmer world at 3.0 degrees K above pre-industrial temperatures] + - [tplus4.0k, Warmer world at 4.0 degrees K above pre-industrial temperatures] + - [abrupt4xco2, CO2 abruptly quadrupled and then held constant] generation: category: data type: integer - realization: category: data type: integer - resolution: category: data type: enum values: - - [standard, Standard resolution model output with longer availability] - - [high, High resolution model output with limited availability] + - [standard, Standard resolution model output with longer availability] + - [high, High resolution model output with limited availability] # - product # - section @@ -1164,11 +1282,11 @@ _observation: &_observation obstype: category: data - type: enum + type: [enum, integer] values: - - all - - [nsd, non satellite data all] - - [sd, satellite data all] + - all + - [nsd, non satellite data all] + - [sd, satellite data all] unset: - context: type: @@ -1233,17 +1351,17 @@ _postproc: &_postproc flatten: false type: [enum, integer] values: - - [av, archived value] - - ['n', normal, auto] - - [r, reduced] - - [l, low] + - [av, archived value] + - ['n', normal, auto] + - [r, reduced] + - [l, low] unset: - context: accuracy: ['n'] set: - context: accuracy: [l, r] - val: 8 + vals: [8] warn: "ACCURACY Low or Reduced force to 8 bits" bitmap: @@ -1256,15 +1374,15 @@ _postproc: &_postproc flatten: false type: enum values: - - [grib1, grib, gb, grib edition 1] - - [grib2, grib edition 2] - - [bufr, bf] - - [grid, gd] - - [netcdf] - - [odb] - - [ascii] - - [p, packed] - - [u, unpacked] + - [grib1, grib, gb, grib edition 1] + - [grib2, grib edition 2] + - [bufr, bf] + - [grid, gd] + - [netcdf] + - [odb] + - [ascii] + - [p, packed] + - [u, unpacked] unset: - context: format: [p] @@ -1277,8 +1395,8 @@ _postproc: &_postproc category: postproc type: enum values: - - reduced - - regular + - reduced + - regular area: category: postproc @@ -1286,8 +1404,12 @@ _postproc: &_postproc multiple: true type: [float, enum] values: - - ['off', g, global] - - [e, europe] + - ['off', g, global] + - [e, europe] + set: + - context: + area: [e] + vals: [73.5,-27,33,45] grid: category: postproc @@ -1295,38 +1417,38 @@ _postproc: &_postproc multiple: true type: [enum, regex, float] values: - - auto - - [av, archived value] - - [F16, 16] - - [F24, 24] - - [F32, 32] - - [F48, 48] - - [F64, 64] - - [F80, 80] - - [F96, 96] - - [F128, 128] - - [F160, 160] - - [F192, 192] - - [F200, 200] - - [F256, 256] - - [F320, 320] - - [F400, 400] - - [F512, 512] - - [F576, 576] - - [F640, 640] - - [F800, 800] - - [F912, 912] - - [F1024, 1024] - - [F1280, 1280] - - [F1600, 1600] - - [F2000, 2000] - - [F2560, 2560] - - [F4000, 4000] - - [F8000, 8000] + - auto + - [av, archived value] + - [F16, 16] + - [F24, 24] + - [F32, 32] + - [F48, 48] + - [F64, 64] + - [F80, 80] + - [F96, 96] + - [F128, 128] + - [F160, 160] + - [F192, 192] + - [F200, 200] + - [F256, 256] + - [F320, 320] + - [F400, 400] + - [F512, 512] + - [F576, 576] + - [F640, 640] + - [F800, 800] + - [F912, 912] + - [F1024, 1024] + - [F1280, 1280] + - [F1600, 1600] + - [F2000, 2000] + - [F2560, 2560] + - [F4000, 4000] + - [F8000, 8000] regex: - - '^[oOfF][1-9][0-9]*$' - - '^[nN](32|48|64|80|96|128|160|200|256|320|400|512|640|800|1024|1280|8000)$' - - '^[hH][rRnN]?(2|4|8|16|32|64|128|256|512|1024|2048|4096|8192)$' + - '^[oOfF][1-9][0-9]*$' + - '^[nN](32|48|64|80|96|128|160|200|256|320|400|512|640|800|1024|1280|8000)$' + - '^[hH][rRnN]?(2|4|8|16|32|64|128|256|512|1024|2048|4096|8192)$' uppercase: true unset: - context: @@ -1346,58 +1468,40 @@ _postproc: &_postproc flatten: false type: enum values: - - - linear - - - nearest-lsm - - nearest lsm - - - 'off' - - default - - any + - [linear] + - [bilinear] + - [nearest-lsm, nearest lsm] + - ['off', default, any] packing: category: postproc flatten: false type: enum values: - - [so, second order] - - ['off', av] - - [complex, co] - - [simple, si] - - ccsds + - [so, second order] + - ['off', av] + - [complex, co] + - [simple, si] + - [ccsds] resol: category: postproc flatten: false - aliases: - - tra type: [enum, integer] values: - - [av, archived value] - - [auto] - # - reduced gaussian 160 - defaults: - - context: - accuracy: - op: 'd' - vals: [auto] - - context: - grid: - op: 'd' - vals: [auto] - unset: - - context: - stream: - op: '!' - vals: [ssmi] - type: [im, sim, oldim] + - [av, archived value] + - [auto, automatic resolution] + - [N128, reduced gaussian 128] + - [N200, reduced gaussian 200] set: - context: style: [dissemination] - val: av + vals: [av] warn: "Force resol=av when style=dissemination" - context: style: [dissemination] resol: [auto] - val: av + vals: [av] warn: "Force resol=av when style=dissemination" @@ -1422,44 +1526,51 @@ _postproc: &_postproc flatten: false type: [enum, regex] values: - - 'off' - - auto - - N32 - - N48 - - N64 - - N80 - - N96 - - N128 - - N160 - - N192 - - N200 - - N256 - - N320 - - N400 - - N512 - - N640 - - N800 - - N912 - - N1024 - - N1280 + - 'off' + - auto + - N32 + - N48 + - N64 + - N80 + - N96 + - N128 + - N160 + - N192 + - N200 + - N256 + - N320 + - N400 + - N512 + - N640 + - N800 + - N912 + - N1024 + - N1280 regex: - - '^[oOfFhH][1-9][0-9]+$' + - '^[oOfFhH][1-9][0-9]+$' truncation: category: postproc flatten: false type: [enum, integer] values: - - auto - - 'off' + - auto + - 'off' + process: category: postproc flatten: false + defaults: + - context: + _verb: [retrieve] + class: [ti] + vals: [local] + default: type: enum values: - - local - - server + - local + - server ####################################################################### @@ -1487,6 +1598,14 @@ disseminate: requirements: type: any + resol: + category: postproc + type: any + + # repres: + # category: postproc + # type: any + day: category: postproc multiple: true @@ -1499,14 +1618,21 @@ disseminate: multiple: true type: enum values: - - bc - - monday - - tuesday - - wednesday - - thursday - - friday - - saturday - - sunday + - [frequent, f] + - [infrequent, i] + - [normal, n] + - compare + - [monthly run] + - intent + - disk + - [bc, boundary conditions] + - monday + - tuesday + - wednesday + - thursday + - friday + - saturday + - sunday option: default: normal @@ -1514,11 +1640,11 @@ disseminate: multiple: true type: enum values: - - normal - - delay - - asap - - gts - - opendata + - normal + - delay + - asap + - gts + - opendata compatibility: category: postproc @@ -1526,8 +1652,8 @@ disseminate: multiple: true type: enum values: - - 'off' - - 'no-local-extension' + - 'off' + - 'no-local-extension' priority: flatten: false @@ -1540,9 +1666,22 @@ disseminate: ############################################################## archive: + # _aliases: [a] + <<: *_field <<: *_observation + resol: + category: postproc + type: any + + # repres: + # category: postproc + # type: any + + password: + aliases: [pass] + type: any database: flatten: false @@ -1570,6 +1709,7 @@ archive: ############################################################## retrieve: + _aliases: [r, ret, retr] <<: *_field <<: *_observation @@ -1581,6 +1721,11 @@ retrieve: multiple: true type: any + source: + flatten: false + multiple: true + type: any + expect: flatten: false multiple: false @@ -1589,6 +1734,7 @@ retrieve: - any fieldset: + aliases: [field] flatten: false multiple: false type: any @@ -1596,7 +1742,16 @@ retrieve: database: flatten: false multiple: true + aliases: [dbase] type: any + set: + - context: + # _verb: [retrieve] + source: + op: 'd' + database: + op: 'u' + vals: [file] optimise: type: enum @@ -1611,7 +1766,7 @@ retrieve: type: enum defaults: - context: - # type: [mfb, ofb, ai] + # type: [mfb, ofb, ai, ofa] obsgroup: op: 'd' vals: [keep] @@ -1632,13 +1787,19 @@ retrieve: padding: flatten: false type: enum + defaults: + - context: + _verb: [retrieve] + class: [ti] + vals: [0] values: - - [0, none, n] - - [auto, automatic] + - [0, none, n] + - [auto, automatic] ############################################################## read: + # _aliases: [r] source: flatten: false multiple: true @@ -1655,6 +1816,7 @@ read: type: any fieldset: + aliases: [field] flatten: false multiple: false type: any @@ -1671,6 +1833,7 @@ read: ############################################################## get: + _aliases: [g] tape: flatten: false @@ -1690,6 +1853,7 @@ get: ############################################################## list: + _aliases: [l] <<: *_field <<: *_observation @@ -1705,17 +1869,20 @@ list: type: any _clear_defaults: [date, domain, expver, levelist, levtype, param, step, stream, time, type] + _multiple: [class, expver, stream, type] ############################################################## compute: + _aliases: [c] formula: flatten: false multiple: false type: any fieldset: + aliases: [field] flatten: false multiple: false type: any @@ -1723,8 +1890,10 @@ compute: ############################################################## write: + _aliases: [w] fieldset: + aliases: [field] flatten: false multiple: false type: any @@ -1736,6 +1905,7 @@ write: ############################################################## + pointdb: lat: multiple: false diff --git a/share/metkit/param-matching.yaml b/share/metkit/param-matching.yaml index d3956c4c..c7279701 100644 --- a/share/metkit/param-matching.yaml +++ b/share/metkit/param-matching.yaml @@ -13,3 +13,4 @@ wind: # list of tables used by ParamID normalisation to limit the param-table expansion to wind, ocean and reanalysis drop-tables: [140,150,151,160,162,170,180,190] full-table-dropping: true +ml-params-single-level: [22, 127, 128, 129, 152] diff --git a/src/metkit/hypercube/HyperCube.cc b/src/metkit/hypercube/HyperCube.cc index 41a03e29..afd43a0e 100644 --- a/src/metkit/hypercube/HyperCube.cc +++ b/src/metkit/hypercube/HyperCube.cc @@ -21,11 +21,6 @@ namespace metkit::hypercube { -static metkit::mars::Type& type(const std::string& name) { - static metkit::mars::MarsLanguage language("retrieve"); - return *language.type(name); -} - AxisOrder::AxisOrder() { eckit::Value axis = eckit::YAMLParser::decodeFile(axisYamlFile()); const eckit::Value axesNames = axis["axes"]; diff --git a/src/metkit/mars/ContextRule.h b/src/metkit/mars/ContextRule.h new file mode 100644 index 00000000..c55a3895 --- /dev/null +++ b/src/metkit/mars/ContextRule.h @@ -0,0 +1,20 @@ +/* + * (C) Copyright 2025- ECMWF. + * + * This software is licensed under the terms of the Apache Licence Version 2.0 + * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. + * In applying this licence, ECMWF does not waive the privileges and immunities + * granted to it by virtue of its status as an intergovernmental organisation nor + * does it submit to any jurisdiction. + */ + +#pragma once + +#include "metkit/mars/MarsRequest.h" + +namespace metkit::mars { + + +//---------------------------------------------------------------------------------------------------------------------- + +} // namespace metkit::mars diff --git a/src/metkit/mars/MarsExpansion.cc b/src/metkit/mars/MarsExpansion.cc index 994af8b4..40a8564a 100644 --- a/src/metkit/mars/MarsExpansion.cc +++ b/src/metkit/mars/MarsExpansion.cc @@ -54,10 +54,14 @@ std::vector MarsExpansion::expand(const std::vector result; result.reserve(requests.size()); + DummyContext cc; + MarsExpandContext& ctx = cc; + // Implement inheritence for (const auto& request : requests) { - auto& lang = language(request, request.verb()); - result.emplace_back(lang.expand(request, request, inherit_, strict_)); + auto& lang = language(ctx, request.verb()); + result.emplace_back(lang.expand(ctx, request, inherit_, strict_)); + ctx = request; } return result; diff --git a/src/metkit/mars/MarsLanguage.cc b/src/metkit/mars/MarsLanguage.cc index cb382f58..98aaff26 100644 --- a/src/metkit/mars/MarsLanguage.cc +++ b/src/metkit/mars/MarsLanguage.cc @@ -12,6 +12,7 @@ #include #include #include +#include #include "eckit/config/Resource.h" #include "eckit/log/JSON.h" @@ -37,13 +38,22 @@ static pthread_once_t once = PTHREAD_ONCE_INIT; static eckit::Value languages_; -static std::vector verbs_; +static std::set verbs_; +static std::map verbAliases_; static void init() { languages_ = eckit::YAMLParser::decodeFile(metkit::mars::MarsLanguage::languageYamlFile()); const eckit::Value verbs = languages_.keys(); for (size_t i = 0; i < verbs.size(); ++i) { - verbs_.push_back(verbs[i]); + verbs_.insert(verbs[i]); + eckit::Value lang = languages_[verbs[i]]; + if (lang.contains("_aliases")) { + eckit::Value aliases = lang["_aliases"]; + ASSERT(aliases.isList()); + for (size_t j = 0; j < aliases.size(); ++j) { + verbAliases_.emplace(aliases[j], verbs[i]); + } + } } } @@ -183,7 +193,8 @@ std::string MarsLanguage::bestMatch(const MarsExpandContext& ctx, const std::str size_t score = (fullMatch ? name.length() : 1); std::vector best; - static bool strict = eckit::Resource("$METKIT_LANGUAGE_STRICT_MODE", false); + + static bool strict = eckit::Resource("$METKIT_LANGUAGE_STRICT_MODE", true); for (size_t i = 0; i < values.size(); ++i) { @@ -296,13 +307,27 @@ std::string MarsLanguage::bestMatch(const MarsExpandContext& ctx, const std::str std::string MarsLanguage::expandVerb(const MarsExpandContext& ctx, const std::string& verb) { pthread_once(&once, init); - return bestMatch(ctx, verb, verbs_, true, true, false); + std::string v = eckit::StringTools::lower(verb); + auto vv = verbs_.find(v); + if (vv != verbs_.end()) { + return v; + } + auto aa = verbAliases_.find(v); + if (aa != verbAliases_.end()) { + return aa->second; + } + + std::ostringstream oss; + oss << "Verb " << v << " is not supported"; + throw eckit::UserError(oss.str()); } class TypeHidden : public Type { - virtual bool flatten() const { return false; } - virtual void print(std::ostream& out) const { out << "TypeHidden"; } - virtual bool expand(const MarsExpandContext& ctx, std::string& value) const { return true; } + bool flatten() const override { return false; } + void print(std::ostream& out) const override { out << "TypeHidden"; } + bool expand(const MarsExpandContext& ctx, const MarsRequest& /* request */, std::string& value) const override { + return true; + } public: @@ -328,38 +353,57 @@ MarsRequest MarsLanguage::expand(const MarsExpandContext& ctx, const MarsRequest MarsRequest result(verb_); try { - std::vector params = r.params(); - std::set seen; - - for (std::vector::iterator j = params.begin(); j != params.end(); ++j) { - std::string p; - + std::vector> sortedParams; + std::unordered_map paramSet; + std::vector params; - std::map::iterator c = cache_.find(*j); + for (const auto& PP : r.params()) { + auto c = cache_.find(PP); if (c != cache_.end()) { - p = (*c).second; + paramSet.emplace((*c).second, PP); } else { - p = cache_[*j] = bestMatch(ctx, *j, keywords_, true, false, false, aliases_); + std::string p = eckit::StringTools::lower(PP); + paramSet.emplace(cache_[p] = bestMatch(ctx, p, keywords_, true, false, true, aliases_), PP); } + } + + { // reorder the parameters, following the AxisOrder + // sort params by axisOrder + for (const auto& k : metkit::hypercube::AxisOrder::instance().axes()) { + auto it = paramSet.find(k); + if (it != paramSet.end()) { + sortedParams.emplace_back(k, it->second); + paramSet.erase(it); + } + } + for (const auto& [k, PP] : paramSet) { + sortedParams.emplace_back(k, PP); + } + } - std::vector values = r.values(*j); + for (const auto& [p, PP] : sortedParams) { + std::vector values = r.values(PP); if (values.size() == 1) { - const std::string& s = values[0]; - if (s == "off" || s == "OFF") { + const std::string& s = eckit::StringTools::lower(values[0]); + if (s == "off") { result.unsetValues(p); - type(p)->clearDefaults(); + type(p)->reset(); + continue; + } + if (s == "all" && type(p)->multiple()) { + result.setValue(p, "all"); continue; } } - type(p)->expand(ctx, values); - result.setValuesTyped(type(p), values); - type(p)->check(ctx, values); + auto t = type(p); + t->expand(ctx, result, values); + result.setValuesTyped(t, values); + t->check(ctx, values); } - if (inherit) { for (const auto& [k, t] : typesByAxisOrder_) { if (t != nullptr && result.countValues(k) == 0) { @@ -379,8 +423,9 @@ MarsRequest MarsLanguage::expand(const MarsExpandContext& ctx, const MarsRequest type(*k)->pass2(ctx, result); } - for (std::vector::const_iterator k = params.begin(); k != params.end(); ++k) { - type(*k)->finalise(ctx, result, strict); + for (const auto& [k, t] : typesByAxisOrder_) { + if (t != nullptr) + t->finalise(ctx, result, strict); } } catch (std::exception& e) { diff --git a/src/metkit/mars/MarsRequest.cc b/src/metkit/mars/MarsRequest.cc index eaa23a0d..cc85938e 100644 --- a/src/metkit/mars/MarsRequest.cc +++ b/src/metkit/mars/MarsRequest.cc @@ -19,6 +19,7 @@ #include "metkit/mars/MarsExpansion.h" #include "metkit/mars/MarsParser.h" #include "metkit/mars/MarsRequest.h" +#include "metkit/mars/ParamID.h" #include "metkit/mars/TypeAny.h" @@ -326,8 +327,43 @@ void MarsRequest::getParams(std::vector& p) const { size_t MarsRequest::count() const { size_t result = 1; - for (std::list::const_iterator i = params_.begin(); i != params_.end(); ++i) { - result *= (*i).count(); + + const std::set& paramIdsSingleLevel = ParamID::getMlParamsSingleLevel(); + + bool ml = false; + size_t levels = 1; + size_t params = 0; + size_t paramsSingleLevel = 0; + + for (const auto& p : params_) { + if (p.values().size() == 1 && (p.values().at(0) == "all" || p.values().at(0) == "any")) { + return 0; + } + if (p.name() == "levelist") { + levels = p.values().size(); + } + else { + if (p.name() == "param") { + for (const auto& v : p.values()) { + paramsSingleLevel += paramIdsSingleLevel.count(v); + } + params = p.values().size() - paramsSingleLevel; + } + else { + if (p.name() == "levtype") { + ml = std::find(p.values().begin(), p.values().end(), "ml") != p.values().end(); + } + result *= p.count(); + } + } + } + if ((params + paramsSingleLevel) > 0) { + if (ml) { + result *= (levels * params + paramsSingleLevel); + } + else { + result *= (levels * (params + paramsSingleLevel)); + } } return result; } diff --git a/src/metkit/mars/ParamID.cc b/src/metkit/mars/ParamID.cc index 7146b5c3..2fa5ef40 100644 --- a/src/metkit/mars/ParamID.cc +++ b/src/metkit/mars/ParamID.cc @@ -32,6 +32,8 @@ static std::vector dropTables_; static bool fullTableDropping_; +static std::set mlParamsSingleLevel_; + //---------------------------------------------------------------------------------------------------------------------- @@ -63,6 +65,12 @@ static void readTable() { ASSERT(fullTableDropping.isBool()); fullTableDropping_ = fullTableDropping; } + + const eckit::Value mlParamsSingleLevel = paramMatching["ml-params-single-level"]; + ASSERT(mlParamsSingleLevel.isList()); + for (size_t i = 0; i < mlParamsSingleLevel.size(); ++i) { + mlParamsSingleLevel_.insert(mlParamsSingleLevel[i]); + } } const std::vector& ParamID::getWindFamilies() { @@ -73,6 +81,10 @@ const std::vector& ParamID::getDropTables() { pthread_once(&once, readTable); return dropTables_; } +const std::set& ParamID::getMlParamsSingleLevel() { + pthread_once(&once, readTable); + return mlParamsSingleLevel_; +} bool ParamID::fullTableDropping() { pthread_once(&once, readTable); diff --git a/src/metkit/mars/ParamID.h b/src/metkit/mars/ParamID.h index cf1a78e5..61beb298 100644 --- a/src/metkit/mars/ParamID.h +++ b/src/metkit/mars/ParamID.h @@ -58,6 +58,7 @@ class ParamID { static const std::vector& getWindFamilies(); static const std::vector& getDropTables(); static bool fullTableDropping(); + static const std::set& getMlParamsSingleLevel(); }; //---------------------------------------------------------------------------------------------------------------------- diff --git a/src/metkit/mars/Parameter.cc b/src/metkit/mars/Parameter.cc index 8710b58a..d73b8959 100644 --- a/src/metkit/mars/Parameter.cc +++ b/src/metkit/mars/Parameter.cc @@ -24,7 +24,7 @@ class UndefinedType : public Type { void print(std::ostream& out) const override { out << ""; } bool filter(const std::vector&, std::vector&) const override { NOTIMP; } - bool expand(const MarsExpandContext&, std::string&) const override { NOTIMP; } + bool expand(const MarsExpandContext&, const MarsRequest& request, std::string&) const override { NOTIMP; } public: diff --git a/src/metkit/mars/Type.cc b/src/metkit/mars/Type.cc index 53b27458..fdb6aa2f 100644 --- a/src/metkit/mars/Type.cc +++ b/src/metkit/mars/Type.cc @@ -24,9 +24,7 @@ #include "eckit/exception/Exceptions.h" #include "eckit/value/Value.h" -#include "metkit/mars/MarsExpandContext.h" -#include "metkit/mars/MarsRequest.h" - +#include "metkit/mars/ContextRule.h" #include "metkit/mars/MarsExpandContext.h" #include "metkit/mars/MarsRequest.h" #include "metkit/mars/TypeToByList.h" @@ -35,17 +33,8 @@ namespace metkit::mars { //---------------------------------------------------------------------------------------------------------------------- -ContextRule::ContextRule(const std::string& k) : key_(k) {} - -std::ostream& operator<<(std::ostream& s, const ContextRule& r) { - r.print(s); - return s; -} - -//---------------------------------------------------------------------------------------------------------------------- - -void Context::add(ContextRule* rule) { - rules_.emplace_back(rule); +void Context::add(std::unique_ptr rule) { + rules_.push_back(std::move(rule)); } bool Context::matches(MarsRequest req) const { @@ -73,87 +62,10 @@ void Context::print(std::ostream& out) const { out << "]"; } -//---------------------------------------------------------------------------------------------------------------------- - -class Include : public ContextRule { -public: - - Include(const std::string& k, const std::set& vv) : ContextRule(k), vals_(vv) {} - - bool matches(MarsRequest req) const override { - if (!req.has(key_)) { - return false; - } - for (const std::string& v : req.values(key_)) { - if (vals_.find(v) != vals_.end()) { - return true; - } - } - return false; - } - -private: // methods - - void print(std::ostream& out) const override { out << "Include[key=" << key_ << ",vals=[" << vals_ << "]]"; } - -private: - - std::set vals_; -}; - -class Exclude : public ContextRule { -public: - - Exclude(const std::string& k, const std::set& vv) : ContextRule(k), vals_(vv) {} - bool matches(MarsRequest req) const override { - if (!req.has(key_)) { - return false; - } - for (const std::string& v : req.values(key_)) { - if (vals_.find(v) != vals_.end()) { - return false; - } - } - return true; - } - -private: // methods - - void print(std::ostream& out) const override { out << "Exclude[key=" << key_ << ",vals=[" << vals_ << "]]"; } - -private: - - std::set vals_; -}; - -class Undef : public ContextRule { -public: - - Undef(const std::string& k) : ContextRule(k) {} - bool matches(MarsRequest req) const override { return !req.has(key_); } - -private: // methods - - void print(std::ostream& out) const override { out << "Undef[key=" << key_ << "]"; } -}; - -class Def : public ContextRule { -public: - - Def(const std::string& k) : ContextRule(k) {} - bool matches(MarsRequest req) const override { return req.has(key_); } - -private: // methods - - void print(std::ostream& out) const override { out << "Def[key=" << key_ << "]"; } -}; - //---------------------------------------------------------------------------------------------------------------------- // HELPERS -namespace { - -ContextRule* parseRule(std::string key, eckit::Value r) { +std::unique_ptr parseRule(std::string key, eckit::Value r) { std::set vals; @@ -161,7 +73,7 @@ ContextRule* parseRule(std::string key, eckit::Value r) { for (size_t k = 0; k < r.size(); k++) { vals.insert(r[k]); } - return new Include(key, vals); + return std::make_unique(key, vals); } ASSERT(r.contains("op")); @@ -169,36 +81,33 @@ ContextRule* parseRule(std::string key, eckit::Value r) { ASSERT(op.size() == 1); switch (op[0]) { case 'u': - return new Undef(key); + return std::make_unique(key); case 'd': - return new Def(key); + return std::make_unique(key); case '!': ASSERT(r.contains("vals")); eckit::Value vv = r["vals"]; for (size_t k = 0; k < vv.size(); k++) { vals.insert(vv[k]); } - return new Exclude(key, vals); + return std::make_unique(key, vals); } return nullptr; } -Context* parseContext(eckit::Value c) { +std::unique_ptr Context::parseContext(eckit::Value c) { - Context* context = new Context{}; + std::unique_ptr context = std::make_unique(); eckit::Value keys = c.keys(); for (size_t j = 0; j < keys.size(); j++) { std::string key = keys[j]; - ContextRule* r = parseRule(key, c[key]); - context->add(r); + context->add(parseRule(key, c[key])); } return context; } -} // namespace - //---------------------------------------------------------------------------------------------------------------------- Type::Type(const std::string& name, const eckit::Value& settings) : @@ -239,14 +148,12 @@ Type::Type(const std::string& name, const eckit::Value& settings) : vals.push_back(vv); } - Context* context = nullptr; if (d.contains("context")) { - context = parseContext(d["context"]); + defaults_.emplace(Context::parseContext(d["context"]), vals); } else { - context = new Context; + defaults_.emplace(std::make_unique(), vals); } - defaults_.emplace(context, vals); } } } @@ -256,8 +163,7 @@ Type::Type(const std::string& name, const eckit::Value& settings) : for (size_t i = 0; i < only.size(); i++) { eckit::Value o = only[i]; ASSERT(o.contains("context")); - Context* c = parseContext(o["context"]); - only_.emplace(c); + only_.insert(Context::parseContext(o["context"])); } } } @@ -266,10 +172,19 @@ Type::Type(const std::string& name, const eckit::Value& settings) : if (!sets.isNil() && sets.isList()) { for (size_t i = 0; i < sets.size(); i++) { eckit::Value s = sets[i]; - ASSERT(s.contains("val")); - eckit::Value val = s["val"]; + std::vector vals; + ASSERT(s.contains("vals")); + eckit::Value vv = s["vals"]; + if (vv.isList()) { + for (size_t k = 0; k < vv.size(); k++) { + vals.push_back(vv[k]); + } + } + else { + vals.push_back(vv); + } ASSERT(s.contains("context")); - sets_.emplace(parseContext(s["context"]), val); + sets_.emplace(Context::parseContext(s["context"]), vals); } } } @@ -279,8 +194,7 @@ Type::Type(const std::string& name, const eckit::Value& settings) : for (size_t i = 0; i < unsets.size(); i++) { eckit::Value u = unsets[i]; ASSERT(u.contains("context")); - Context* c = parseContext(u["context"]); - unsets_.emplace(c); + unsets_.insert(Context::parseContext(u["context"])); } } } @@ -350,39 +264,39 @@ std::ostream& operator<<(std::ostream& s, const Type& x) { } -std::string Type::tidy(const MarsExpandContext& ctx, const std::string& value) const { +std::string Type::tidy(const MarsExpandContext& ctx, const MarsRequest& request, const std::string& value) const { std::string result = value; - expand(ctx, result); + expand(ctx, request, result); return result; } -std::string Type::tidy(const std::string& value) const { +std::string Type::tidy(const MarsRequest& request, const std::string& value) const { DummyContext ctx; - return tidy(ctx, value); + return tidy(ctx, request, value); } -std::vector Type::tidy(const std::vector& values) const { +std::vector Type::tidy(const MarsRequest& request, const std::vector& values) const { DummyContext ctx; std::vector result; result.reserve(values.size()); std::transform(values.begin(), values.end(), std::back_inserter(result), - [this, ctx](const std::string& s) { return this->tidy(ctx, s); }); + [this, ctx, request](const std::string& s) { return this->tidy(ctx, request, s); }); return result; } -bool Type::expand(const MarsExpandContext&, std::string& value) const { +bool Type::expand(const MarsExpandContext&, const MarsRequest& request, std::string& value) const { std::ostringstream oss; oss << *this << ": expand not implemented (" << value << ")"; throw eckit::SeriousBug(oss.str()); } -void Type::expand(const MarsExpandContext& ctx, std::vector& values) const { +void Type::expand(const MarsExpandContext& ctx, const MarsRequest& request, std::vector& values) const { if (toByList_ && values.size() > 1) { - toByList_->expandRanges(ctx, values); + toByList_->expandRanges(ctx, request, values); } std::vector newvals; @@ -391,7 +305,7 @@ void Type::expand(const MarsExpandContext& ctx, std::vector& values for (const std::string& val : values) { std::string value = val; - if (!expand(ctx, value)) { + if (!expand(ctx, request, value)) { std::ostringstream oss; oss << *this << ": cannot expand '" << val << "'" << ctx; throw eckit::UserError(oss.str()); @@ -472,40 +386,44 @@ void Type::finalise(const MarsExpandContext& ctx, MarsRequest& request, bool str request.unsetValues(name_); } else { - bool matches = (only_.size() == 0); - for (const auto& context : only_) { - if (context->matches(request)) { - matches = true; - break; - } - } - if (!matches) { - std::ostringstream oss; - oss << *this << ": Key [" << name_ << "] not acceptable with contextes: " << std::endl; + if (values.size() > 0) { + bool matches = (only_.size() == 0); for (const auto& context : only_) { - oss << " " << *context << std::endl; + if (context->matches(request)) { + matches = true; + break; + } } - throw eckit::UserError(oss.str()); - } - for (const auto& context : unsets_) { - if (context->matches(request)) { - if (strict && request.has(name_)) { - std::ostringstream oss; - oss << *this << ": Key [" << name_ << "] not acceptable with context: " << *context; - throw eckit::UserError(oss.str()); + if (!matches) { + std::ostringstream oss; + oss << *this << ": Key [" << name_ << "] not acceptable with contextes: " << std::endl; + for (const auto& context : only_) { + oss << " " << *context << std::endl; + } + throw eckit::UserError(oss.str()); + } + for (const auto& context : unsets_) { + if (context->matches(request)) { + if (strict && request.has(name_)) { + std::ostringstream oss; + oss << *this << ": Key [" << name_ << "] not acceptable with context: " << *context; + throw eckit::UserError(oss.str()); + } + request.unsetValues(name_); } - request.unsetValues(name_); } } - for (const auto& [context, value] : sets_) { - if (context->matches(request)) { - if (strict && !request.has(name_)) { - std::ostringstream oss; - oss << *this << ": missing Key [" << name_ << "] - required with context: " << *context; - throw eckit::UserError(oss.str()); + if (request.verb() != "list") { + for (const auto& [context, values] : sets_) { + if (context->matches(request)) { + if (strict && !request.has(name_)) { + std::ostringstream oss; + oss << *this << ": missing Key [" << name_ << "] - required with context: " << *context; + throw eckit::UserError(oss.str()); + } + request.setValuesTyped(this, values); } - request.setValuesTyped(this, std::vector{value}); } } } diff --git a/src/metkit/mars/Type.h b/src/metkit/mars/Type.h index df34fcd8..169196a9 100644 --- a/src/metkit/mars/Type.h +++ b/src/metkit/mars/Type.h @@ -26,21 +26,29 @@ #include "eckit/memory/Counted.h" #include "eckit/value/Value.h" +#include "metkit/mars/MarsRequest.h" + namespace metkit::mars { -class MarsRequest; class MarsExpandContext; +//---------------------------------------------------------------------------------------------------------------------- + +/// @brief abstract class - ContextRule subclasses are used to define a context. A MarsRequest matches a context, if it +/// matches all its ContextRules class ContextRule { public: - ContextRule(const std::string& k); + ContextRule(const std::string& k) : key_(k) {} virtual ~ContextRule() = default; virtual bool matches(MarsRequest req) const = 0; - friend std::ostream& operator<<(std::ostream& s, const ContextRule& x); + friend std::ostream& operator<<(std::ostream& s, const ContextRule& r) { + r.print(s); + return s; + } protected: @@ -51,11 +59,102 @@ class ContextRule { virtual void print(std::ostream& out) const = 0; }; +//---------------------------------------------------------------------------------------------------------------------- + +/// @brief A MarsRequest matches an Include ContextRule if at least one of the mars request values matches with the +/// values associated with the Include rule +class Include : public ContextRule { +public: + + Include(const std::string& k, const std::set& vv) : ContextRule(k), vals_(vv) {} + + bool matches(MarsRequest req) const override { + if (key_ == "_verb") { + return (vals_.find(req.verb()) != vals_.end()); + } + if (!req.has(key_)) { + return false; + } + for (const std::string& v : req.values(key_)) { + if (vals_.find(v) != vals_.end()) { + return true; + } + } + return false; + } + +private: // methods + + void print(std::ostream& out) const override { out << "Include[key=" << key_ << ",vals=[" << vals_ << "]]"; } + +private: + + std::set vals_; +}; + +/// @brief A MarsRequest matches an Exclude ContextRule if none of the mars request values matches with the values +/// associated with the Exclude rule +class Exclude : public ContextRule { +public: + + Exclude(const std::string& k, const std::set& vv) : ContextRule(k), vals_(vv) {} + bool matches(MarsRequest req) const override { + if (!req.has(key_)) { + return false; + } + for (const std::string& v : req.values(key_)) { + if (vals_.find(v) != vals_.end()) { + return false; + } + } + return true; + } + +private: // methods + + void print(std::ostream& out) const override { out << "Exclude[key=" << key_ << ",vals=[" << vals_ << "]]"; } + +private: + + std::set vals_; +}; + +/// @brief A MarsRequest matches an Undef ContextRule if the specified keyword is not defined in the mars request +class Undef : public ContextRule { +public: + + Undef(const std::string& k) : ContextRule(k) {} + bool matches(MarsRequest req) const override { return !req.has(key_); } + +private: // methods + + void print(std::ostream& out) const override { out << "Undef[key=" << key_ << "]"; } +}; + +/// @brief A MarsRequest matches an Undef ContextRule if the specified keyword is defined in the mars request +class Def : public ContextRule { +public: + + Def(const std::string& k) : ContextRule(k) {} + bool matches(MarsRequest req) const override { return req.has(key_); } + +private: // methods + + void print(std::ostream& out) const override { out << "Def[key=" << key_ << "]"; } +}; + + +//---------------------------------------------------------------------------------------------------------------------- + +/// @brief a Context contains a list of ContextRule. A MarsRequest matches a context, if it matches all the ContextRules +/// associated class Context { public: + static std::unique_ptr parseContext(eckit::Value c); + /// @note takes ownership of the rule - void add(ContextRule* rule); + void add(std::unique_ptr rule); bool matches(MarsRequest req) const; @@ -75,8 +174,9 @@ class Context { class ITypeToByList { public: - virtual ~ITypeToByList() = default; - virtual void expandRanges(const MarsExpandContext& ctx, std::vector& values) const = 0; + virtual ~ITypeToByList() = default; + virtual void expandRanges(const MarsExpandContext& ctx, const MarsRequest& request, + std::vector& values) const = 0; }; //---------------------------------------------------------------------------------------------------------------------- @@ -88,12 +188,13 @@ class Type : public eckit::Counted { ~Type() noexcept override = default; - virtual void expand(const MarsExpandContext& ctx, std::vector& values) const; - virtual bool expand(const MarsExpandContext& ctx, std::string& value) const; + virtual void expand(const MarsExpandContext& ctx, const MarsRequest& request, + std::vector& values) const; + virtual bool expand(const MarsExpandContext& ctx, const MarsRequest& request, std::string& value) const; - std::string tidy(const MarsExpandContext& ctx, const std::string& value) const; - std::string tidy(const std::string& value) const; - std::vector tidy(const std::vector& values) const; + std::string tidy(const MarsExpandContext& ctx, const MarsRequest& request, const std::string& value) const; + std::string tidy(const MarsRequest& request, const std::string& value) const; + std::vector tidy(const MarsRequest& request, const std::vector& values) const; virtual void setDefaults(MarsRequest& request); virtual void setInheritance(const std::vector& inheritance); @@ -132,7 +233,7 @@ class Type : public eckit::Counted { std::map, std::vector> defaults_; std::optional> inheritance_; std::set> only_; - std::map, std::string> sets_; + std::map, std::vector> sets_; std::set> unsets_; std::unique_ptr toByList_; diff --git a/src/metkit/mars/TypeAny.cc b/src/metkit/mars/TypeAny.cc index 4020fd92..a6cd62c9 100644 --- a/src/metkit/mars/TypeAny.cc +++ b/src/metkit/mars/TypeAny.cc @@ -24,7 +24,8 @@ void TypeAny::print(std::ostream& out) const { out << "TypeAny[name=" << name_ << "]"; } -bool TypeAny::expand(const MarsExpandContext& ctx, std::string& value) const { +bool TypeAny::expand(const MarsExpandContext& /* ctx */, const MarsRequest& /* request */, + std::string& /* value */) const { return true; } diff --git a/src/metkit/mars/TypeAny.h b/src/metkit/mars/TypeAny.h index 08eb4a15..8ff3f559 100644 --- a/src/metkit/mars/TypeAny.h +++ b/src/metkit/mars/TypeAny.h @@ -32,7 +32,7 @@ class TypeAny : public Type { private: // methods virtual void print(std::ostream& out) const override; - virtual bool expand(const MarsExpandContext& ctx, std::string& value) const override; + virtual bool expand(const MarsExpandContext& ctx, const MarsRequest& request, std::string& value) const override; }; //---------------------------------------------------------------------------------------------------------------------- diff --git a/src/metkit/mars/TypeDate.cc b/src/metkit/mars/TypeDate.cc index d5351570..b93e6e42 100644 --- a/src/metkit/mars/TypeDate.cc +++ b/src/metkit/mars/TypeDate.cc @@ -30,19 +30,26 @@ namespace { static std::array months{"jan", "feb", "mar", "apr", "may", "jun", "jul", "aug", "sep", "oct", "nov", "dec"}; -int month(const std::string& value) { - if (value.size() == 3) { - const auto* it = std::find(months.begin(), months.end(), eckit::StringTools::lower(value)); - if (it == months.end()) { +std::string month(const std::string& value) { + if (std::isdigit(value[0])) { + eckit::Translator s2i; + int m = s2i(value); + if (m > 12) { std::ostringstream oss; - oss << value << " is not a valid month short name"; + oss << value << " is not a valid month"; throw eckit::BadValue(oss.str()); } - return it - months.begin() + 1; + return months[m - 1]; } - eckit::Translator s2i; - return s2i(value); + ASSERT(value.size() >= 3); + const auto* it = std::find(months.begin(), months.end(), eckit::StringTools::lower(value.substr(0, 3))); + if (it == months.end()) { + std::ostringstream oss; + oss << value << " is not a valid month name"; + throw eckit::BadValue(oss.str()); + } + return *it; } long day(std::string& value) { @@ -61,11 +68,16 @@ long day(std::string& value) { eckit::Tokenizer t("-"); std::vector tokens = t.tokenize(value); - if (tokens.size() == 2) { // month-day (i.e. TypeClimateDaily) - int m = month(tokens[0]); - return s2l(tokens[1]); + if (tokens.size() == 2) { + if (std::isdigit(tokens[0][0]) && tokens[0].size() > 2) { // year-dayOfYear (e.g. 2018-23 ==> 20180123) + eckit::Date d(s2l(tokens[0]), s2l(tokens[1])); + return d.day(); + } + else { // month-day (i.e. TypeClimateDaily) + return s2l(tokens[1]); + } } - if (tokens.size() == 1 && tokens[0].size() <= 3) { // month (i.e. TypeClimateMonthly) + if (tokens.size() == 1 && (!std::isdigit(value[0]) || value.size() <= 2)) { // month (i.e. TypeClimateMonthly) return -1; } eckit::Date date(value); @@ -115,11 +127,11 @@ TypeDate::TypeDate(const std::string& name, const eckit::Value& settings) : Type void TypeDate::pass2(const MarsExpandContext& ctx, MarsRequest& request) { std::vector values = request.values(name_, true); - Type::expand(ctx, values); + Type::expand(ctx, request, values); request.setValuesTyped(this, values); } -bool TypeDate::expand(const MarsExpandContext& ctx, std::string& value) const { +bool TypeDate::expand(const MarsExpandContext& ctx, const MarsRequest& /* request */, std::string& value) const { if (!value.empty()) { eckit::Translator s2l; eckit::Translator l2s; @@ -134,16 +146,23 @@ bool TypeDate::expand(const MarsExpandContext& ctx, std::string& value) const { eckit::Tokenizer t("-"); std::vector tokens = t.tokenize(value); - if (tokens.size() == 2) { // month-day (i.e. TypeClimateDaily) - int m = month(tokens[0]); - long d = s2l(tokens[1]); + if (tokens.size() == 2) { // month-day (i.e. TypeClimateDaily) + if (std::isdigit(tokens[0][0]) && tokens[0].size() > 2) { // year-dayOfYear (e.g. 2018-23 ==> 20180123) + eckit::Date d(s2l(tokens[0]), s2l(tokens[1])); + value = l2s(d.yyyymmdd()); + } + else { // month-day (i.e. TypeClimateDaily) + + std::string m = month(tokens[0]); + long d = s2l(tokens[1]); - value = l2s(100 * m + d); + value = m + "-" + l2s(d); + } } else { - if (tokens.size() == 1 && tokens[0].size() <= 3) { // month (i.e. TypeClimateMonthly) - int m = month(tokens[0]); - value = l2s(m); + if (tokens.size() == 1 && + (!std::isdigit(value[0]) || value.size() <= 2)) { // month (i.e. TypeClimateMonthly) + value = month(tokens[0]); } else { eckit::Date date(value); @@ -163,4 +182,4 @@ static TypeBuilder type("date"); //---------------------------------------------------------------------------------------------------------------------- -} // namespace metkit::mars +} // namespace metkit::mars \ No newline at end of file diff --git a/src/metkit/mars/TypeDate.h b/src/metkit/mars/TypeDate.h index 335543ce..21004405 100644 --- a/src/metkit/mars/TypeDate.h +++ b/src/metkit/mars/TypeDate.h @@ -34,7 +34,7 @@ class TypeDate : public Type { virtual void print(std::ostream& out) const override; virtual void pass2(const MarsExpandContext& ctx, MarsRequest& request) override; - bool expand(const MarsExpandContext& ctx, std::string& value) const override; + bool expand(const MarsExpandContext& ctx, const MarsRequest& request, std::string& value) const override; }; //---------------------------------------------------------------------------------------------------------------------- diff --git a/src/metkit/mars/TypeEnum.cc b/src/metkit/mars/TypeEnum.cc index 10252296..ef0b9c8a 100644 --- a/src/metkit/mars/TypeEnum.cc +++ b/src/metkit/mars/TypeEnum.cc @@ -10,6 +10,7 @@ #include "eckit/parser/JSONParser.h" +#include "eckit/utils/StringTools.h" #include "metkit/config/LibMetkit.h" #include "metkit/mars/MarsLanguage.h" @@ -27,6 +28,10 @@ TypeEnum::TypeEnum(const std::string& name, const eckit::Value& settings) : Type LOG_DEBUG_LIB(LibMetkit) << "TypeEnum name=" << name << " settings=" << settings << std::endl; eckit::Value values = settings["values"]; + bool uppercase = false; + if (settings.contains("uppercase")) { + uppercase = settings["uppercase"]; + } if (!values.isList()) { values = MarsLanguage::jsonFile(values); @@ -42,13 +47,17 @@ TypeEnum::TypeEnum(const std::string& name, const eckit::Value& settings) : Type ASSERT(val.size() > 0); std::string first = val[0]; + if (uppercase) { + first = eckit::StringTools::upper(first); + } for (size_t j = 0; j < val.size(); ++j) { - std::string v = val[j]; + std::string VV = val[j]; + std::string v = eckit::StringTools::lower(VV); // LOG_DEBUG_LIB(LibMetkit) << "v[" << j << "] : " << v << std::endl; if (mapping_.find(v) != mapping_.end()) { std::ostringstream oss; - oss << "Redefined enum '" << v << "', '" << first << "' and '" << mapping_[v] << "'"; + oss << "Redefined enum '" << VV << "', '" << first << "' and '" << mapping_[v] << "'"; throw eckit::SeriousBug(oss.str()); } @@ -57,13 +66,17 @@ TypeEnum::TypeEnum(const std::string& name, const eckit::Value& settings) : Type } } else { - std::string v = val; + std::string VV = val; + if (uppercase) { + VV = eckit::StringTools::upper(VV); + } + std::string v = eckit::StringTools::lower(VV); if (mapping_.find(v) != mapping_.end()) { std::ostringstream oss; - oss << "Redefined enum '" << v << "' and '" << mapping_[v] << "'"; + oss << "Redefined enum '" << VV << "' and '" << mapping_[v] << "'"; throw eckit::SeriousBug(oss.str()); } - mapping_[v] = v; + mapping_[v] = VV; values_.push_back(v); } } @@ -74,21 +87,22 @@ void TypeEnum::print(std::ostream& out) const { out << "TypeEnum[name=" << name_ << "]"; } -bool TypeEnum::expand(const MarsExpandContext& ctx, std::string& value) const { - std::map::iterator c = cache_.find(value); +bool TypeEnum::expand(const MarsExpandContext& ctx, const MarsRequest& /* request */, std::string& value) const { + std::string val = eckit::StringTools::lower(value); + std::map::iterator c = cache_.find(val); if (c != cache_.end()) { value = (*c).second; return true; } - std::string v = MarsLanguage::bestMatch(ctx, value, values_, false, false, false, mapping_); + std::string v = MarsLanguage::bestMatch(ctx, val, values_, false, false, true, mapping_); if (v.empty()) { return false; } - std::map::const_iterator k = mapping_.find(v); + std::map::const_iterator k = mapping_.find(eckit::StringTools::lower(v)); ASSERT(k != mapping_.end()); - value = cache_[value] = (*k).second; + value = cache_[val] = (*k).second; return true; } diff --git a/src/metkit/mars/TypeEnum.h b/src/metkit/mars/TypeEnum.h index a2531a9f..8c1293fe 100644 --- a/src/metkit/mars/TypeEnum.h +++ b/src/metkit/mars/TypeEnum.h @@ -34,7 +34,7 @@ class TypeEnum : public Type { virtual void print(std::ostream& out) const override; virtual void reset() override; - virtual bool expand(const MarsExpandContext& ctx, std::string& value) const override; + virtual bool expand(const MarsExpandContext& ctx, const MarsRequest& request, std::string& value) const override; std::map mapping_; std::vector values_; diff --git a/src/metkit/mars/TypeExpver.cc b/src/metkit/mars/TypeExpver.cc index ff1afc91..b8602483 100644 --- a/src/metkit/mars/TypeExpver.cc +++ b/src/metkit/mars/TypeExpver.cc @@ -24,10 +24,18 @@ namespace mars { TypeExpver::TypeExpver(const std::string& name, const eckit::Value& settings) : Type(name, settings) {} -bool TypeExpver::expand(const MarsExpandContext&, std::string& value) const { - std::ostringstream oss; - oss << std::setfill('0') << std::setw(4) << eckit::StringTools::trim(value); - value = oss.str(); +bool TypeExpver::expand(const MarsExpandContext&, const MarsRequest& /* request */, std::string& value) const { + + std::string v = eckit::StringTools::lower(eckit::StringTools::trim(value)); + + if (v == "all" || v == "any") { + value = v; + } + else { + std::ostringstream oss; + oss << std::setfill('0') << std::setw(4) << eckit::StringTools::trim(value); + value = oss.str(); + } return true; } diff --git a/src/metkit/mars/TypeExpver.h b/src/metkit/mars/TypeExpver.h index 32be1a87..0a196b3d 100644 --- a/src/metkit/mars/TypeExpver.h +++ b/src/metkit/mars/TypeExpver.h @@ -28,7 +28,7 @@ class TypeExpver : public Type { ~TypeExpver() noexcept override = default; - virtual bool expand(const MarsExpandContext& ctx, std::string& value) const override; + virtual bool expand(const MarsExpandContext& ctx, const MarsRequest& request, std::string& value) const override; private: // methods diff --git a/src/metkit/mars/TypeFloat.cc b/src/metkit/mars/TypeFloat.cc index ab2ed62e..5ad6c069 100644 --- a/src/metkit/mars/TypeFloat.cc +++ b/src/metkit/mars/TypeFloat.cc @@ -22,7 +22,7 @@ namespace metkit::mars { TypeFloat::TypeFloat(const std::string& name, const eckit::Value& settings) : Type(name, settings) {} -bool TypeFloat::expand(const MarsExpandContext& ctx, std::string& value) const { +bool TypeFloat::expand(const MarsExpandContext& ctx, const MarsRequest& /* request */, std::string& value) const { bool dot = false; diff --git a/src/metkit/mars/TypeFloat.h b/src/metkit/mars/TypeFloat.h index 0ea9acd3..257eb849 100644 --- a/src/metkit/mars/TypeFloat.h +++ b/src/metkit/mars/TypeFloat.h @@ -33,7 +33,7 @@ class TypeFloat : public Type { private: // methods virtual void print(std::ostream& out) const override; - virtual bool expand(const MarsExpandContext& ctx, std::string& value) const override; + virtual bool expand(const MarsExpandContext& ctx, const MarsRequest& request, std::string& value) const override; }; //---------------------------------------------------------------------------------------------------------------------- diff --git a/src/metkit/mars/TypeInteger.cc b/src/metkit/mars/TypeInteger.cc index b8e6aa91..e8c097fe 100644 --- a/src/metkit/mars/TypeInteger.cc +++ b/src/metkit/mars/TypeInteger.cc @@ -68,7 +68,7 @@ bool TypeInteger::ok(const std::string& value, long& n) const { return !range_ || (n >= range_->lower_ && n <= range_->upper_); } -bool TypeInteger::expand(const MarsExpandContext& ctx, std::string& value) const { +bool TypeInteger::expand(const MarsExpandContext& ctx, const MarsRequest& /* request */, std::string& value) const { long n = 0; if (ok(value, n)) { static eckit::Translator l2s; diff --git a/src/metkit/mars/TypeInteger.h b/src/metkit/mars/TypeInteger.h index 288e4425..8b49d1a2 100644 --- a/src/metkit/mars/TypeInteger.h +++ b/src/metkit/mars/TypeInteger.h @@ -34,7 +34,7 @@ class TypeInteger : public Type { protected: bool ok(const std::string& value, long& n) const; - bool expand(const MarsExpandContext& ctx, std::string& value) const override; + bool expand(const MarsExpandContext& ctx, const MarsRequest& request, std::string& value) const override; private: // methods diff --git a/src/metkit/mars/TypeLowercase.cc b/src/metkit/mars/TypeLowercase.cc index 4be10ed9..635c9521 100644 --- a/src/metkit/mars/TypeLowercase.cc +++ b/src/metkit/mars/TypeLowercase.cc @@ -26,7 +26,7 @@ void TypeLowercase::print(std::ostream& out) const { out << "TypeLowercase[name=" << name_ << "]"; } -bool TypeLowercase::expand(const MarsExpandContext& ctx, std::string& value) const { +bool TypeLowercase::expand(const MarsExpandContext& ctx, const MarsRequest& /* request */, std::string& value) const { std::transform(value.begin(), value.end(), value.begin(), [](unsigned char c) { return std::tolower(c); }); return true; diff --git a/src/metkit/mars/TypeLowercase.h b/src/metkit/mars/TypeLowercase.h index 356e253f..4fcb5079 100644 --- a/src/metkit/mars/TypeLowercase.h +++ b/src/metkit/mars/TypeLowercase.h @@ -31,7 +31,7 @@ class TypeLowercase : public Type { private: // methods virtual void print(std::ostream& out) const override; - virtual bool expand(const MarsExpandContext& ctx, std::string& value) const override; + virtual bool expand(const MarsExpandContext& ctx, const MarsRequest& request, std::string& value) const override; }; //---------------------------------------------------------------------------------------------------------------------- diff --git a/src/metkit/mars/TypeMixed.cc b/src/metkit/mars/TypeMixed.cc index b54d806f..3c7996da 100644 --- a/src/metkit/mars/TypeMixed.cc +++ b/src/metkit/mars/TypeMixed.cc @@ -10,6 +10,7 @@ #include "metkit/mars/TypeMixed.h" +#include "metkit/mars/MarsRequest.h" #include "metkit/mars/TypesFactory.h" @@ -21,42 +22,59 @@ namespace mars { TypeMixed::TypeMixed(const std::string& name, const eckit::Value& settings) : Type(name, settings) { eckit::Value types = settings["type"]; - eckit::Value cfg = settings; - + eckit::Value cfg; for (size_t i = 0; i < types.size(); ++i) { - cfg["type"] = types[i]; + if (types[i].isString()) { + cfg = settings; + cfg["type"] = types[i]; - Type* k = TypesFactory::build(name + "." + std::string(types[i]), cfg); - k->attach(); - types_.push_back(k); + Type* k = TypesFactory::build(name + "." + std::string(types[i]), cfg); + k->attach(); + types_.emplace_back(nullptr, k); + } + else { // it is a subtype, potentially with a Context + cfg = types[i]; + eckit::Value type = cfg["type"]; + + std::unique_ptr c; + if (cfg.contains("context")) { + c = Context::parseContext(cfg["context"]); + } + + Type* k = TypesFactory::build(name + "." + std::to_string(i) + "." + std::string(type), cfg); + k->attach(); + types_.emplace_back(std::move(c), k); + } } } TypeMixed::~TypeMixed() noexcept { - for (std::vector::iterator j = types_.begin(); j != types_.end(); ++j) { - (*j)->detach(); + for (auto it = types_.begin(); it != types_.end(); it++) { + (*it).second->detach(); } } void TypeMixed::print(std::ostream& out) const { out << "TypeMixed[name=" << name_; - for (std::vector::const_iterator j = types_.begin(); j != types_.end(); ++j) { - out << "," << *(*j); + for (auto it = types_.begin(); it != types_.end(); it++) { + out << "," << *((*it).second); } out << "]"; } -bool TypeMixed::expand(const MarsExpandContext& ctx, std::string& value) const { - for (std::vector::const_iterator j = types_.begin(); j != types_.end(); ++j) { - std::string tmp = value; - if ((*j)->expand(ctx, tmp)) { - value = tmp; - return true; +bool TypeMixed::expand(const MarsExpandContext& ctx, const MarsRequest& request, std::string& value) const { + + for (auto it = types_.begin(); it != types_.end(); it++) { + if ((*it).first == nullptr || (*it).first->matches(request)) { + std::string tmp = value; + if ((*it).second->expand(ctx, request, tmp)) { + value = tmp; + return true; + } } } - return false; } diff --git a/src/metkit/mars/TypeMixed.h b/src/metkit/mars/TypeMixed.h index 84f5d2a5..7494a129 100644 --- a/src/metkit/mars/TypeMixed.h +++ b/src/metkit/mars/TypeMixed.h @@ -34,9 +34,9 @@ class TypeMixed : public Type { private: // methods virtual void print(std::ostream& out) const override; - virtual bool expand(const MarsExpandContext& ctx, std::string& value) const override; + virtual bool expand(const MarsExpandContext& ctx, const MarsRequest& request, std::string& value) const override; - std::vector types_; + std::vector, Type*>> types_; }; //---------------------------------------------------------------------------------------------------------------------- diff --git a/src/metkit/mars/TypeParam.cc b/src/metkit/mars/TypeParam.cc index 33325e87..4f5cefe6 100644 --- a/src/metkit/mars/TypeParam.cc +++ b/src/metkit/mars/TypeParam.cc @@ -539,7 +539,8 @@ void TypeParam::pass2(const MarsExpandContext& ctx, MarsRequest& request) { } -void TypeParam::expand(const MarsExpandContext& ctx, std::vector& values) const { +void TypeParam::expand(const MarsExpandContext& /* ctx */, const MarsRequest& /* request */, + std::vector& /* values */) const { // Work done on pass2() } diff --git a/src/metkit/mars/TypeParam.h b/src/metkit/mars/TypeParam.h index 8d6b8263..75aac68b 100644 --- a/src/metkit/mars/TypeParam.h +++ b/src/metkit/mars/TypeParam.h @@ -30,7 +30,6 @@ class TypeParam : public Type { TypeParam(const std::string& name, const eckit::Value& settings); ~TypeParam() noexcept override = default; - ; protected: @@ -45,7 +44,8 @@ class TypeParam : public Type { virtual void print(std::ostream& out) const override; virtual void reset() override; virtual void pass2(const MarsExpandContext& ctx, MarsRequest& request) override; - virtual void expand(const MarsExpandContext& ctx, std::vector& values) const override; + virtual void expand(const MarsExpandContext& ctx, const MarsRequest& request, + std::vector& values) const override; }; //---------------------------------------------------------------------------------------------------------------------- diff --git a/src/metkit/mars/TypeRange.cc b/src/metkit/mars/TypeRange.cc index 5fe794d5..47408d5d 100644 --- a/src/metkit/mars/TypeRange.cc +++ b/src/metkit/mars/TypeRange.cc @@ -72,7 +72,7 @@ StepRange TypeRange::parse(std::string& value) const { } } -bool TypeRange::expand(const MarsExpandContext& ctx, std::string& value) const { +bool TypeRange::expand(const MarsExpandContext& /* ctx */, const MarsRequest& /* request */, std::string& value) const { value = parse(value); return true; diff --git a/src/metkit/mars/TypeRange.h b/src/metkit/mars/TypeRange.h index ea77e0bd..64abce0d 100644 --- a/src/metkit/mars/TypeRange.h +++ b/src/metkit/mars/TypeRange.h @@ -33,7 +33,7 @@ class TypeRange : public Type { private: // methods virtual void print(std::ostream& out) const override; - virtual bool expand(const MarsExpandContext& ctx, std::string& value) const override; + virtual bool expand(const MarsExpandContext& ctx, const MarsRequest& request, std::string& value) const override; StepRange parse(std::string& value) const; }; diff --git a/src/metkit/mars/TypeRegex.cc b/src/metkit/mars/TypeRegex.cc index 0890b4a2..e41245cb 100644 --- a/src/metkit/mars/TypeRegex.cc +++ b/src/metkit/mars/TypeRegex.cc @@ -39,7 +39,7 @@ TypeRegex::TypeRegex(const std::string& name, const eckit::Value& settings) : Ty } } -bool TypeRegex::expand(const MarsExpandContext& ctx, std::string& value) const { +bool TypeRegex::expand(const MarsExpandContext& /* ctx */, const MarsRequest& /* request */, std::string& value) const { for (std::vector::const_iterator j = regex_.begin(); j != regex_.end(); ++j) { if ((*j).match(value)) { diff --git a/src/metkit/mars/TypeRegex.h b/src/metkit/mars/TypeRegex.h index 39ea7f71..ccce94d4 100644 --- a/src/metkit/mars/TypeRegex.h +++ b/src/metkit/mars/TypeRegex.h @@ -35,7 +35,7 @@ class TypeRegex : public Type { private: // methods virtual void print(std::ostream& out) const override; - virtual bool expand(const MarsExpandContext& ctx, std::string& value) const override; + virtual bool expand(const MarsExpandContext& ctx, const MarsRequest& request, std::string& value) const override; std::vector regex_; bool uppercase_; diff --git a/src/metkit/mars/TypeTime.cc b/src/metkit/mars/TypeTime.cc index c5ba03ef..079b1f8c 100644 --- a/src/metkit/mars/TypeTime.cc +++ b/src/metkit/mars/TypeTime.cc @@ -26,7 +26,7 @@ TypeTime::TypeTime(const std::string& name, const eckit::Value& settings) : Type multiple_ = true; } -bool TypeTime::expand(const MarsExpandContext&, std::string& value) const { +bool TypeTime::expand(const MarsExpandContext&, const MarsRequest& /* request */, std::string& value) const { eckit::Time time(value); diff --git a/src/metkit/mars/TypeTime.h b/src/metkit/mars/TypeTime.h index 9a3529a9..069becd0 100644 --- a/src/metkit/mars/TypeTime.h +++ b/src/metkit/mars/TypeTime.h @@ -34,7 +34,7 @@ class TypeTime : public Type { private: // methods virtual void print(std::ostream& out) const override; - virtual bool expand(const MarsExpandContext& ctx, std::string& value) const override; + virtual bool expand(const MarsExpandContext& ctx, const MarsRequest& request, std::string& value) const override; }; //---------------------------------------------------------------------------------------------------------------------- diff --git a/src/metkit/mars/TypeToByList.h b/src/metkit/mars/TypeToByList.h index f7a1188e..54d8f560 100644 --- a/src/metkit/mars/TypeToByList.h +++ b/src/metkit/mars/TypeToByList.h @@ -40,7 +40,12 @@ class TypeToByList : public ITypeToByList { virtual ~TypeToByList() = default; - void expandRanges(const MarsExpandContext& ctx, std::vector& values) const override { + void expandRanges(const MarsExpandContext& ctx, const MarsRequest& request, + std::vector& values) const override { + + if (values.size() == 1) { + return; + } static eckit::Translator s2el; static eckit::Translator s2by; @@ -66,8 +71,8 @@ class TypeToByList : public ITypeToByList { throw eckit::BadValue(oss.str()); } - EL from = s2el(type_.tidy(ctx, values[i - 1])); - EL to = s2el(type_.tidy(ctx, values[i + 1])); + EL from = s2el(type_.tidy(ctx, request, values[i - 1])); + EL to = s2el(type_.tidy(ctx, request, values[i + 1])); BY by = s2by(by_); if (i + 2 < values.size() && eckit::StringTools::lower(values[i + 2]) == "by") { @@ -112,12 +117,12 @@ class TypeToByList : public ITypeToByList { if ((from < to && j > to) || (from > to && j < to)) { break; } - newval.emplace_back(type_.tidy(ctx, el2s(j))); + newval.emplace_back(type_.tidy(ctx, request, el2s(j))); } i++; } else { - newval.push_back(type_.tidy(ctx, s)); + newval.push_back(type_.tidy(ctx, request, s)); } } diff --git a/src/metkit/mars/TypeToByListQuantile.cc b/src/metkit/mars/TypeToByListQuantile.cc index f20916db..251c51ba 100644 --- a/src/metkit/mars/TypeToByListQuantile.cc +++ b/src/metkit/mars/TypeToByListQuantile.cc @@ -61,7 +61,8 @@ void TypeToByListQuantile::print(std::ostream& out) const { out << "TypeToByListQuantile[name=" << name_ << "]"; } -bool TypeToByListQuantile::expand(const MarsExpandContext& ctx, std::string& value) const { +bool TypeToByListQuantile::expand(const MarsExpandContext& ctx, const MarsRequest& /* request */, + std::string& value) const { Quantile q(value); if (denominators_.find(q.den()) == denominators_.end()) { std::ostringstream oss; diff --git a/src/metkit/mars/TypeToByListQuantile.h b/src/metkit/mars/TypeToByListQuantile.h index 1eac1b86..cc203ecc 100644 --- a/src/metkit/mars/TypeToByListQuantile.h +++ b/src/metkit/mars/TypeToByListQuantile.h @@ -31,7 +31,7 @@ class TypeToByListQuantile : public Type { private: // methods virtual void print(std::ostream& out) const override; - virtual bool expand(const MarsExpandContext& ctx, std::string& value) const override; + virtual bool expand(const MarsExpandContext& ctx, const MarsRequest& request, std::string& value) const override; std::set denominators_; }; diff --git a/src/metkit/odb/OdbMetadataDecoder.cc b/src/metkit/odb/OdbMetadataDecoder.cc index d4f99e26..c872dc6e 100644 --- a/src/metkit/odb/OdbMetadataDecoder.cc +++ b/src/metkit/odb/OdbMetadataDecoder.cc @@ -19,6 +19,7 @@ #include "eckit/utils/StringTools.h" #include "metkit/config/LibMetkit.h" +#include "metkit/mars/MarsRequest.h" #include "metkit/mars/Type.h" #include "metkit/odb/IdMapper.h" @@ -61,8 +62,7 @@ class OdbColumnNameMapping { //---------------------------------------------------------------------------------------------------------------------- -namespace metkit { -namespace codes { +namespace metkit::codes { //---------------------------------------------------------------------------------------------------------------------- @@ -83,7 +83,7 @@ void OdbMetadataDecoder::visit(const std::string& columnName, const std::set& for (auto val : vals) { std::string stringVal = eckit::Translator()(val); - std::string tidyVal = t->tidy(stringVal); + std::string tidyVal = t->tidy(metkit::mars::MarsRequest{}, stringVal); if (stringVal == tidyVal) // if t->tidy had no effect, set the original value gather_.setValue(keyword, val); else @@ -122,5 +122,4 @@ void OdbMetadataDecoder::operator()(const std::string& columnName, const std::se //---------------------------------------------------------------------------------------------------------------------- -} // namespace codes -} // namespace metkit +} // namespace metkit::codes diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 0a9fe059..b76bb1db 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -24,16 +24,8 @@ ecbuild_get_test_multidata( TARGET metkit_get_odb_data NAMES multiodb.odb multiodb2.odb ) -# ecbuild_add_test( TARGET metkit_test_emosfile -# ARGS --log_level=message -# CONDITION HAVE_GRIB -# INCLUDES "${ECKIT_INCLUDE_DIRS}" -# SOURCES test_emosfile.cc -# ENVIRONMENT "${metkit_env}" -# LIBS metkit -# TEST_DEPENDS grib_get_data -# ) - +add_custom_target(soft_link_expand_test_data ALL + COMMAND ${CMAKE_COMMAND} -E create_symlink "${CMAKE_CURRENT_SOURCE_DIR}/expand" "${CMAKE_CURRENT_BINARY_DIR}/expand") ecbuild_add_test( TARGET metkit_test_multihandle CONDITION HAVE_GRIB @@ -73,6 +65,7 @@ ecbuild_add_test( TARGET metkit_test_gribhandle foreach( test c_api + context date expand filter diff --git a/tests/expand/MARSC-223.expected b/tests/expand/MARSC-223.expected new file mode 100644 index 00000000..ebd82cfc --- /dev/null +++ b/tests/expand/MARSC-223.expected @@ -0,0 +1,17 @@ + RETRIEVE, + CLASS = OD, + TYPE = FC, + STREAM = OPER, + EXPVER = 0001, + REPRES = GG, + LEVTYPE = SFC, + PARAM = 33, + DATE = 20231221, + TIME = 0000, + STEP = 0, + DOMAIN = G, + TARGET = reference.zcbyW7.data, + RESOL = AUTO, + GRID = .125/.125, + PADDING = 0, + USE = INFREQUENT \ No newline at end of file diff --git a/tests/expand/MARSC-223.req b/tests/expand/MARSC-223.req new file mode 100644 index 00000000..e1bdc13f --- /dev/null +++ b/tests/expand/MARSC-223.req @@ -0,0 +1,2 @@ +retrieve, date=2023-12-21,expver=1,grid=0.125/0.125,levtype=sfc,padding=0,param=33.128,step=0,stream=oper,time=00:00:00,type=fc,use=infrequent, +target="reference.zcbyW7.data" \ No newline at end of file diff --git a/tests/expand/MARSC-224.expected b/tests/expand/MARSC-224.expected new file mode 100644 index 00000000..ef659f8a --- /dev/null +++ b/tests/expand/MARSC-224.expected @@ -0,0 +1,18 @@ + RETRIEVE, + CLASS = TI, + TYPE = FC, + STREAM = OPER, + EXPVER = prod, + REPRES = SH, + LEVTYPE = SFC, + PARAM = 151, + DATE = 20231226, + TIME = 1200, + STEP = 0/6/12/18/24/30/36/42/48/54/60/66/72/78/84/90/96/102/108/114/120/126/132/138/144/150/156/162/168/174/180/186/192/198/204/210/216/222/228/234/240, + NUMBER = ALL, + ORIGIN = ECMF, + TARGET = reference.OkV8i4.data, + RESOL = AUTO, + GRID = .5/.5, + PADDING = 0, + PROCESS = LOCAL \ No newline at end of file diff --git a/tests/expand/MARSC-224.req b/tests/expand/MARSC-224.req new file mode 100644 index 00000000..2ece4449 --- /dev/null +++ b/tests/expand/MARSC-224.req @@ -0,0 +1,3 @@ +retrieve, +class=ti,date=20231226/to/20231226,expver=prod,grid=0.5/0.5,levtype=sfc,padding=0,param=151,step=0/to/240/by/6,time=12,type=fc,number=all,origin=ecmf, +target="reference.OkV8i4.data" \ No newline at end of file diff --git a/tests/expand/MARSC-225.expected b/tests/expand/MARSC-225.expected new file mode 100644 index 00000000..93d49953 --- /dev/null +++ b/tests/expand/MARSC-225.expected @@ -0,0 +1,18 @@ +RETRIEVE, + CLASS = TI, + TYPE = PF, + STREAM = ENFO, + EXPVER = prod, + REPRES = SH, + LEVTYPE = SFC, + PARAM = 167, + DATE = 20231230, + TIME = 0000, + STEP = 0/6/12/18/24/30/36/42/48/54/60/66/72/78/84/90/96/102/108/114/120/126/132/138/144/150/156/162/168/174/180/186/192/198/204/210/216/222/228/234/240/246/252/258/264/270/276/282/288/294/300/306/312/318/324/330/336/342/348/354/360, + NUMBER = 1, + ORIGIN = ECMF, + TARGET = reference.8nWO8K.data, + RESOL = AUTO, + GRID = .2/.2, + PADDING = 0, + PROCESS = LOCAL \ No newline at end of file diff --git a/tests/expand/MARSC-225.req b/tests/expand/MARSC-225.req new file mode 100644 index 00000000..c3ee0a65 --- /dev/null +++ b/tests/expand/MARSC-225.req @@ -0,0 +1,3 @@ +retrieve, +class=ti,date=2023-12-30,expver=prod,grid=0.2/0.2,levtype=sfc,padding=0,param=167,step=0/to/360/by/6,time=00:00:00,type=pf,number=1,origin=ecmf, +target="reference.8nWO8K.data" \ No newline at end of file diff --git a/tests/expand/MARSC-227.expected b/tests/expand/MARSC-227.expected new file mode 100644 index 00000000..192f7eb5 --- /dev/null +++ b/tests/expand/MARSC-227.expected @@ -0,0 +1,17 @@ +RETRIEVE, + CLASS = OD, + TYPE = FC, + STREAM = OPER, + EXPVER = 0001, + REPRES = GG, + LEVTYPE = SFC, + PARAM = 33, + DATE = 20231221, + TIME = 0000, + STEP = 0, + DOMAIN = G, + TARGET = reference.zcbyW7.data, + RESOL = AUTO, + GRID = .125/.125, + PADDING = 0, + USE = INFREQUENT \ No newline at end of file diff --git a/tests/expand/MARSC-227.req b/tests/expand/MARSC-227.req new file mode 100644 index 00000000..015bf9b8 --- /dev/null +++ b/tests/expand/MARSC-227.req @@ -0,0 +1,3 @@ +retrieve, +date=2023-12-21,expver=1,grid=0.125/0.125,levtype=sfc,padding=0,param=33.128,step=0,stream=oper,time=00:00:00,type=fc,use=infrequent, +target="reference.zcbyW7.data" \ No newline at end of file diff --git a/tests/expand/MARSC-228.expected b/tests/expand/MARSC-228.expected new file mode 100644 index 00000000..895431a7 --- /dev/null +++ b/tests/expand/MARSC-228.expected @@ -0,0 +1,13 @@ +RETRIEVE, +    CLASS      = OD, +    TYPE       = OB, +    STREAM     = OPER, +    EXPVER     = 0001, +    REPRES     = BU, +    OBSTYPE    = 1, +    DATE       = 20210501, +    TIME       = 2101, +    DOMAIN     = G, +    TARGET     = reference.xoB8Cx.data, +    DUPLICATES = KEEP, +    RANGE      = 179 \ No newline at end of file diff --git a/tests/expand/MARSC-228.re b/tests/expand/MARSC-228.re new file mode 100644 index 00000000..acaa955c --- /dev/null +++ b/tests/expand/MARSC-228.re @@ -0,0 +1,3 @@ +retrieve, +date=20210501,time=2101/to/2400,type=ob,target="/ec/fws2/sb/work/rd/erds/i7ug/LWDA/2021050200/an/scat", +target="reference.xoB8Cx.data" \ No newline at end of file diff --git a/tests/expand/MARSC-231.expected b/tests/expand/MARSC-231.expected new file mode 100644 index 00000000..1ac9f158 --- /dev/null +++ b/tests/expand/MARSC-231.expected @@ -0,0 +1,16 @@ +RETRIEVE, + CLASS = OD, + TYPE = FC, + STREAM = OPER, + EXPVER = 0001, + REPRES = GG, + LEVTYPE = SFC, + PARAM = 167, + DATE = 20231231, + TIME = 0000/1200, + STEP = 0, + DOMAIN = G, + TARGET = reference.vEDx0X.data, + RESOL = AUTO, + AREA = 58/-10/35/80, + GRID = .1/.1 \ No newline at end of file diff --git a/tests/expand/MARSC-231.req b/tests/expand/MARSC-231.req new file mode 100644 index 00000000..22305a2a --- /dev/null +++ b/tests/expand/MARSC-231.req @@ -0,0 +1,3 @@ +retrieve, +area=58./-10./35./80,class=od,date=20231231,expver=1,grid=0.1/0.1,levtype=surf,param=2t,step=0,stream=oper,time=00:00:00/12:00:00,type=fc,target=target.bbafa703-e7da-4383-8c34-d36a7cbee4f5,repres=gg, +target="reference.vEDx0X.data" \ No newline at end of file diff --git a/tests/expand/MARSC-232.expected b/tests/expand/MARSC-232.expected new file mode 100644 index 00000000..d86ebfa5 --- /dev/null +++ b/tests/expand/MARSC-232.expected @@ -0,0 +1,18 @@ +RETRIEVE, + DATASET = mars, + CLASS = OD, + TYPE = FC, + STREAM = OPER, + EXPVER = 0001, + REPRES = GG, + LEVTYPE = SFC, + PARAM = 144, + DATE = 20231003, + TIME = 0000/1200, + STEP = 0/1/2/3/4/5/6/7/8/9/10/11/12, + DOMAIN = G, + TARGET = reference.data, + RESOL = AUTO, + AREA = 85/-180/-60/180, + GRID = .1/.1, + PADDING = 0 \ No newline at end of file diff --git a/tests/expand/MARSC-232.req b/tests/expand/MARSC-232.req new file mode 100644 index 00000000..24ed8213 --- /dev/null +++ b/tests/expand/MARSC-232.req @@ -0,0 +1,3 @@ +retrieve, + area=85.000/-180.000/-60.000/180.000,class=od,date=20231003/to/20231003,expver=1,grid=0.100/0.100,levtype=sfc,padding=0,param=144.128,step=0/to/12/by/1,stream=oper,time=00/12,type=fc,dataset=mars, + target=reference.data \ No newline at end of file diff --git a/tests/expand/MARSC-233 copy.expected b/tests/expand/MARSC-233 copy.expected new file mode 100644 index 00000000..be875b1e --- /dev/null +++ b/tests/expand/MARSC-233 copy.expected @@ -0,0 +1,19 @@ +RETRIEVE, + DATASET = tigge, + CLASS = TI, + TYPE = FC, + STREAM = OPER, + EXPVER = prod, + REPRES = SH, + LEVTYPE = PL, + LEVELIST = 250/500/850, + PARAM = 156, + DATE = 20231224, + TIME = 0000/1200, + STEP = 0, + ORIGIN = RKSL, + TARGET = reference.data, + RESOL = AUTO, + AREA = 90/0/-90/359.75, + GRID = .25/.25, + PADDING = 0 \ No newline at end of file diff --git a/tests/expand/MARSC-233.expected b/tests/expand/MARSC-233.expected new file mode 100644 index 00000000..010894bf --- /dev/null +++ b/tests/expand/MARSC-233.expected @@ -0,0 +1,20 @@ +RETRIEVE, + DATASET = tigge, + CLASS = TI, + TYPE = FC, + STREAM = OPER, + EXPVER = prod, + REPRES = SH, + LEVTYPE = PL, + LEVELIST = 250/500/850, + PARAM = 156, + DATE = 20231224, + TIME = 0000/1200, + STEP = 0, + ORIGIN = RKSL, + TARGET = reference.data, + RESOL = AUTO, + AREA = 90/0/-90/359.75, + GRID = .25/.25, + PADDING = 0, + PROCESS = LOCAL \ No newline at end of file diff --git a/tests/expand/MARSC-233.req b/tests/expand/MARSC-233.req new file mode 100644 index 00000000..48abbf6f --- /dev/null +++ b/tests/expand/MARSC-233.req @@ -0,0 +1,2 @@ +retrieve,area=90.0/0.0/-90.0/359.75,class=ti,date=20231224,expver=prod,grid=0.25/0.25,levtype=pl,padding=0,param=156,step=0,time=0000/1200,type=fc,levelist=250/500/850,origin=rksl,dataset=tigge, + target=reference.data \ No newline at end of file diff --git a/tests/expand/MARSC-234.expected b/tests/expand/MARSC-234.expected new file mode 100644 index 00000000..e8d4c84e --- /dev/null +++ b/tests/expand/MARSC-234.expected @@ -0,0 +1,16 @@ +RETRIEVE, + CLASS = OD, + TYPE = FC, + STREAM = OPER, + EXPVER = 0001, + REPRES = GG, + LEVTYPE = SFC, + PARAM = 228022, + DATE = 20231220, + TIME = 1200, + STEP = 0, + DOMAIN = G, + TARGET = reference.A0FgVE.data, + RESOL = AUTO, + AREA = 73.5/-27/33/45, + GRID = .125/.125 \ No newline at end of file diff --git a/tests/expand/MARSC-234.req b/tests/expand/MARSC-234.req new file mode 100644 index 00000000..e1efb701 --- /dev/null +++ b/tests/expand/MARSC-234.req @@ -0,0 +1,3 @@ +retrieve, +area=Europe,class=od,date=2023-12-20,expver=1,grid=0.125/0.125,levtype=sfc,param=22.228,step=0,stream=oper,time=12:00:00,type=fc,target=target.27f72f51-1e60-437f-b1ce-e57129e2dff6, +target="reference.A0FgVE.data" \ No newline at end of file diff --git a/tests/expand/MARSC-236.expected b/tests/expand/MARSC-236.expected new file mode 100644 index 00000000..b8b8e744 --- /dev/null +++ b/tests/expand/MARSC-236.expected @@ -0,0 +1,19 @@ +RETRIEVE, + CLASS = OD, + TYPE = AN, + STREAM = OPER, + EXPVER = 0001, + REPRES = GG, + LEVTYPE = SFC, + PARAM = 134/137/165/166/167/168/235, + DATE = 20240102, + TIME = 0000, + STEP = 0, + DOMAIN = G, + TARGET = data.reference, + RESOL = AV, + ACCURACY = 12, + STYLE = DISSEMINATION, + AREA = 90/0/-90/359.5, + GRID = .5/.5, + PADDING = 0 \ No newline at end of file diff --git a/tests/expand/MARSC-236.req b/tests/expand/MARSC-236.req new file mode 100644 index 00000000..146777e1 --- /dev/null +++ b/tests/expand/MARSC-236.req @@ -0,0 +1,3 @@ +retrieve, +accuracy=12,area=90.0/0.0/-90.0/359.5,date=20240102,domain=g,grid=0.5/0.5,leve=off,levtype=sfc,padding=0,param=134/137/165/166/167/168/235,stream=da,style=dissemination,time=00,type=an, +target="data.reference" \ No newline at end of file diff --git a/tests/expand/MARSC-237.expected b/tests/expand/MARSC-237.expected new file mode 100644 index 00000000..17e8724b --- /dev/null +++ b/tests/expand/MARSC-237.expected @@ -0,0 +1,17 @@ +RETRIEVE, + CLASS = OD, + TYPE = FC, + STREAM = OPER, + EXPVER = 0001, + REPRES = GG, + LEVTYPE = SFC, + PARAM = 151, + DATE = 20240101, + TIME = 0000, + STEP = 0/3/6/9/12/15/18/21/24/27/30/33/36/39/42/45/48/51/54/57/60/63/66/69/72/75/78/81/84/87/90/93/96/99/102/105/108/111/114/117/120, + DOMAIN = G, + TARGET = reference.Hx2aUM.data, + RESOL = AUTO, + AREA = 90/-180/-90/180, + GRID = .25/.25, + PADDING = 0 \ No newline at end of file diff --git a/tests/expand/MARSC-237.re b/tests/expand/MARSC-237.re new file mode 100644 index 00000000..d834ade0 --- /dev/null +++ b/tests/expand/MARSC-237.re @@ -0,0 +1,3 @@ +retrieve, +area=90/-180/-90/180,class=od,date=2024-01-01,expver=1,grid=0.25/0.25,levtype=sfc,padding=0,param=mslp,step=0/to/120/by/3,stream=oper,time=00:00,type=fc, + target="reference.Hx2aUM.data" \ No newline at end of file diff --git a/tests/expand/MARSC-240.expected b/tests/expand/MARSC-240.expected new file mode 100644 index 00000000..f7b8e9a8 --- /dev/null +++ b/tests/expand/MARSC-240.expected @@ -0,0 +1,21 @@ +RETRIEVE, + CLASS = OD, + TYPE = OF, + STREAM = OCEA, + EXPVER = 0001, + REPRES = SH, + LEVTYPE = DP, + LEVELIST = 0, + PARAM = 151145, + DATE = 20070601, + TIME = 0000, + RANGE = 264, + STEP = 288, + NUMBER = 0, + DOMAIN = G, + SYSTEM = 2, + METHOD = 1, + PRODUCT = TIMS, + SECTION = Z, + LATITUDE = -9.967, + TARGET = reference.0DY4f2.data \ No newline at end of file diff --git a/tests/expand/MARSC-240.req b/tests/expand/MARSC-240.req new file mode 100644 index 00000000..0f279c15 --- /dev/null +++ b/tests/expand/MARSC-240.req @@ -0,0 +1,3 @@ +retrieve, +DOMAIN=G,LEVTYPE=DP,DATE=20070601,TIME=0000,STEP=288,PARAM=145.151,CLASS=OD,TYPE=OF,STREAM=OCEA,EXPVER=0001,NUMBER=0,SYSTEM=2,METHOD=1,PRODUCT=TIMS,SECTION=Z,LEVELIST=0.000,LATITUDE=-9.967,RANGE=264, +target="reference.0DY4f2.data" \ No newline at end of file diff --git a/tests/expand/MARSC-241.expected b/tests/expand/MARSC-241.expected new file mode 100644 index 00000000..c1df90cc --- /dev/null +++ b/tests/expand/MARSC-241.expected @@ -0,0 +1,14 @@ +RETRIEVE, + CLASS = RD, + TYPE = FC, + STREAM = OPER, + EXPVER = f36f, + REPRES = SH, + LEVTYPE = ML, + LEVELIST = 1, + PARAM = 210073/210074, + DATE = 20041015, + TIME = 1200, + STEP = 0, + DOMAIN = G, + TARGET = reference.data \ No newline at end of file diff --git a/tests/expand/MARSC-241.req b/tests/expand/MARSC-241.req new file mode 100644 index 00000000..852cd240 --- /dev/null +++ b/tests/expand/MARSC-241.req @@ -0,0 +1,3 @@ +retrieve, + DOMAIN=G,LEVTYPE=ML,LEVELIST=1,DATE=20041015,TIME=1200,STEP=0,PARAM=73.210/74.210,CLASS=RD,TYPE=FC,STREAM=OPER,EXPVER=f36f, + target=reference.data \ No newline at end of file diff --git a/tests/expand/MARSC-242.expected b/tests/expand/MARSC-242.expected new file mode 100644 index 00000000..8118c83e --- /dev/null +++ b/tests/expand/MARSC-242.expected @@ -0,0 +1,12 @@ +RETRIEVE, + CLASS = E4, + TYPE = CL, + STREAM = MODA, + EXPVER = 0001, + REPRES = SH, + LEVTYPE = ML, + LEVELIST = 1, + PARAM = 155, + DATE = JAN, + DOMAIN = G, + TARGET = reference.data \ No newline at end of file diff --git a/tests/expand/MARSC-242.req b/tests/expand/MARSC-242.req new file mode 100644 index 00000000..99f5258c --- /dev/null +++ b/tests/expand/MARSC-242.req @@ -0,0 +1,3 @@ +retrieve, + DOMAIN=G,LEVTYPE=ML,LEVELIST=1,DATE=JAN,PARAM=155.128,CLASS=E4,TYPE=CL,STREAM=MODA,EXPVER=0001, + target=reference.data \ No newline at end of file diff --git a/tests/expand/MARSC-244.expected b/tests/expand/MARSC-244.expected new file mode 100644 index 00000000..ad1e2c20 --- /dev/null +++ b/tests/expand/MARSC-244.expected @@ -0,0 +1,17 @@ +RETRIEVE, + CLASS = TI, + TYPE = PF, + STREAM = ENFO, + EXPVER = test, + MODEL = LAM, + REPRES = SH, + LEVTYPE = SFC, + PARAM = 166, + DATE = 20130225, + TIME = 0000, + STEP = 3, + NUMBER = 1, + ORIGIN = SRNWPPEPS-DWD-EUA, + TARGET = reference.data, + PADDING = 0, + PROCESS = LOCAL \ No newline at end of file diff --git a/tests/expand/MARSC-244.req b/tests/expand/MARSC-244.req new file mode 100644 index 00000000..9eccd65b --- /dev/null +++ b/tests/expand/MARSC-244.req @@ -0,0 +1,3 @@ +retrieve, + DATE=20130225,TIME=0000,ORIGIN=SRNWPPEPS-DWD-EUA,STEP=3,LEVTYPE=SFC,NUMBER=1,PARAM=166,EXPVER=test,CLASS=TI,MODEL=LAM,TYPE=PF,STREAM=ENFO, + target=reference.data \ No newline at end of file diff --git a/tests/expand/MARSC-245.expected b/tests/expand/MARSC-245.expected new file mode 100644 index 00000000..44fa10f8 --- /dev/null +++ b/tests/expand/MARSC-245.expected @@ -0,0 +1,18 @@ +RETRIEVE, + CLASS = MS, + COUNTRY = IT, + MODEL = HRM, + BCMODEL = IFS, + ICMODEL = MVOI, + DOMAIN = EUROATL, + STREAM = OPER, + TYPE = FG, + EXPVER = 0001, + LEVTYPE = 110, + PARAM = 201033, + TIME = 1800, + DATE = 20040102, + STEP = 6, + LEVELIST = 1, + TARGET = reference.data, + GRIB = ECMWF \ No newline at end of file diff --git a/tests/expand/MARSC-245.req b/tests/expand/MARSC-245.req new file mode 100644 index 00000000..6ca616e3 --- /dev/null +++ b/tests/expand/MARSC-245.req @@ -0,0 +1,3 @@ +retrieve, + DOMAIN=EUROATL,LEVTYPE=110,LEVELIST=1,DATE=20040102,TIME=1800,STEP=6,PARAM=33.201,CLASS=MS,TYPE=FG,STREAM=OPER,EXPVER=0001,COUNTRY=IT,MODEL=HRM,BCMODEL=IFS,ICMODEL=MVOI, + target=reference.data \ No newline at end of file diff --git a/tests/expand/MARSC-247.expected b/tests/expand/MARSC-247.expected new file mode 100644 index 00000000..72d31b60 --- /dev/null +++ b/tests/expand/MARSC-247.expected @@ -0,0 +1,14 @@ +RETRIEVE, + CLASS = RD, + TYPE = AN, + STREAM = OPER, + EXPVER = aaaa, + REPRES = SH, + LEVTYPE = PL, + LEVELIST = 1000/850/700/500/400/300, + PARAM = 129, + DATE = 20250413, + TIME = 1200, + STEP = 0, + DOMAIN = G, + TARGET = data.reference \ No newline at end of file diff --git a/tests/expand/MARSC-247.req b/tests/expand/MARSC-247.req new file mode 100644 index 00000000..a4433d45 --- /dev/null +++ b/tests/expand/MARSC-247.req @@ -0,0 +1,5 @@ + retrieve, + class=rd, + date=20250413, + expver=aaaa, + target=data.reference \ No newline at end of file diff --git a/tests/expand/MARSC-248.expected b/tests/expand/MARSC-248.expected new file mode 100644 index 00000000..9fd11734 --- /dev/null +++ b/tests/expand/MARSC-248.expected @@ -0,0 +1,15 @@ +RETRIEVE, + CLASS = OD, + TYPE = AN, + STREAM = OPER, + EXPVER = 0001, + REPRES = SH, + LEVTYPE = PL, + LEVELIST = 1000/500, + PARAM = 130, + DATE = 20250416, + TIME = 1200, + STEP = 0, + DOMAIN = G, + TARGET = data.reference, + ACCURACY = 8 \ No newline at end of file diff --git a/tests/expand/MARSC-248.req b/tests/expand/MARSC-248.req new file mode 100644 index 00000000..eab3684e --- /dev/null +++ b/tests/expand/MARSC-248.req @@ -0,0 +1,7 @@ +retrieve, + levtype=pl, + level=1000/500, + date=20250416, + param=t, + accuracy=LOW, + target=data.reference \ No newline at end of file diff --git a/tests/expand/MARSC-249.expected b/tests/expand/MARSC-249.expected new file mode 100644 index 00000000..bfeec007 --- /dev/null +++ b/tests/expand/MARSC-249.expected @@ -0,0 +1,17 @@ +RETRIEVE, + CLASS = OD, + TYPE = AN, + STREAM = OPER, + EXPVER = 0001, + REPRES = SH, + LEVTYPE = PL, + LEVELIST = 1000/500, + PARAM = 130, + DATE = 20250416, + TIME = 1200, + STEP = 0, + DOMAIN = G, + TARGET = data.reference, + RESOL = AUTO, + ACCURACY = 8, + GRID = 5/5 \ No newline at end of file diff --git a/tests/expand/MARSC-249.req b/tests/expand/MARSC-249.req new file mode 100644 index 00000000..36c4b3b7 --- /dev/null +++ b/tests/expand/MARSC-249.req @@ -0,0 +1,8 @@ +retrieve, + levtype=pl, + level=1000/500, + date=20250416, + param=t, + accuracy=REDUCED, + grid=5/5, + target=data.reference \ No newline at end of file diff --git a/tests/expand/MARSC-251.expected b/tests/expand/MARSC-251.expected new file mode 100644 index 00000000..972c8655 --- /dev/null +++ b/tests/expand/MARSC-251.expected @@ -0,0 +1,17 @@ +RETRIEVE, + CLASS = TI, + TYPE = CF, + STREAM = ENFO, + EXPVER = ALL, + REPRES = SH, + LEVTYPE = SFC, + PARAM = 167, + DATE = 20250414, + TIME = 1200, + STEP = 24, + ORIGIN = ALL, + TARGET = data.reference, + PADDING = 0, + PROCESS = LOCAL, + EXPECT = ANY, + NUMBER = 0 \ No newline at end of file diff --git a/tests/expand/MARSC-251.req b/tests/expand/MARSC-251.req new file mode 100644 index 00000000..7bba5534 --- /dev/null +++ b/tests/expand/MARSC-251.req @@ -0,0 +1,13 @@ +retrieve, + class=ti, + date=20250414, + time=12, + origin=all, + expver=all, + type=cf, + stream=enfo, + levtype=sfc, + param=2t, + step=24, + expect=any, + target=data.reference \ No newline at end of file diff --git a/tests/expand/MARSC-252.expected b/tests/expand/MARSC-252.expected new file mode 100644 index 00000000..b0f31fdc --- /dev/null +++ b/tests/expand/MARSC-252.expected @@ -0,0 +1,13 @@ +RETRIEVE, + CLASS = OD, + TYPE = AN, + STREAM = OPER, + EXPVER = 0001, + REPRES = GG, + LEVTYPE = SFC, + PARAM = 164, + DATE = 20250416, + TIME = 0000, + STEP = 0, + DOMAIN = G, + TARGET = data.reference \ No newline at end of file diff --git a/tests/expand/MARSC-252.req b/tests/expand/MARSC-252.req new file mode 100644 index 00000000..a4c04f2f --- /dev/null +++ b/tests/expand/MARSC-252.req @@ -0,0 +1,16 @@ +retrieve, + class=od, + stream=da, + type=an, + levtype=sfc, + levelist=off, + resol=off, + date=20250416, + time=00, + step=00, + param=tcc/10u/10v/2t/msl, + param=tcc, + repres=gg, + format=p, + expver=0001, + target=data.reference \ No newline at end of file diff --git a/tests/expand/MARSC-253.expected b/tests/expand/MARSC-253.expected new file mode 100644 index 00000000..4ff01120 --- /dev/null +++ b/tests/expand/MARSC-253.expected @@ -0,0 +1,13 @@ +RETRIEVE, + CLASS = OD, + TYPE = TF, + STREAM = ENFO, + EXPVER = 0001, + REPRES = BU, + OBSTYPE = 32, + DATE = 20060112, + TIME = 0000/1200, + STEP = 0, + DOMAIN = G, + TARGET = data.reference, + DUPLICATES = KEEP \ No newline at end of file diff --git a/tests/expand/MARSC-253.req b/tests/expand/MARSC-253.req new file mode 100644 index 00000000..057560de --- /dev/null +++ b/tests/expand/MARSC-253.req @@ -0,0 +1,12 @@ +retrieve, + class=od, + type=tf, + stream=enfo, + expver=0001, + repres=bu, + obstype=32, + date=20060112, + time=0000/1200, + domain=g, + duplicates=keep, + target=data.reference \ No newline at end of file diff --git a/tests/expand/MARSC-254.expected b/tests/expand/MARSC-254.expected new file mode 100644 index 00000000..add17633 --- /dev/null +++ b/tests/expand/MARSC-254.expected @@ -0,0 +1,13 @@ +RETRIEVE, + CLASS = OD, + TYPE = OB, + STREAM = OPER, + EXPVER = 0001, + REPRES = BU, + OBSTYPE = 1, + DATE = 20250414, + TIME = 0000, + RANGE = 1439, + DOMAIN = G, + TARGET = data.reference, + DUPLICATES = KEEP \ No newline at end of file diff --git a/tests/expand/MARSC-254.re b/tests/expand/MARSC-254.re new file mode 100644 index 00000000..02a922cb --- /dev/null +++ b/tests/expand/MARSC-254.re @@ -0,0 +1,6 @@ +retrieve, + type=ob, + date=-3, + time=00, + range=1439, + target=data.reference \ No newline at end of file diff --git a/tests/expand/MARSC-255.expected b/tests/expand/MARSC-255.expected new file mode 100644 index 00000000..bed984e8 --- /dev/null +++ b/tests/expand/MARSC-255.expected @@ -0,0 +1,18 @@ +RETRIEVE, + CLASS = OD, + TYPE = AN, + STREAM = OPER, + EXPVER = 0001, + REPRES = SH, + LEVTYPE = ML, + LEVELIST = 50, + PARAM = 248, + DATE = 20250416, + TIME = 1200, + STEP = 0, + DOMAIN = G, + TARGET = data.reference, + RESOL = AUTO, + INTERPOLATION = BILINEAR, + AREA = 75/60/10/-20, + GRID = 2.5/2.5 \ No newline at end of file diff --git a/tests/expand/MARSC-255.req b/tests/expand/MARSC-255.req new file mode 100644 index 00000000..79a08e2d --- /dev/null +++ b/tests/expand/MARSC-255.req @@ -0,0 +1,9 @@ +retrieve, + date=20250416, + area=75/60/10/-20, + grid=2.5/2.5, + levtype=ml, + levelist=50, + param=248, + interpolation=bilinear, + target=data.reference \ No newline at end of file diff --git a/tests/expand/MARSC-258.expected b/tests/expand/MARSC-258.expected new file mode 100644 index 00000000..3cf8f2aa --- /dev/null +++ b/tests/expand/MARSC-258.expected @@ -0,0 +1,15 @@ +RETRIEVE, + CLASS = RD, + TYPE = FC, + STREAM = LWDA, + EXPVER = h3f7, + REPRES = SH, + LEVTYPE = PL, + LEVELIST = 1000/850/700/500/400/300, + PARAM = 129, + DATE = 20181101, + TIME = 0000, + STEP = ALL, + ANOFFSET = 9, + DOMAIN = G, + TARGET = data.reference \ No newline at end of file diff --git a/tests/expand/MARSC-258.req b/tests/expand/MARSC-258.req new file mode 100644 index 00000000..8309beae --- /dev/null +++ b/tests/expand/MARSC-258.req @@ -0,0 +1,11 @@ +retrieve, + class=rd, + stream=lwda, + levtype=pl, + type=fc, + expver=h3f7, + step=all, + anoffset=9, + time=00, + date=20181101, + target=data.reference \ No newline at end of file diff --git a/tests/expand/MARSC-261.expected b/tests/expand/MARSC-261.expected new file mode 100644 index 00000000..117e67e0 --- /dev/null +++ b/tests/expand/MARSC-261.expected @@ -0,0 +1,17 @@ + RETRIEVE, + CLASS = OD, + TYPE = PF, + STREAM = ENFO, + EXPVER = 0001, + REPRES = SH, + LEVTYPE = SFC, + PARAM = 167/165/166/164/228, + DATE = 20250416, + TIME = 0000, + STEP = 6/12, + NUMBER = 1/2, + DOMAIN = G, + TARGET = data.reference, + RESOL = N128, + AREA = 70.5/-21/30/40.5, + GRID = 1.5/1.5 \ No newline at end of file diff --git a/tests/expand/MARSC-261.re b/tests/expand/MARSC-261.re new file mode 100644 index 00000000..3838b213 --- /dev/null +++ b/tests/expand/MARSC-261.re @@ -0,0 +1,17 @@ + retrieve, + class=od, + type=pf, + stream=ef, + expver=0001, + repres=sh, + levtype=sfc, + param=167/165/166/164/228, + date=20250416, + time=0000, + step=6/12, + number=1/2, + domain=g, + resol=n128, + area=70.5/-21.0/30.0/40.5, + grid=1.5/1.5, + target=data.reference \ No newline at end of file diff --git a/tests/expand/MARSC-263.expected b/tests/expand/MARSC-263.expected new file mode 100644 index 00000000..76baaca3 --- /dev/null +++ b/tests/expand/MARSC-263.expected @@ -0,0 +1,21 @@ +RETRIEVE, + CLASS = OD, + TYPE = OF, + STREAM = OCEA, + EXPVER = 0001, + REPRES = SH, + LEVTYPE = DP, + LEVELIST = 0/5, + PARAM = 129/130/145, + DATE = 20120101, + TIME = 0000, + STEP = 24/48/72/96, + NUMBER = 0/1/2/3/4, + DOMAIN = G, + SYSTEM = 3, + METHOD = 1, + PRODUCT = INST, + SECTION = H, + TARGET = data.reference, + DATABASE = marsod, + EXPECT = 60 \ No newline at end of file diff --git a/tests/expand/MARSC-263.req b/tests/expand/MARSC-263.req new file mode 100644 index 00000000..c758b8b5 --- /dev/null +++ b/tests/expand/MARSC-263.req @@ -0,0 +1,19 @@ +retrieve, + levelist=0/5, + section=h, + stream=ocea, + system=3, + method=1, + number=0/to/4, + time=00, + levtype=dp, + product=inst, + expver=1, + param=129/130/145, + class=od, + date=20120101, + type=of, + step=24/to/96/by/24, + expect=60, + database=marsod, + target=data.reference \ No newline at end of file diff --git a/tests/expand/MARSC-264.expected b/tests/expand/MARSC-264.expected new file mode 100644 index 00000000..4369707e --- /dev/null +++ b/tests/expand/MARSC-264.expected @@ -0,0 +1,18 @@ + RETRIEVE, + CLASS = OD, + TYPE = FCMAX, + STREAM = SFMM, + EXPVER = 0001, + REPRES = GG, + LEVTYPE = SFC, + PARAM = 167, + DATE = 19911001, + FCMONTH = 2/3/4, + TIME = 0000, + NUMBER = 0/1/2/3/4, + DOMAIN = G, + SYSTEM = 2, + METHOD = 1, + SOURCE = mod.cl.surface, + TARGET = data.reference, + DATABASE = file \ No newline at end of file diff --git a/tests/expand/MARSC-264.req b/tests/expand/MARSC-264.req new file mode 100644 index 00000000..854bf7ea --- /dev/null +++ b/tests/expand/MARSC-264.req @@ -0,0 +1,17 @@ +retrieve, + class=od, + type=fcmax, + stream=sfmm, + expver=0001, + repres=gg, + levtype=sfc, + param=167, + date=19911001, + fcmonth=02/03/04, + time=0000, + number=0/1/2/3/4, + domain=g, + system=02, + method=01, + source="mod.cl.surface", + target="data.reference" \ No newline at end of file diff --git a/tests/expand/MARSC-267 copy.expected b/tests/expand/MARSC-267 copy.expected new file mode 100644 index 00000000..48ba21de --- /dev/null +++ b/tests/expand/MARSC-267 copy.expected @@ -0,0 +1,19 @@ +RETRIEVE, + CLASS = S2, + TYPE = PF, + STREAM = ENFH, + EXPVER = prod, + REPRES = SH, + LEVTYPE = PL, + LEVELIST = 200/300/500/700/850/925/1000, + PARAM = 130, + DATE = 20240111, + HDATE = 2004-01-11, + TIME = 0000, + STEP = 0/24/48/72/96/120/144/168/192/216/240/264/288/312/336/360/384/408/432/456/480/504/528/552/576/600/624/648/672/696/720/744/768/792/816/840/864/888/912/936/960/984/1008/1032/1056/1080/1104, + NUMBER = 1, + ORIGIN = ECMF, + TARGET = target.out, + AREA = 40/-180/-40/180, + PADDING = 0, + PROCESS = LOCAL \ No newline at end of file diff --git a/tests/expand/MARSC-267.expected b/tests/expand/MARSC-267.expected new file mode 100644 index 00000000..1707b0d8 --- /dev/null +++ b/tests/expand/MARSC-267.expected @@ -0,0 +1,18 @@ +RETRIEVE, + CLASS = S2, + TYPE = PF, + STREAM = ENFH, + EXPVER = prod, + REPRES = SH, + LEVTYPE = PL, + LEVELIST = 200/300/500/700/850/925/1000, + PARAM = 130, + DATE = 20240111, + HDATE = 20040111, + TIME = 0000, + STEP = 0/24/48/72/96/120/144/168/192/216/240/264/288/312/336/360/384/408/432/456/480/504/528/552/576/600/624/648/672/696/720/744/768/792/816/840/864/888/912/936/960/984/1008/1032/1056/1080/1104, + NUMBER = 1, + ORIGIN = ECMF, + TARGET = target.out, + AREA = 40/-180/-40/180, + PADDING = 0 \ No newline at end of file diff --git a/tests/expand/MARSC-267.req b/tests/expand/MARSC-267.req new file mode 100644 index 00000000..5beda736 --- /dev/null +++ b/tests/expand/MARSC-267.req @@ -0,0 +1 @@ +retrieve,area=40/-180/-40/180,class=s2,date=2024-01-11,expver=prod,levtype=pl,padding=0,param=130,step=0/to/1104/by/24,stream=enfh,time=00:00:00,type=pf,levelist=200/300/500/700/850/925/1000,number=1,origin=ecmf,hdate=2004-01-11,target=target.out \ No newline at end of file diff --git a/tests/regressions/METK-89/METK-89.sh.in b/tests/regressions/METK-89/METK-89.sh.in index a90c2908..c947cea0 100755 --- a/tests/regressions/METK-89/METK-89.sh.in +++ b/tests/regressions/METK-89/METK-89.sh.in @@ -68,11 +68,11 @@ EOF $parse req cat > req.porcelain < req.json < +#include +#include + +#include "eckit/testing/Test.h" + +#include "metkit/mars/MarsExpandContext.h" +#include "metkit/mars/MarsLanguage.h" +#include "metkit/mars/Type.h" + +namespace metkit::mars::test { + +using ::eckit::BadValue; + +//----------------------------------------------------------------------------- + +CASE("Context match") { + + Context c; + std::set cc{"s2", "ti"}; + c.add(std::make_unique("class", cc)); + std::set tt{"cf"}; + c.add(std::make_unique("type", tt)); + + std::string text = + "retrieve, " + "class=ti,date=20250414,time=12,origin=all,expver=all,type=cf,stream=enfo,levtype=sfc,param=2t,step=24,expect=" + "any,target=data.reference"; + + metkit::mars::MarsRequest r = MarsRequest::parse(text, true); + + EXPECT(c.matches(r)); +} + + +//----------------------------------------------------------------------------- + +} // namespace metkit::mars::test + +int main(int argc, char** argv) { + return eckit::testing::run_tests(argc, argv); +} diff --git a/tests/test_date.cc b/tests/test_date.cc index f36b8e4d..32458f80 100644 --- a/tests/test_date.cc +++ b/tests/test_date.cc @@ -16,6 +16,7 @@ #include #include "eckit/testing/Test.h" +#include "eckit/types/Date.h" #include "eckit/value/Value.h" #include "metkit/mars/MarsExpandContext.h" @@ -32,7 +33,7 @@ using ::eckit::Value; void assertTypeExpansion(const std::string& name, std::vector values, const std::vector& expected) { static MarsLanguage language("retrieve"); - language.type(name)->expand(DummyContext(), values); + language.type(name)->expand(DummyContext{}, MarsRequest{}, values); EXPECT_EQUAL(expected, values); } @@ -41,6 +42,7 @@ CASE("Test TypeDate expansions") { TypeDate tdate("date", Value()); Type& td(tdate); DummyContext ctx; + MarsRequest r; assertTypeExpansion("date", {"20140506"}, {"20140506"}); assertTypeExpansion("date", {"2014-05-06"}, {"20140506"}); @@ -50,23 +52,36 @@ CASE("Test TypeDate expansions") { assertTypeExpansion("date", {"20140506", "to", "20140508"}, {"20140506", "20140507", "20140508"}); assertTypeExpansion("date", {"20140504", "20140506", "to", "20140508"}, {"20140504", "20140506", "20140507", "20140508"}); - assertTypeExpansion("date", {"2"}, {"2"}); - assertTypeExpansion("date", {"jan"}, {"1"}); - assertTypeExpansion("date", {"1-01"}, {"101"}); - assertTypeExpansion("date", {"jan-01"}, {"101"}); - assertTypeExpansion("date", {"feb-23"}, {"223"}); + assertTypeExpansion("date", {"2"}, {"feb"}); + assertTypeExpansion("date", {"jan"}, {"jan"}); + assertTypeExpansion("date", {"september"}, {"sep"}); + assertTypeExpansion("date", {"9"}, {"sep"}); + assertTypeExpansion("date", {"1-01"}, {"jan-1"}); + assertTypeExpansion("date", {"jan-01"}, {"jan-1"}); + assertTypeExpansion("date", {"january-01"}, {"jan-1"}); + assertTypeExpansion("date", {"feb-23"}, {"feb-23"}); + assertTypeExpansion("date", {"2018-23"}, {"20180123"}); + assertTypeExpansion("date", {"2018-41"}, {"20180210"}); { std::string value = "20141506"; - EXPECT_THROWS(td.expand(ctx, value)); // throws BadDate that is not exported + EXPECT_THROWS(td.expand(ctx, r, value)); // throws BadDate that is not exported + } + { + std::string value = "20180132"; + EXPECT_THROWS(td.expand(ctx, r, value)); // throws BadDate that is not exported + } + { + std::string value = "202401366"; + EXPECT_THROWS(td.expand(ctx, r, value)); // throws BadDate that is not exported } { std::string value = "abc"; - EXPECT_THROWS_AS(td.expand(ctx, value), BadValue); + EXPECT_THROWS_AS(td.expand(ctx, r, value), BadValue); } { std::string value = "abc-01"; - EXPECT_THROWS_AS(td.expand(ctx, value), BadValue); + EXPECT_THROWS_AS(td.expand(ctx, r, value), BadValue); } } diff --git a/tests/test_expand.cc b/tests/test_expand.cc index 254168ba..a52ef651 100644 --- a/tests/test_expand.cc +++ b/tests/test_expand.cc @@ -13,8 +13,12 @@ /// @author Florian Rathgeber /// @author Emanuele Danovaro +#include +#include #include +#include "eckit/filesystem/LocalPathName.h" +#include "eckit/filesystem/StdDir.h" #include "eckit/types/Date.h" #include "eckit/utils/StringTools.h" #include "metkit/mars/MarsExpansion.h" @@ -31,75 +35,130 @@ using namespace eckit::testing; namespace metkit::mars::test { namespace { -using ExpectedOutput = std::map>; +using ExpectedVals = std::map>; + +/** + * @brief We can specify a set of keys which should be ignored when not specified in the user request. + * In case the user requests defines them, check them regardless. This is mean to ignore auto-injected + * keys e.g. for resol. + */ +std::set ignore_{"repres", "resol"}; + +std::string date(long d) { + if (d <= 0) { + eckit::Date day(d); + d = day.yyyymmdd(); + } + return std::to_string(d); } -//----------------------------------------------------------------------------- +std::string date(std::string d) { + if (d == "0" || d[0] == '-') { + long dd = std::stol(d); + eckit::Date day(dd); + return std::to_string(day.yyyymmdd()); + } + return d; +} +struct ExpectedRequest { -void expand(const MarsRequest& r, const std::string& verb, const ExpectedOutput& expected, - const std::vector dates) { - // std::cout << "comparing " << r << " with " << expected << " dates " << dates << std::endl; - EXPECT_EQUAL(verb, r.verb()); - for (const auto& e : expected) { - if (!r.has(e.first)) { - std::cerr << eckit::Colour::red << "Missing keyword: " << e.first << eckit::Colour::reset << std::endl; - } - EXPECT(r.has(e.first)); - auto vv = r.values(e.first); - if (e.first != "date") { // dates are verified at a later stage - EXPECT_EQUAL(e.second.size(), vv.size()); + ExpectedRequest() = default; + + ExpectedRequest(std::string vrb, ExpectedVals vv, std::vector dd) : verb(vrb), vals(vv), dates(dd) {} + + ExpectedRequest(std::string vrb, ExpectedVals vv, std::vector dd) : verb(vrb), vals(vv) { + dates.reserve(dd.size()); + for (long d : dd) { + dates.push_back(date(d)); } - for (int i = 0; i < vv.size(); i++) { - if (e.first == "grid") { - EXPECT_EQUAL(eckit::StringTools::upper(e.second.at(i)), vv.at(i)); + } + + std::string verb; + ExpectedVals vals; + std::vector dates; +}; +} // namespace + +//----------------------------------------------------------------------------- + + +void expand(const MarsRequest& r, const ExpectedRequest& expected, std::set ignore) { + try { + EXPECT_EQUAL(expected.verb, r.verb()); + for (const auto& e : expected.vals) { + if (!r.has(e.first)) { + if (ignore.find(e.first) != ignore.end()) { + continue; + } + std::cerr << eckit::Colour::red << "Missing keyword: " << e.first << eckit::Colour::reset << std::endl; } - else { - EXPECT_EQUAL(e.second.at(i), vv.at(i)); + EXPECT(r.has(e.first)); + auto vv = r.values(e.first); + if (e.first != "date") { // dates are verified at a later stage + EXPECT_EQUAL(e.second.size(), vv.size()); + } + for (int i = 0; i < vv.size(); i++) { + if (e.first == "grid") { + EXPECT_EQUAL(eckit::StringTools::upper(e.second.at(i)), vv.at(i)); + } + else { + EXPECT_EQUAL(e.second.at(i), vv.at(i)); + } } } - } - if (dates.size() > 0) { - EXPECT(r.has("date")); - auto dd = r.values("date"); - EXPECT_EQUAL(dates.size(), dd.size()); - for (int i = 0; i < dates.size(); i++) { - long d = dates.at(i); - if (d < 0) { - eckit::Date day(d); - d = day.yyyymmdd(); + if (expected.dates.size() > 0) { + EXPECT(r.has("date")); + auto dd = r.values("date"); + EXPECT_EQUAL(expected.dates.size(), dd.size()); + for (int i = 0; i < expected.dates.size(); i++) { + EXPECT_EQUAL(date(expected.dates.at(i)), dd.at(i)); } - EXPECT_EQUAL(std::to_string(d), dd.at(i)); } } + catch (...) { + std::cerr << "Error comparing " << r << " with " << expected.vals << " dates " << expected.dates << std::endl; + throw; + } +} + +void expand(const MarsRequest& r, const std::string& verb, const ExpectedVals& expected, std::vector& dates, + std::set ignore) { + expand(r, {verb, expected, dates}, ignore); } -void expand(const std::string& text, const std::string& verb, const ExpectedOutput& expected, std::vector dates, +void expand(const std::string& text, const std::string& verb, const ExpectedVals& expected, std::vector dates, bool strict = false) { MarsRequest r = MarsRequest::parse(text, strict); - expand(r, verb, expected, std::move(dates)); + std::set ignore; + std::string tt = eckit::StringTools::lower(text); + for (const auto& i : ignore_) { + auto idx = tt.find(i); + if (idx == std::string::npos) { + ignore.insert(i); + } + } + expand(r, {verb, expected, dates}, ignore); } -void expand(const std::string& text, const std::string& expected, bool strict = false, std::vector dates = {}) { - ExpectedOutput out; +void parse(const std::string& req, ExpectedRequest& expected) { eckit::Tokenizer c(","); eckit::Tokenizer e("="); eckit::Tokenizer s("/"); eckit::StringList tokens; - c(expected, tokens); - std::string verb; + c(req, tokens); for (const auto& t : tokens) { - if (verb.empty()) { - verb = eckit::StringTools::lower(t); + auto tt = eckit::StringTools::trim(t); + if (expected.verb.empty()) { + expected.verb = eckit::StringTools::lower(tt); continue; } - auto tt = eckit::StringTools::trim(t); eckit::StringList kv; e(tt, kv); EXPECT_EQUAL(2, kv.size()); auto key = eckit::StringTools::lower(eckit::StringTools::trim(kv[0])); if (key == "date") { - EXPECT_EQUAL(0, dates.size()); + EXPECT_EQUAL(0, expected.dates.size()); } eckit::StringList vals; s(kv[1], vals); @@ -110,27 +169,76 @@ void expand(const std::string& text, const std::string& expected, bool strict = val = eckit::StringTools::lower(val); } if (key == "date") { - dates.push_back(std::stol(val)); + + expected.dates.push_back(date(val)); } else { vv.push_back(val); } } if (key != "date") { - out.emplace(key, vv); + expected.vals.emplace(key, vv); } } +} +void expand(const std::string& text, const std::string& expected, bool strict = false, std::vector dates = {}) { + ExpectedRequest out; + out.dates.reserve(dates.size()); + for (long d : dates) { + out.dates.push_back(date(d)); + } + parse(expected, out); MarsRequest r = MarsRequest::parse(text, strict); - expand(r, verb, out, std::move(dates)); + std::set ignore; + std::string tt = eckit::StringTools::lower(text); + for (const auto& i : ignore_) { + auto idx = tt.find(i); + if (idx == std::string::npos) { + ignore.insert(i); + } + } + expand(r, out, ignore); +} +void expand(const std::string& text, const std::vector& expected, bool strict = false, + std::vector> dates = {}) { + ExpectedVals out; + + std::istringstream in(text); + std::vector reqs = MarsRequest::parse(in, strict); + + std::set ignore; + std::string tt = eckit::StringTools::lower(text); + for (const auto& i : ignore_) { + auto idx = tt.find(i); + if (idx == std::string::npos) { + ignore.insert(i); + } + } + + ASSERT(dates.size() == 0 || dates.size() == expected.size()); + + EXPECT_EQUAL(expected.size(), reqs.size()); + + for (size_t i = 0; i < expected.size(); i++) { + ExpectedRequest expectedReq; + if (dates.size() != 0) { + expectedReq.dates.reserve(dates.at(i).size()); + for (long d : dates.at(i)) { + expectedReq.dates.push_back(date(d)); + } + } + parse(expected.at(i), expectedReq); + expand(reqs.at(i), expectedReq, ignore); + } } CASE("test_metkit_expand_1") { const char* text = "ret,date=-5/to/-1"; - ExpectedOutput expected{{"class", {"od"}}, {"domain", {"g"}}, - {"expver", {"0001"}}, {"levelist", {"1000", "850", "700", "500", "400", "300"}}, - {"levtype", {"pl"}}, {"param", {"129"}}, - {"step", {"0"}}, {"stream", {"oper"}}, - {"time", {"1200"}}, {"type", {"an"}}}; + ExpectedVals expected{{"class", {"od"}}, {"domain", {"g"}}, + {"expver", {"0001"}}, {"levelist", {"1000", "850", "700", "500", "400", "300"}}, + {"levtype", {"pl"}}, {"param", {"129"}}, + {"step", {"0"}}, {"stream", {"oper"}}, + {"time", {"1200"}}, {"type", {"an"}}}; expand(text, "retrieve", expected, {-5, -4, -3, -2, -1}); const char* text2 = "ret,date=-5/to/-1."; @@ -139,55 +247,55 @@ CASE("test_metkit_expand_1") { const char* expectedStr = "RETRIEVE,CLASS=OD,TYPE=AN,STREAM=OPER,EXPVER=0001,REPRES=SH,LEVTYPE=PL,LEVELIST=1000/850/700/500/400/" "300,PARAM=129,TIME=1200,STEP=0,DOMAIN=G"; - expand(text, expectedStr, true, {-5, -4, -3, -2, -1}); + expand(text, expectedStr, false, {-5, -4, -3, -2, -1}); } CASE("test_metkit_expand_2") { { const char* text = "ret,date=-1"; - ExpectedOutput expected{{"class", {"od"}}, {"domain", {"g"}}, - {"expver", {"0001"}}, {"levelist", {"1000", "850", "700", "500", "400", "300"}}, - {"levtype", {"pl"}}, {"param", {"129"}}, - {"step", {"0"}}, {"stream", {"oper"}}, - {"time", {"1200"}}, {"type", {"an"}}}; + ExpectedVals expected{{"class", {"od"}}, {"domain", {"g"}}, + {"expver", {"0001"}}, {"levelist", {"1000", "850", "700", "500", "400", "300"}}, + {"levtype", {"pl"}}, {"param", {"129"}}, + {"step", {"0"}}, {"stream", {"oper"}}, + {"time", {"1200"}}, {"type", {"an"}}}; expand(text, "retrieve", expected, {-1}); } { const char* text = "ret,levtype=ml"; - ExpectedOutput expected{{"class", {"od"}}, - {"domain", {"g"}}, - {"expver", {"0001"}}, - {"levelist", {"1000", "850", "700", "500", "400", "300"}}, - // {"levelist", {"1","2"}}, // keeping the old default, for MARS client tests - {"levtype", {"ml"}}, - {"param", {"129"}}, - {"step", {"0"}}, - {"stream", {"oper"}}, - {"time", {"1200"}}, - {"type", {"an"}}}; + ExpectedVals expected{{"class", {"od"}}, + {"domain", {"g"}}, + {"expver", {"0001"}}, + {"levelist", {"1000", "850", "700", "500", "400", "300"}}, + // {"levelist", {"1","2"}}, // keeping the old default, for MARS client tests + {"levtype", {"ml"}}, + {"param", {"129"}}, + {"step", {"0"}}, + {"stream", {"oper"}}, + {"time", {"1200"}}, + {"type", {"an"}}}; expand(text, "retrieve", expected, {-1}); } } CASE("test_metkit_expand_3") { const char* text = "ret,date=-5/to/-1,grid=n640"; - ExpectedOutput expected{{"class", {"od"}}, {"domain", {"g"}}, - {"expver", {"0001"}}, {"levelist", {"1000", "850", "700", "500", "400", "300"}}, - {"levtype", {"pl"}}, {"param", {"129"}}, - {"step", {"0"}}, {"stream", {"oper"}}, - {"time", {"1200"}}, {"type", {"an"}}, - {"grid", {"N640"}}}; + ExpectedVals expected{{"class", {"od"}}, {"domain", {"g"}}, + {"expver", {"0001"}}, {"levelist", {"1000", "850", "700", "500", "400", "300"}}, + {"levtype", {"pl"}}, {"param", {"129"}}, + {"step", {"0"}}, {"stream", {"oper"}}, + {"time", {"1200"}}, {"type", {"an"}}, + {"grid", {"N640"}}}; expand(text, "retrieve", expected, {-5, -4, -3, -2, -1}); } CASE("test_metkit_expand_4") { const char* text = "ret,date=-5/to/-1,grid=o640"; - ExpectedOutput expected{{"class", {"od"}}, {"domain", {"g"}}, - {"expver", {"0001"}}, {"levelist", {"1000", "850", "700", "500", "400", "300"}}, - {"levtype", {"pl"}}, {"param", {"129"}}, - {"step", {"0"}}, {"stream", {"oper"}}, - {"time", {"1200"}}, {"type", {"an"}}, - {"grid", {"O640"}}}; + ExpectedVals expected{{"class", {"od"}}, {"domain", {"g"}}, + {"expver", {"0001"}}, {"levelist", {"1000", "850", "700", "500", "400", "300"}}, + {"levtype", {"pl"}}, {"param", {"129"}}, + {"step", {"0"}}, {"stream", {"oper"}}, + {"time", {"1200"}}, {"type", {"an"}}, + {"grid", {"O640"}}}; expand(text, "retrieve", expected, {-5, -4, -3, -2, -1}); } @@ -195,9 +303,9 @@ CASE("test_metkit_expand_5") { const char* text = "retrieve,class=od,date=20050601,diagnostic=1,expver=1,iteration=0,levelist=1,levtype=ml,param=155.129,stream=" "sens,time=1200,type=sg"; - ExpectedOutput expected{{"class", {"od"}}, {"diagnostic", {"1"}}, {"domain", {"g"}}, {"expver", {"0001"}}, - {"iteration", {"0"}}, {"levelist", {"1"}}, {"levtype", {"ml"}}, {"param", {"129155"}}, - {"step", {"0"}}, {"stream", {"sens"}}, {"time", {"1200"}}, {"type", {"sg"}}}; + ExpectedVals expected{{"class", {"od"}}, {"diagnostic", {"1"}}, {"domain", {"g"}}, {"expver", {"0001"}}, + {"iteration", {"0"}}, {"levelist", {"1"}}, {"levtype", {"ml"}}, {"param", {"129155"}}, + {"step", {"0"}}, {"stream", {"sens"}}, {"time", {"1200"}}, {"type", {"sg"}}}; expand(text, "retrieve", expected, {20050601}); } @@ -205,9 +313,9 @@ CASE("test_metkit_expand_6") { const char* text = "retrieve,class=rd,expver=hl1m,stream=oper,date=20000801,time=0000,domain=g,type=fc,levtype=pl,step=24,param=" "129,levelist=1/to/31"; - ExpectedOutput expected{{"class", {"rd"}}, {"expver", {"hl1m"}}, {"stream", {"oper"}}, - {"time", {"0000"}}, {"domain", {"g"}}, {"type", {"fc"}}, - {"levtype", {"pl"}}, {"step", {"24"}}, {"param", {"129"}}}; + ExpectedVals expected{{"class", {"rd"}}, {"expver", {"hl1m"}}, {"stream", {"oper"}}, + {"time", {"0000"}}, {"domain", {"g"}}, {"type", {"fc"}}, + {"levtype", {"pl"}}, {"step", {"24"}}, {"param", {"129"}}}; std::vector levelist; for (int i = 1; i <= 31; i++) { levelist.push_back(std::to_string(i)); @@ -220,9 +328,9 @@ CASE("test_metkit_expand_7") { const char* text = "retrieve,class=rd,expver=hl1m,stream=oper,date=20000801,time=0000,domain=g,type=fc,levtype=pl,step=24,param=" "129,levelist=0.01/0.7"; - ExpectedOutput expected{{"class", {"rd"}}, {"expver", {"hl1m"}}, {"stream", {"oper"}}, {"time", {"0000"}}, - {"domain", {"g"}}, {"type", {"fc"}}, {"levtype", {"pl"}}, {"step", {"24"}}, - {"param", {"129"}}, {"levelist", {".01", ".7"}}}; + ExpectedVals expected{{"class", {"rd"}}, {"expver", {"hl1m"}}, {"stream", {"oper"}}, {"time", {"0000"}}, + {"domain", {"g"}}, {"type", {"fc"}}, {"levtype", {"pl"}}, {"step", {"24"}}, + {"param", {"129"}}, {"levelist", {".01", ".7"}}}; expand(text, "retrieve", expected, {20000801}); } @@ -230,11 +338,11 @@ CASE("test_metkit_expand_8") { const char* text = "retrieve,class=rd,expver=hl1m,stream=oper,date=20000801,time=0000,domain=g,type=fc,levtype=pl,step=24,param=" "129,levelist=0.1/to/0.7/by/0.2"; - ExpectedOutput expected{{"class", {"rd"}}, {"expver", {"hl1m"}}, - {"stream", {"oper"}}, {"time", {"0000"}}, - {"domain", {"g"}}, {"type", {"fc"}}, - {"levtype", {"pl"}}, {"step", {"24"}}, - {"param", {"129"}}, {"levelist", {".1", ".3", ".5", ".7"}}}; + ExpectedVals expected{{"class", {"rd"}}, {"expver", {"hl1m"}}, + {"stream", {"oper"}}, {"time", {"0000"}}, + {"domain", {"g"}}, {"type", {"fc"}}, + {"levtype", {"pl"}}, {"step", {"24"}}, + {"param", {"129"}}, {"levelist", {".1", ".3", ".5", ".7"}}}; expand(text, "retrieve", expected, {20000801}); } @@ -293,28 +401,63 @@ CASE("test_metkit_expand_10_strict") { CASE("test_metkit_expand_multirequest-1") { const std::string text = "ret,date=-5/to/-2.\nret,date=-1"; std::istringstream in(text); - std::vector reqs = MarsRequest::parse(in, true); + std::vector reqs = MarsRequest::parse(in, false); EXPECT_EQUAL(reqs.size(), 2); - ExpectedOutput expected{{"class", {"od"}}, {"domain", {"g"}}, - {"expver", {"0001"}}, {"levelist", {"1000", "850", "700", "500", "400", "300"}}, - {"levtype", {"pl"}}, {"param", {"129"}}, - {"step", {"0"}}, {"stream", {"oper"}}, - {"time", {"1200"}}, {"type", {"an"}}}; - expand(reqs.at(0), "retrieve", expected, {-5, -4, -3, -2}); - expand(reqs.at(1), "retrieve", expected, {-1}); + ExpectedVals expected{{"class", {"od"}}, {"domain", {"g"}}, + {"expver", {"0001"}}, {"levelist", {"1000", "850", "700", "500", "400", "300"}}, + {"levtype", {"pl"}}, {"param", {"129"}}, + {"step", {"0"}}, {"stream", {"oper"}}, + {"time", {"1200"}}, {"type", {"an"}}}; + + expand(reqs.at(0), {"retrieve", expected, std::vector{-5, -4, -3, -2}}, ignore_); + expand(reqs.at(1), {"retrieve", expected, std::vector{-1}}, ignore_); +} + +CASE("test_metkit_expand_multirequest-2") { + const std::string text = "ret,date=-5/to/-2.\nret,date=-1"; + std::string expectedStr = + "retrieve,class=od,domain=g,expver=0001,levelist=1000/850/700/500/400/" + "300,levtype=pl,param=129,step=0,stream=oper,time=1200,type=an"; + expand(text, {expectedStr, expectedStr}, false, {{-5, -4, -3, -2}, {-1}}); +} + +CASE("test_metkit_expand_multirequest-3") { + const char* text = + "retrieve,accuracy=16,area=14.8/-19.6/-14.5/19.8,class=od,date=20230810,expver=1,grid=0.09/0.09,levelist=1/" + "to/137,levtype=ml,number=-1,param=z,process=local,rotation=-78.8/-61.0,step=000,stream=scda,time=18," + "type=an,target=\"reference.ect1qF.data\"\n" + "ret,rotation=off,target=\"out\""; + const char* expected1 = + "RETRIEVE,CLASS=OD,TYPE=AN,STREAM=SCDA,EXPVER=0001,REPRES=SH,LEVTYPE=ML,LEVELIST=1/2/3/4/5/6/7/8/9/10/11/" + "12/13/14/15/16/17/18/19/20/21/22/23/24/25/26/27/28/29/30/31/32/33/34/35/36/37/38/39/40/41/42/43/44/45/46/" + "47/48/49/50/51/52/53/54/55/56/57/58/59/60/61/62/63/64/65/66/67/68/69/70/71/72/73/74/75/76/77/78/79/80/81/" + "82/83/84/85/86/87/88/89/90/91/92/93/94/95/96/97/98/99/100/101/102/103/104/105/106/107/108/109/110/111/112/" + "113/114/115/116/117/118/119/120/121/122/123/124/125/126/127/128/129/130/131/132/133/134/135/136/137," + "PARAM=129,DATE=20230810,TIME=1800,STEP=0,DOMAIN=G,TARGET=reference.ect1qF.data,RESOL=AUTO,ACCURACY=16," + "AREA=14.8/-19.6/-14.5/19.8,ROTATION=-78.8/-61,GRID=.09/.09,PROCESS=LOCAL"; + const char* expected2 = + "RETRIEVE,CLASS=OD,TYPE=AN,STREAM=SCDA,EXPVER=0001,REPRES=SH,LEVTYPE=ML,LEVELIST=1/2/3/4/5/6/7/8/9/10/11/" + "12/13/14/15/16/17/18/19/20/21/22/23/24/25/26/27/28/29/30/31/32/33/34/35/36/37/38/39/40/41/42/43/44/45/46/" + "47/48/49/50/51/52/53/54/55/56/57/58/59/60/61/62/63/64/65/66/67/68/69/70/71/72/73/74/75/76/77/78/79/80/81/" + "82/83/84/85/86/87/88/89/90/91/92/93/94/95/96/97/98/99/100/101/102/103/104/105/106/107/108/109/110/111/112/" + "113/114/115/116/117/118/119/120/121/122/123/124/125/126/127/128/129/130/131/132/133/134/135/136/137," + "PARAM=129,DATE=20230810,TIME=1800,STEP=0,DOMAIN=G,TARGET=out,RESOL=AUTO,ACCURACY=16," + "AREA=14.8/-19.6/-14.5/19.8,GRID=.09/.09,PROCESS=LOCAL"; + + expand(text, std::vector{expected1, expected2}); } void expandKeyThrows(const std::string& key, std::vector values) { DummyContext ctx; static metkit::mars::MarsLanguage language("retrieve"); metkit::mars::Type* t = language.type(key); - EXPECT_THROWS_AS(t->expand(ctx, values), eckit::BadValue); + EXPECT_THROWS_AS(t->expand(ctx, MarsRequest{}, values), eckit::BadValue); } void expandKey(const std::string& key, std::vector values, std::vector expected) { DummyContext ctx; static metkit::mars::MarsLanguage language("retrieve"); metkit::mars::Type* t = language.type(key); - t->expand(ctx, values); + t->expand(ctx, MarsRequest{}, values); EXPECT_EQUAL(expected, values); } @@ -634,34 +777,25 @@ CASE("test_metkit_expand_param") { CASE("test_metkit_expand_d1") { { const char* text = "retrieve,class=d1,dataset=extremes-dt,date=-1"; - ExpectedOutput expected{{"class", {"d1"}}, {"dataset", {"extremes-dt"}}, - {"expver", {"0001"}}, {"levelist", {"1000", "850", "700", "500", "400", "300"}}, - {"levtype", {"pl"}}, {"param", {"129"}}, - {"step", {"0"}}, {"stream", {"oper"}}, - {"time", {"1200"}}, {"type", {"an"}}}; - expand(text, "retrieve", expected, {-1}); - } - { - const char* text = "retrieve,class=d1,dataset=extreme-dt,date=-1"; - ExpectedOutput expected{{"class", {"d1"}}, {"dataset", {"extremes-dt"}}, - {"expver", {"0001"}}, {"levelist", {"1000", "850", "700", "500", "400", "300"}}, - {"levtype", {"pl"}}, {"param", {"129"}}, - {"step", {"0"}}, {"stream", {"oper"}}, - {"time", {"1200"}}, {"type", {"an"}}}; + ExpectedVals expected{{"class", {"d1"}}, {"dataset", {"extremes-dt"}}, + {"expver", {"0001"}}, {"levelist", {"1000", "850", "700", "500", "400", "300"}}, + {"levtype", {"pl"}}, {"param", {"129"}}, + {"step", {"0"}}, {"stream", {"oper"}}, + {"time", {"1200"}}, {"type", {"an"}}}; expand(text, "retrieve", expected, {-1}); } { const char* text = "retrieve,class=d1,dataset=climate-dt,levtype=pl,date=20000101,activity=CMIP6,experiment=hist,model=IFS-" "NEMO,generation=1,realization=1,resolution=high,stream=clte,type=fc,param=134/137"; - ExpectedOutput expected{{"class", {"d1"}}, {"dataset", {"climate-dt"}}, - {"activity", {"cmip6"}}, {"experiment", {"hist"}}, - {"model", {"ifs-nemo"}}, {"generation", {"1"}}, - {"realization", {"1"}}, {"resolution", {"high"}}, - {"expver", {"0001"}}, {"time", {"1200"}}, - {"stream", {"clte"}}, {"type", {"fc"}}, - {"levtype", {"pl"}}, {"levelist", {"1000", "850", "700", "500", "400", "300"}}, - {"param", {"134", "137"}}}; + ExpectedVals expected{{"class", {"d1"}}, {"dataset", {"climate-dt"}}, + {"activity", {"cmip6"}}, {"experiment", {"hist"}}, + {"model", {"ifs-nemo"}}, {"generation", {"1"}}, + {"realization", {"1"}}, {"resolution", {"high"}}, + {"expver", {"0001"}}, {"time", {"1200"}}, + {"stream", {"clte"}}, {"type", {"fc"}}, + {"levtype", {"pl"}}, {"levelist", {"1000", "850", "700", "500", "400", "300"}}, + {"param", {"134", "137"}}}; expand(text, "retrieve", expected, {20000101}); } { @@ -673,11 +807,12 @@ CASE("test_metkit_expand_d1") { "retrieve,date=20120515,time=0000,dataset=climate-dt,activity=cmip6,experiment=hist,generation=1,model=" "icon,realization=1,resolution=high,class=d1,expver=0001,type=fc,stream=clte,levelist=1," "levtype=o3d,param=263500"; - ExpectedOutput expected{{"class", {"d1"}}, {"dataset", {"climate-dt"}}, {"activity", {"cmip6"}}, - {"experiment", {"hist"}}, {"model", {"icon"}}, {"generation", {"1"}}, - {"realization", {"1"}}, {"resolution", {"high"}}, {"expver", {"0001"}}, - {"time", {"0000"}}, {"stream", {"clte"}}, {"type", {"fc"}}, - {"levtype", {"o3d"}}, {"levelist", {"1"}}, {"param", {"263500"}}}; + ExpectedVals expected{{"class", {"d1"}}, {"dataset", {"climate-dt"}}, {"activity", {"cmip6"}}, + {"experiment", {"hist"}}, {"model", {"icon"}}, {"generation", {"1"}}, + {"realization", {"1"}}, {"resolution", {"high"}}, {"expver", {"0001"}}, + {"time", {"0000"}}, {"stream", {"clte"}}, {"type", {"fc"}}, + {"levtype", {"o3d"}}, {"levelist", {"1"}}, {"param", {"263500"}}}; + expand(text, "retrieve", expected, {20120515}); expand(text2, "retrieve", expected, {20120515}); } } @@ -686,21 +821,21 @@ CASE("test_metkit_expand_ng") { const char* text = "retrieve,class=ng,date=20000101,activity=CMIP6,experiment=hist,model=IFS-NEMO,generation=1,realization=1," "resolution=high,stream=clte,type=fc,levtype=pl,param=134/137"; - ExpectedOutput expected{{"class", {"ng"}}, - {"levtype", {"pl"}}, - {"levelist", {"1000", "850", "700", "500", "400", "300"}}, - {"activity", {"cmip6"}}, - {"experiment", {"hist"}}, - {"model", {"ifs-nemo"}}, - {"generation", {"1"}}, - {"realization", {"1"}}, - {"resolution", {"high"}}, - {"expver", {"0001"}}, - {"date", {"20000101"}}, - {"time", {"1200"}}, - {"stream", {"clte"}}, - {"type", {"fc"}}, - {"param", {"134", "137"}}}; + ExpectedVals expected{{"class", {"ng"}}, + {"levtype", {"pl"}}, + {"levelist", {"1000", "850", "700", "500", "400", "300"}}, + {"activity", {"cmip6"}}, + {"experiment", {"hist"}}, + {"model", {"ifs-nemo"}}, + {"generation", {"1"}}, + {"realization", {"1"}}, + {"resolution", {"high"}}, + {"expver", {"0001"}}, + {"date", {"20000101"}}, + {"time", {"1200"}}, + {"stream", {"clte"}}, + {"type", {"fc"}}, + {"param", {"134", "137"}}}; expand(text, "retrieve", expected, {20000101}); } } @@ -708,10 +843,10 @@ CASE("test_metkit_expand_ai") { { const char* text = "retrieve,class=ai,date=20250208,time=1800,expver=9999,model=aifs-single,type=fc,levtype=sfc,param=169"; - ExpectedOutput expected{{"class", {"ai"}}, {"domain", {"g"}}, {"expver", {"9999"}}, - {"levtype", {"sfc"}}, {"step", {"0"}}, {"stream", {"oper"}}, - {"time", {"1800"}}, {"type", {"fc"}}, {"model", {"aifs-single"}}, - {"param", {"169"}}}; + ExpectedVals expected{{"class", {"ai"}}, {"domain", {"g"}}, {"expver", {"9999"}}, + {"levtype", {"sfc"}}, {"step", {"0"}}, {"stream", {"oper"}}, + {"time", {"1800"}}, {"type", {"fc"}}, {"model", {"aifs-single"}}, + {"param", {"169"}}}; expand(text, "retrieve", expected, {20250208}); } } @@ -722,21 +857,21 @@ CASE("test_metkit_expand_list") { "list,date=20250105,domain=g,levtype=pl,expver=" "0001,step=0,stream=oper,levelist=1000/850/700/500/400/" "300,time=1200,type=an,param=129"; - ExpectedOutput expected{{"class", {"od"}}, - {"date", {"20250105"}}, - {"domain", {"g"}}, - {"levtype", {"pl"}}, - {"levelist", {"1000", "850", "700", "500", "400", "300"}}, - {"expver", {"0001"}}, - {"time", {"1200"}}, - {"stream", {"oper"}}, - {"type", {"an"}}, - {"param", {"129"}}}; + ExpectedVals expected{{"class", {"od"}}, + {"date", {"20250105"}}, + {"domain", {"g"}}, + {"levtype", {"pl"}}, + {"levelist", {"1000", "850", "700", "500", "400", "300"}}, + {"expver", {"0001"}}, + {"time", {"1200"}}, + {"stream", {"oper"}}, + {"type", {"an"}}, + {"param", {"129"}}}; expand(text, "list", expected, {20250105}); } { const char* text = "list,class=tr,date=20250105"; - ExpectedOutput expected{{"class", {"tr"}}, {"date", {"20250105"}}}; + ExpectedVals expected{{"class", {"tr"}}, {"date", {"20250105"}}}; expand(text, "list", expected, {20250105}); } } @@ -746,21 +881,21 @@ CASE("test_metkit_expand_read") { const char* text = "read,class=tr,date=20250105,domain=g,levtype=pl,expver=0001,step=0,stream=oper," "levelist=1000/850/700/500/400/300,time=1200,type=an,param=129"; - ExpectedOutput expected{{"class", {"tr"}}, - {"date", {"20250105"}}, - {"domain", {"g"}}, - {"levtype", {"pl"}}, - {"levelist", {"1000", "850", "700", "500", "400", "300"}}, - {"expver", {"0001"}}, - {"time", {"1200"}}, - {"stream", {"oper"}}, - {"type", {"an"}}, - {"param", {"129"}}}; + ExpectedVals expected{{"class", {"tr"}}, + {"date", {"20250105"}}, + {"domain", {"g"}}, + {"levtype", {"pl"}}, + {"levelist", {"1000", "850", "700", "500", "400", "300"}}, + {"expver", {"0001"}}, + {"time", {"1200"}}, + {"stream", {"oper"}}, + {"type", {"an"}}, + {"param", {"129"}}}; expand(text, "read", expected, {20250105}); } { const char* text = "read,date=20250105,param=129"; - ExpectedOutput expected{{"date", {"20250105"}}, {"param", {"129"}}}; + ExpectedVals expected{{"date", {"20250105"}}, {"param", {"129"}}}; expand(text, "read", expected, {20250105}); } } @@ -771,21 +906,21 @@ CASE("test_metkit_expand_clmn") { "retrieve,class=d1,expver=1,dataset=climate-dt,activity=story-nudging,experiment=Tplus2.0K,generation=1," "model=IFS-FESOM,realization=1,stream=clmn,year=2024,month=october,resolution=standard,type=fc,levtype=sfc," "param=144"; - ExpectedOutput expected{{"class", {"d1"}}, - {"dataset", {"climate-dt"}}, - {"activity", {"story-nudging"}}, - {"experiment", {"tplus2.0k"}}, - {"generation", {"1"}}, - {"model", {"ifs-fesom"}}, - {"realization", {"1"}}, - {"expver", {"0001"}}, - {"stream", {"clmn"}}, - {"year", {"2024"}}, - {"month", {"10"}}, - {"resolution", {"standard"}}, - {"type", {"fc"}}, - {"levtype", {"sfc"}}, - {"param", {"144"}}}; + ExpectedVals expected{{"class", {"d1"}}, + {"dataset", {"climate-dt"}}, + {"activity", {"story-nudging"}}, + {"experiment", {"tplus2.0k"}}, + {"generation", {"1"}}, + {"model", {"ifs-fesom"}}, + {"realization", {"1"}}, + {"expver", {"0001"}}, + {"stream", {"clmn"}}, + {"year", {"2024"}}, + {"month", {"10"}}, + {"resolution", {"standard"}}, + {"type", {"fc"}}, + {"levtype", {"sfc"}}, + {"param", {"144"}}}; expand(text, "retrieve", expected, {}); } } @@ -800,173 +935,295 @@ CASE("test_metkit_expand_frequency") { expand(text, expected); } -CASE("test_metkit_expand_") { - // issues from https://confluence.ecmwf.int/pages/viewpage.action?pageId=496866851 - { - // https://jira.ecmwf.int/browse/MARSC-218 - const char* text = - "retrieve,accuracy=10,class=ea,date=1969-03-28,expver=11,grid=0.25/" - "0.25,levtype=sfc,packing=si,param=142.128/143.128/151.128/165.128/166.128,step=0/6/12/18/24/30/36/42/48/" - "54/60/66/72/78/84/90/96/102/108/114/120/132/144/156/168/180/192/204/216/228/" - "240,stream=oper,time=00:00:00,type=fc,target=\"reference.rFP7XB.data\""; - const char* expected = - "RETRIEVE,CLASS=EA,TYPE=FC,STREAM=OPER,EXPVER=0011,LEVTYPE=SFC,PARAM=142/143/151/165/" - "166,DATE=19690328,TIME=0000,STEP=0/6/12/18/24/30/36/42/48/54/60/66/72/78/84/90/96/102/108/114/120/132/144/" - "156/168/180/192/204/216/228/240,DOMAIN=G,TARGET=reference.rFP7XB.data,RESOL=AUTO,ACCURACY=10,GRID=.25/" - ".25,PACKING=SIMPLE"; - expand(text, expected); - } - { - // https://jira.ecmwf.int/browse/MARSC-221 - const char* text = - "retrieve,accuracy=12,area=90.0/0.0/-90.0/359.5,date=20240102,domain=g,grid=0.5/" - "0.5,leve=off,levtype=sfc,padding=0,param=134/137/165/166/167/168/" - "235,stream=da,style=dissemination,time=00,type=an,target=\"reference.tzpUX7.data\""; - const char* expected = - "RETRIEVE,CLASS=OD,TYPE=AN,STREAM=OPER,EXPVER=0001,REPRES=GG,LEVTYPE=SFC,PARAM=134/137/165/166/167/168/" - "235,DATE=20240102,TIME=0000,STEP=0,DOMAIN=G,TARGET=reference.tzpUX7.data,RESOL=AV,ACCURACY=12,STYLE=" - "DISSEMINATION,AREA=90/0/-90/359.5,GRID=.5/.5,PADDING=0"; - expand(text, expected); - } - { - // https://jira.ecmwf.int/browse/MARSC-212 - const char* text = - "retrieve,accuracy=16,area=14.8/-19.6/-14.5/19.8,class=od,date=20230810,expver=1,grid=0.09/0.09,levelist=1/" - "to/137,levtype=ml,number=-1,param=z,process=local,rotation=-78.8/" - "-61.0,step=000,stream=scda,time=18,type=an,target=\"reference.ect1qF.data\""; - const char* expected = - "RETRIEVE,CLASS=OD,TYPE=AN,STREAM=SCDA,EXPVER=0001,REPRES=SH,LEVTYPE=ML,LEVELIST=1/2/3/4/5/6/7/8/9/10/11/" - "12/13/14/15/16/17/18/19/20/21/22/23/24/25/26/27/28/29/30/31/32/33/34/35/36/37/38/39/40/41/42/43/44/45/46/" - "47/48/49/50/51/52/53/54/55/56/57/58/59/60/61/62/63/64/65/66/67/68/69/70/71/72/73/74/75/76/77/78/79/80/81/" - "82/83/84/85/86/87/88/89/90/91/92/93/94/95/96/97/98/99/100/101/102/103/104/105/106/107/108/109/110/111/112/" - "113/114/115/116/117/118/119/120/121/122/123/124/125/126/127/128/129/130/131/132/133/134/135/136/" - "137,PARAM=129,DATE=20230810,TIME=1800,STEP=0,DOMAIN=G,TARGET=reference.ect1qF.data,RESOL=AUTO,ACCURACY=16," - "AREA=14.8/-19.6/-14.5/19.8,ROTATION=-78.8/-61,GRID=.09/.09,PROCESS=LOCAL"; - expand(text, expected); - } - { - // https://jira.ecmwf.int/browse/MARSC-210 - const char* text = - "retrieve,accuracy=24,area=90.0/-179.0/-90.0/180.0,class=od,dataset=none,date=20231231/to/" - "20231231,expver=1,grid=off,levelist=1,levtype=ml,number=off,padding=0,param=152.128,resol=255,step=00," - "stream=oper,time=00/12,type=an,target=\"reference.YYhupw.data\""; - /// @todo DATASET - const char* expected = - "RETRIEVE,DATASET=none,CLASS=OD,TYPE=AN,STREAM=OPER,EXPVER=0001,REPRES=SH,LEVTYPE=ML,LEVELIST=1,PARAM=152." - "128,DATE=20231231,TIME=0000/" - "1200,STEP=0,DOMAIN=G,TARGET=reference.YYhupw.data,RESOL=255,ACCURACY=24,AREA=90/-179/-90/180,PADDING=0"; - // expand(text, expected); - } - { - // https://jira.ecmwf.int/browse/MARSC-220 - const char* text = - "retrieve,an_offset=9,class=rd,date=20210828,expver=i8k5,gaussian=regular,grid=4000,levtype=sfc,param=151." - "128/165.128/166.128,step=15,stream=da,time=00,type=fc,target=\"reference.6Zr8N7.data\""; - const char* expected = - "RETRIEVE,CLASS=RD,TYPE=FC,STREAM=OPER,EXPVER=i8k5,REPRES=SH,LEVTYPE=SFC,PARAM=151/165/" - "166,DATE=20210828,TIME=0000,STEP=15,DOMAIN=G,TARGET=reference.6Zr8N7.data,RESOL=AUTO,GRID=F4000"; - expand(text, expected); - } - { - // https://jira.ecmwf.int/browse/MARSC-214 - const char* text = - "retrieve,anoffset=90,class=ce,database=marser,date=20240102,domain=g,expver=0001,level=3,levtype=sol," - "model=lisflood,origin=ecmf,param=260199,step=6/to/72/by/" - "6,stream=efas,time=0000,type=sfo,expect=any,target=\"reference.43PsBL.data\""; - const char* expected = - "RETRIEVE,CLASS=CE,TYPE=SFO,STREAM=EFAS,EXPVER=0001,MODEL=lisflood,REPRES=SH,LEVTYPE=SOL,LEVELIST=3,PARAM=" - "260199,DATE=20240102,TIME=0000,STEP=6/12/18/24/30/36/42/48/54/60/66/" - "72,ANOFFSET=90,DOMAIN=G,ORIGIN=ECMF,EXPECT=ANY,TARGET=reference.43PsBL.data,DATABASE=marser"; - expand(text, expected); - } - { - // https://jira.ecmwf.int/browse/MARSC-222 - const char* text = - "retrieve,class=rd,date=20201204,expver=hk3a,obsgroup=22,reportype=21001,stream=lwda,time=1200,type=mfb," - "target=\"reference.vYyJf6.data\""; - /// @todo DUPLICATES - const char* expected = - "RETRIEVE,CLASS=RD,TYPE=MFB,STREAM=LWDA,EXPVER=hk3a,REPRES=BU,OBSGROUP=AMSUA_AS,REPORTYPE=21001,obstype=1," - "DATE=20201204,TIME=1200,DOMAIN=G,TARGET=reference.vYyJf6.data,DUPLICATES=KEEP"; - // expand(text, expected); - } - { - // https://jira.ecmwf.int/browse/MARSC-219 - const char* text = - "retrieve,class=od,date=20231205,expver=0001,obstype=gpsro,stream=lwda,time=18,type=ai,target=\"reference." - "E2RRc8.data\""; - /// @todo OBSTYPE, OBSGROUP - const char* expected = - "RETRIEVE,CLASS=OD,TYPE=AI,STREAM=LWDA,EXPVER=0001,REPRES=BU,OBSTYPE=250,DATE=20231205,TIME=1800,DOMAIN=G," - "TARGET=reference.E2RRc8.data,DUPLICATES=KEEP"; - // expand(text, expected); - } - { - // https://jira.ecmwf.int/browse/MARSC-213 - const char* text = - "retrieve,class=od,date=20230821,expect=any,expver=0001,levtype=sfc,param=70.228/71.228/72.228/73.228/" - "74.228,stream=da,time=12,type=gai,target=\"reference.1e7AY1.data\""; - const char* expected = - "RETRIEVE,CLASS=OD,TYPE=GAI,STREAM=OPER,EXPVER=0001,REPRES=GG,LEVTYPE=SFC,PARAM=228070/228071/228072/" - "228073/228074,DATE=20230821,TIME=1200,STEP=0,DOMAIN=G,TARGET=reference.1e7AY1.data,EXPECT=ANY"; - expand(text, expected); - } - { - const char* text = - "retrieve,accuracy=16,area=14.8/-19.6/-14.5/19.8,class=od,date=20230810,expver=1,grid=0.09/0.09,levelist=1/" - "to/137,levtype=ml,number=-1,param=z,process=local,rotation=-78.8/" - "-61.0,step=000,stream=scda,time=18,type=an,target=\"reference.ect1qF.data\""; - const char* expected = - "RETRIEVE,CLASS=OD,TYPE=AN,STREAM=SCDA,EXPVER=0001,REPRES=SH,LEVTYPE=ML,LEVELIST=1/2/3/4/5/6/7/8/9/10/11/" - "12/13/14/15/16/17/18/19/20/21/22/23/24/25/26/27/28/29/30/31/32/33/34/35/36/37/38/39/40/41/42/43/44/45/46/" - "47/48/49/50/51/52/53/54/55/56/57/58/59/60/61/62/63/64/65/66/67/68/69/70/71/72/73/74/75/76/77/78/79/80/81/" - "82/83/84/85/86/87/88/89/90/91/92/93/94/95/96/97/98/99/100/101/102/103/104/105/106/107/108/109/110/111/112/" - "113/114/115/116/117/118/119/120/121/122/123/124/125/126/127/128/129/130/131/132/133/134/135/136/" - "137,PARAM=129,DATE=20230810,TIME=1800,STEP=0,DOMAIN=G,TARGET=reference.ect1qF.data,RESOL=AUTO,ACCURACY=16," - "AREA=14.8/-19.6/-14.5/19.8,ROTATION=-78.8/-61,GRID=.09/.09,PROCESS=LOCAL"; - expand(text, expected); - } - { - const char* text = - "retrieve,accuracy=16,area=60.0/-60.0/-60.0/60.0,class=ea,date=20101029,expver=1,grid=0.30/0.30,levelist=1/" - "to/137,levtype=ml,number=-1,param=q/t/u/v/lnsp/z,rotation=0.0/" - "0.0,step=000,stream=oper,time=15:00:00,type=an,target=\"reference.1OEDK0.data\""; - const char* expected = - "RETRIEVE,CLASS=EA,TYPE=AN,STREAM=OPER,EXPVER=0001,LEVTYPE=ML,LEVELIST=1/2/3/4/5/6/7/8/9/10/11/12/13/14/15/" - "16/17/18/19/20/21/22/23/24/25/26/27/28/29/30/31/32/33/34/35/36/37/38/39/40/41/42/43/44/45/46/47/48/49/50/" - "51/52/53/54/55/56/57/58/59/60/61/62/63/64/65/66/67/68/69/70/71/72/73/74/75/76/77/78/79/80/81/82/83/84/85/" - "86/87/88/89/90/91/92/93/94/95/96/97/98/99/100/101/102/103/104/105/106/107/108/109/110/111/112/113/114/115/" - "116/117/118/119/120/121/122/123/124/125/126/127/128/129/130/131/132/133/134/135/136/137,PARAM=133/130/131/" - "132/152/129,TIME=1500,STEP=0,DOMAIN=G,TARGET=reference.1OEDK0.data,RESOL=AUTO,ACCURACY=16,AREA=60/-60/-60/" - "60,ROTATION=0/0,GRID=.3/.3,DATE=20101029"; - expand(text, expected); - } - { - const char* text = - "retrieve,accuracy=12,area=90.0/0.0/-90.0/359.5,date=20240102,domain=g,grid=0.5/" - "0.5,leve=off,levtype=sfc,padding=0,param=134/137/165/166/167/168/" - "235,stream=da,style=dissemination,time=00,type=an,target=\"reference.tzpUX7.data\""; - const char* expected = - "RETRIEVE,CLASS=OD,TYPE=AN,STREAM=OPER,EXPVER=0001,REPRES=GG,LEVTYPE=SFC,PARAM=134/137/165/166/167/168/" - "235,DATE=20240102,TIME=0000,STEP=0,DOMAIN=G,TARGET=reference.tzpUX7.data,RESOL=AV,ACCURACY=12,STYLE=" - "DISSEMINATION,AREA=90/0/-90/359.5,GRID=.5/.5,PADDING=0"; - expand(text, expected); - } - { - // https://jira.ecmwf.int/browse/MARSC-211 - const char* text = - "retrieve,class=ce,database=marser,date=20240102,domain=g,expver=0001,level=2,levtype=sol,model=lisflood," - "origin=ecmf,param=260199,step=6/to/240/by/" - "6,stream=efas,time=0000,type=fc,target=\"reference.JkqWoW.data\""; - const char* expected = - "RETRIEVE,CLASS=CE,TYPE=FC,STREAM=EFAS,EXPVER=0001,MODEL=lisflood,REPRES=SH,LEVTYPE=SOL,LEVELIST=2,PARAM=" - "260199,DATE=20240102,TIME=0000,STEP=6/12/18/24/30/36/42/48/54/60/66/72/78/84/90/96/102/108/114/120/126/" - "132/138/144/150/156/162/168/174/180/186/192/198/204/210/216/222/228/234/" - "240,DOMAIN=G,ORIGIN=ECMF,TARGET=reference.JkqWoW.data"; - expand(text, expected); - } +// issues from https://confluence.ecmwf.int/pages/viewpage.action?pageId=496866851 +CASE("test_metkit_expand_MARSC-218") { + // https://jira.ecmwf.int/browse/MARSC-218 + const char* text = + "retrieve,accuracy=10,class=ea,date=1969-03-28,expver=11,grid=0.25/" + "0.25,levtype=sfc,packing=si,param=142.128/143.128/151.128/165.128/166.128,step=0/6/12/18/24/30/36/42/48/" + "54/60/66/72/78/84/90/96/102/108/114/120/132/144/156/168/180/192/204/216/228/" + "240,stream=oper,time=00:00:00,type=fc,target=\"reference.rFP7XB.data\""; + const char* expected = + "RETRIEVE,CLASS=EA,TYPE=FC,STREAM=OPER,EXPVER=0011,LEVTYPE=SFC,PARAM=142/143/151/165/" + "166,DATE=19690328,TIME=0000,STEP=0/6/12/18/24/30/36/42/48/54/60/66/72/78/84/90/96/102/108/114/120/132/144/" + "156/168/180/192/204/216/228/240,DOMAIN=G,TARGET=reference.rFP7XB.data,RESOL=AUTO,ACCURACY=10,GRID=.25/" + ".25,PACKING=SIMPLE"; + expand(text, expected); +} + +CASE("test_metkit_expand_MARSC-221") { + // https://jira.ecmwf.int/browse/MARSC-221 + const char* text = + "retrieve,accuracy=12,area=90.0/0.0/-90.0/359.5,date=20240102,domain=g,grid=0.5/" + "0.5,leve=off,levtype=sfc,padding=0,param=134/137/165/166/167/168/" + "235,stream=da,style=dissemination,time=00,type=an,target=\"reference.tzpUX7.data\""; + const char* expected = + "RETRIEVE,CLASS=OD,TYPE=AN,STREAM=OPER,EXPVER=0001,REPRES=GG,LEVTYPE=SFC,PARAM=134/137/165/166/167/168/" + "235,DATE=20240102,TIME=0000,STEP=0,DOMAIN=G,TARGET=reference.tzpUX7.data,RESOL=AV,ACCURACY=12,STYLE=" + "DISSEMINATION,AREA=90/0/-90/359.5,GRID=.5/.5,PADDING=0"; + expand(text, expected); +} + +CASE("test_metkit_expand_MARSC-212") { + // https://jira.ecmwf.int/browse/MARSC-212 + const char* text = + "retrieve,accuracy=16,area=14.8/-19.6/-14.5/19.8,class=od,date=20230810,expver=1,grid=0.09/0.09,levelist=1/" + "to/137,levtype=ml,number=-1,param=z,process=local,rotation=-78.8/-61.0,step=000,stream=scda,time=18," + "type=an,target=\"reference.ect1qF.data\""; + const char* expected = + "RETRIEVE,CLASS=OD,TYPE=AN,STREAM=SCDA,EXPVER=0001,REPRES=SH,LEVTYPE=ML,LEVELIST=1/2/3/4/5/6/7/8/9/10/11/" + "12/13/14/15/16/17/18/19/20/21/22/23/24/25/26/27/28/29/30/31/32/33/34/35/36/37/38/39/40/41/42/43/44/45/46/" + "47/48/49/50/51/52/53/54/55/56/57/58/59/60/61/62/63/64/65/66/67/68/69/70/71/72/73/74/75/76/77/78/79/80/81/" + "82/83/84/85/86/87/88/89/90/91/92/93/94/95/96/97/98/99/100/101/102/103/104/105/106/107/108/109/110/111/112/" + "113/114/115/116/117/118/119/120/121/122/123/124/125/126/127/128/129/130/131/132/133/134/135/136/137," + "PARAM=129,DATE=20230810,TIME=1800,STEP=0,DOMAIN=G,TARGET=reference.ect1qF.data,RESOL=AUTO,ACCURACY=16," + "AREA=14.8/-19.6/-14.5/19.8,ROTATION=-78.8/-61,GRID=.09/.09,PROCESS=LOCAL"; + expand(text, expected); +} + +CASE("test_metkit_expand_MARSC-210") { + // https://jira.ecmwf.int/browse/MARSC-210 + const char* text = + "retrieve,accuracy=24,area=90.0/-179.0/-90.0/180.0,class=od,dataset=none,date=20231231/to/20231231,expver=1," + "grid=off,levelist=1,levtype=ml,number=off,padding=0,param=152.128,resol=255,step=00,stream=oper,time=00/12," + "type=an,target=reference.data"; + const char* expected = + "RETRIEVE,DATASET=none,CLASS=OD,TYPE=AN,STREAM=OPER,EXPVER=0001,REPRES=SH,LEVTYPE=ML,LEVELIST=1,PARAM=152," + "DATE=20231231,TIME=0000/1200,STEP=0,DOMAIN=G,TARGET=reference.data,RESOL=255,ACCURACY=24," + "AREA=90/-179/-90/180,PADDING=0"; + expand(text, expected); } +CASE("test_metkit_expand_MARSC-220") { + // https://jira.ecmwf.int/browse/MARSC-220 + const char* text = + "retrieve,an_offset=9,class=rd,date=20210828,expver=i8k5,gaussian=regular,grid=4000,levtype=sfc,param=151." + "128/165.128/166.128,step=15,stream=da,time=00,type=fc,target=\"reference.6Zr8N7.data\""; + const char* expected = + "RETRIEVE,CLASS=RD,TYPE=FC,STREAM=OPER,EXPVER=i8k5,REPRES=SH,LEVTYPE=SFC,PARAM=151/165/" + "166,DATE=20210828,TIME=0000,STEP=15,DOMAIN=G,TARGET=reference.6Zr8N7.data,RESOL=AUTO,GRID=F4000"; + expand(text, expected); +} + +CASE("test_metkit_expand_MARSC-214") { + // https://jira.ecmwf.int/browse/MARSC-214 + const char* text = + "retrieve,anoffset=90,class=ce,database=marser,date=20240102,domain=g,expver=0001,level=3,levtype=sol," + "model=lisflood,origin=ecmf,param=260199,step=6/to/72/by/" + "6,stream=efas,time=0000,type=sfo,expect=any,target=\"reference.43PsBL.data\""; + const char* expected = + "RETRIEVE,CLASS=CE,TYPE=SFO,STREAM=EFAS,EXPVER=0001,MODEL=lisflood,REPRES=SH,LEVTYPE=SOL,LEVELIST=3,PARAM=" + "260199,DATE=20240102,TIME=0000,STEP=6/12/18/24/30/36/42/48/54/60/66/" + "72,ANOFFSET=90,DOMAIN=G,ORIGIN=ECMF,EXPECT=ANY,TARGET=reference.43PsBL.data,DATABASE=marser"; + expand(text, expected); +} + +CASE("test_metkit_expand_MARSC-222") { + // https://jira.ecmwf.int/browse/MARSC-222 + const char* text = + "retrieve,class=rd,date=20201204,expver=hk3a,obsgroup=22,reportype=21001,stream=lwda,time=1200,type=mfb," + "target=\"reference.vYyJf6.data\""; + /// @todo DUPLICATES + const char* expected = + "RETRIEVE,CLASS=RD,TYPE=MFB,STREAM=LWDA,EXPVER=hk3a,REPRES=BU,OBSGROUP=AMSUA_AS,REPORTYPE=21001,obstype=1," + "DATE=20201204,TIME=1200,DOMAIN=G,TARGET=reference.vYyJf6.data,DUPLICATES=KEEP"; + // expand(text, expected); +} + +CASE("test_metkit_expand_MARSC-219") { + // https://jira.ecmwf.int/browse/MARSC-219 + const char* text = + "retrieve,class=od,date=20231205,expver=0001,obstype=gpsro,stream=lwda,time=18,type=ai,target=\"reference." + "E2RRc8.data\""; + /// @todo OBSTYPE, OBSGROUP + const char* expected = + "RETRIEVE,CLASS=OD,TYPE=AI,STREAM=LWDA,EXPVER=0001,REPRES=BU,OBSTYPE=250,DATE=20231205,TIME=1800,DOMAIN=G," + "TARGET=reference.E2RRc8.data,DUPLICATES=KEEP"; + // expand(text, expected); +} + +CASE("test_metkit_expand_MARSC-213") { + // https://jira.ecmwf.int/browse/MARSC-213 + const char* text = + "retrieve,class=od,date=20230821,expect=any,expver=0001,levtype=sfc,param=70.228/71.228/72.228/73.228/" + "74.228,stream=da,time=12,type=gai,target=\"reference.1e7AY1.data\""; + const char* expected = + "RETRIEVE,CLASS=OD,TYPE=GAI,STREAM=OPER,EXPVER=0001,REPRES=GG,LEVTYPE=SFC,PARAM=228070/228071/228072/" + "228073/228074,DATE=20230821,TIME=1200,STEP=0,DOMAIN=G,TARGET=reference.1e7AY1.data,EXPECT=ANY"; + expand(text, expected); +} + +CASE("test_metkit_expand_MARSC-211") { + // https://jira.ecmwf.int/browse/MARSC-211 + const char* text = + "retrieve,class=ce,database=marser,date=20240102,domain=g,expver=0001,level=2,levtype=sol,model=lisflood," + "origin=ecmf,param=260199,step=6/to/240/by/" + "6,stream=efas,time=0000,type=fc,target=\"reference.JkqWoW.data\""; + const char* expected = + "RETRIEVE,CLASS=CE,TYPE=FC,STREAM=EFAS,EXPVER=0001,MODEL=lisflood,REPRES=SH,LEVTYPE=SOL,LEVELIST=2,PARAM=" + "260199,DATE=20240102,TIME=0000,STEP=6/12/18/24/30/36/42/48/54/60/66/72/78/84/90/96/102/108/114/120/126/" + "132/138/144/150/156/162/168/174/180/186/192/198/204/210/216/222/228/234/" + "240,DOMAIN=G,ORIGIN=ECMF,TARGET=reference.JkqWoW.data"; + expand(text, expected); +} + +CASE("test_metkit_expand_MARSC-246") { + // https://jira.ecmwf.int/browse/MARSC-246 + const char* text = + "retrieve,DOMAIN=G,LEVTYPE=DP,DATE=20120201,TIME=0000,STEP=288,PARAM=175.151,CLASS=OD,TYPE=OF,STREAM=OCEA," + "EXPVER=0001,NUMBER=0,SYSTEM=3,METHOD=1,PRODUCT=TIMS,SECTION=Z,LEVELIST=0.000,LATITUDE=-9.967,RANGE=264,target=" + "\"reference.t2APXu.data\""; + const char* expected = + "RETRIEVE,CLASS=OD,TYPE=OF,STREAM=OCEA,EXPVER=0001,REPRES=SH,LEVTYPE=DP,LEVELIST=0,PARAM=151175,DATE=20120201," + "TIME=0000,RANGE=264,STEP=288,NUMBER=0,DOMAIN=G,SYSTEM=3,METHOD=1,PRODUCT=TIMS,SECTION=Z,LATITUDE=-9.967," + "TARGET=reference.t2APXu.data"; + expand(text, expected); +} + +// https://jira.ecmwf.int/browse/MARSC-306 +CASE("test_metkit_expand_MARSC-306") { + const std::string text = + "retrieve,CLASS=OD,TYPE=PF,STREAM=EF,EXPVER=0001,REPRES=SH,LEVTYPE=SFC,PARAM=167/165/166/164/" + "228,DATE=20250523,TIME=0000,STEP=6/12,NUMBER=1/2,DOMAIN=G,RESOL=N128,AREA=70.5/-21.0/30.0/40.5,GRID=1.5/" + "1.5,target=\"target.vareps.test\",RESOL=N128"; + + // N128 needs to be forwarded and is therefore not manipulated + const std::string expected = + "retrieve,class=od,type=pf,stream=enfo,levtype=sfc,date=20250523,time=0000,step=6/" + "12,expver=0001,domain=g,number=1/2,param=167/165/166/164/228,target=target.vareps.test,grid=1.5/1.5,area=70.5/" + "-21/30/40.5,repres=sh,resol=N128"; + + + MarsRequest r = MarsRequest::parse(text); + std::string expanded = r.asString(); + + EXPECT_EQUAL(expanded, expected); +} + + +CASE("test_metkit_expand_0") { + const char* text = + "retrieve,accuracy=16,area=14.8/-19.6/-14.5/19.8,class=od,date=20230810,expver=1,grid=0.09/0.09,levelist=1/" + "to/137,levtype=ml,number=-1,param=z,process=local,rotation=-78.8/" + "-61.0,step=000,stream=scda,time=18,type=an,target=\"reference.ect1qF.data\""; + const char* expected = + "RETRIEVE,CLASS=OD,TYPE=AN,STREAM=SCDA,EXPVER=0001,REPRES=SH,LEVTYPE=ML,LEVELIST=1/2/3/4/5/6/7/8/9/10/11/" + "12/13/14/15/16/17/18/19/20/21/22/23/24/25/26/27/28/29/30/31/32/33/34/35/36/37/38/39/40/41/42/43/44/45/46/" + "47/48/49/50/51/52/53/54/55/56/57/58/59/60/61/62/63/64/65/66/67/68/69/70/71/72/73/74/75/76/77/78/79/80/81/" + "82/83/84/85/86/87/88/89/90/91/92/93/94/95/96/97/98/99/100/101/102/103/104/105/106/107/108/109/110/111/112/" + "113/114/115/116/117/118/119/120/121/122/123/124/125/126/127/128/129/130/131/132/133/134/135/136/" + "137,PARAM=129,DATE=20230810,TIME=1800,STEP=0,DOMAIN=G,TARGET=reference.ect1qF.data,RESOL=AUTO,ACCURACY=16," + "AREA=14.8/-19.6/-14.5/19.8,ROTATION=-78.8/-61,GRID=.09/.09,PROCESS=LOCAL"; + expand(text, expected); +} + +CASE("test_metkit_expand_1") { + const char* text = + "retrieve,accuracy=16,area=60.0/-60.0/-60.0/60.0,class=ea,date=20101029,expver=1,grid=0.30/0.30,levelist=1/" + "to/137,levtype=ml,number=-1,param=q/t/u/v/lnsp/z,rotation=0.0/" + "0.0,step=000,stream=oper,time=15:00:00,type=an,target=\"reference.1OEDK0.data\""; + const char* expected = + "RETRIEVE,CLASS=EA,TYPE=AN,STREAM=OPER,EXPVER=0001,LEVTYPE=ML,LEVELIST=1/2/3/4/5/6/7/8/9/10/11/12/13/14/15/" + "16/17/18/19/20/21/22/23/24/25/26/27/28/29/30/31/32/33/34/35/36/37/38/39/40/41/42/43/44/45/46/47/48/49/50/" + "51/52/53/54/55/56/57/58/59/60/61/62/63/64/65/66/67/68/69/70/71/72/73/74/75/76/77/78/79/80/81/82/83/84/85/" + "86/87/88/89/90/91/92/93/94/95/96/97/98/99/100/101/102/103/104/105/106/107/108/109/110/111/112/113/114/115/" + "116/117/118/119/120/121/122/123/124/125/126/127/128/129/130/131/132/133/134/135/136/137,PARAM=133/130/131/" + "132/152/129,TIME=1500,STEP=0,DOMAIN=G,TARGET=reference.1OEDK0.data,RESOL=AUTO,ACCURACY=16,AREA=60/-60/-60/" + "60,ROTATION=0/0,GRID=.3/.3,DATE=20101029"; + expand(text, expected); +} + +CASE("test_metkit_expand_2") { + const char* text = + "retrieve,accuracy=12,area=90.0/0.0/-90.0/359.5,date=20240102,domain=g,grid=0.5/" + "0.5,leve=off,levtype=sfc,padding=0,param=134/137/165/166/167/168/" + "235,stream=da,style=dissemination,time=00,type=an,target=\"reference.tzpUX7.data\""; + const char* expected = + "RETRIEVE,CLASS=OD,TYPE=AN,STREAM=OPER,EXPVER=0001,REPRES=GG,LEVTYPE=SFC,PARAM=134/137/165/166/167/168/" + "235,DATE=20240102,TIME=0000,STEP=0,DOMAIN=G,TARGET=reference.tzpUX7.data,RESOL=AV,ACCURACY=12,STYLE=" + "DISSEMINATION,AREA=90/0/-90/359.5,GRID=.5/.5,PADDING=0"; + expand(text, expected); +} + +CASE("test_metkit_disseminate") { + const char* text = + "disseminate,option=normal,target=NTI:HT,date=20250506,time=0/12,stream=oper,levtype=sfc,type=an,param=lsm," + "step=0,direction=off,frequency=off,area=54.5/1.5/51/8,grid=.1/.1,packing=simple\n" + "disseminate,stream=wave,param=2dfd,direction=1/to/36,frequency=1/to/29,packing=off\n" + "disseminate,type=fc,step=3/to/144/by/3\n" + "disseminate,stream=oper,type=an,param=lsm,step=0,direction=off,frequency=off,area=64/-15/43/13," + "grid=.25/.25,packing=simple\n" + "disseminate,stream=wave,param=tmax/hmax/swh/mwd/pp1d/mwp/shww/mdww/mpww/shts/mdts/mpts/sh10\n" + "disseminate,type=fc,step=3/to/72/by/3\n" + "disseminate,step=78/to/240/by/6"; + std::vector expected = { + "disseminate,stream=oper,type=an,param=172,step=0,area=54.5/1.5/51/8,grid=.1/.1,packing=simple,class=od," + "date=20250506,domain=g,expver=0001,levtype=sfc,option=normal,target=NTI:HT,time=0000/1200", + "disseminate,stream=wave,param=140251,direction=1/2/3/4/5/6/7/8/9/10/11/12/13/14/15/16/17/18/19/20/21/22/23/24/" + "25/26/27/28/29/30/31/32/33/34/35/36,frequency=1/2/3/4/5/6/7/8/9/10/11/12/13/14/15/16/17/18/19/20/21/22/23/24/" + "25/26/27/28/29,area=54.5/1.5/51/8,class=od,date=20250506,domain=g,expver=0001,grid=.1/.1,levtype=sfc," + "option=normal,step=0,target=NTI:HT,time=0000/1200,type=an", + "disseminate,type=fc,step=3/6/9/12/15/18/21/24/27/30/33/36/39/42/45/48/51/54/57/60/63/66/69/72/75/78/81/84/87/" + "90/93/96/99/102/105/108/111/114/117/120/123/126/129/132/135/138/141/144,area=54.5/1.5/51/" + "8,class=od,date=20250506,direction=1/2/3/4/5/6/7/8/9/10/11/12/13/14/15/16/17/18/19/20/21/22/23/24/25/26/27/28/" + "29/30/31/32/33/34/35/36,domain=g,expver=0001,frequency=1/2/3/4/5/6/7/8/9/10/11/12/13/14/15/16/17/18/19/20/21/" + "22/23/24/25/26/27/28/29,grid=.1/.1,levtype=sfc,option=normal,param=140251,stream=wave,target=NTI:HT,time=0000/" + "1200", + "disseminate,stream=oper,type=an,param=172,step=0,area=64/-15/43/13,grid=.25/" + ".25,packing=simple,class=od,date=20250506,domain=g,expver=0001,levtype=sfc,option=normal,target=NTI:HT,time=" + "0000/1200", + "disseminate,stream=wave,param=140217/140218/140229/140230/140231/140232/140234/140235/140236/140237/140238/" + "140239/140120,area=64/-15/43/13,class=od,date=20250506,domain=g,expver=0001,grid=.25/" + ".25,levtype=sfc,option=normal,packing=simple,step=0,target=NTI:HT,time=0000/1200,type=an", + "disseminate,type=fc,step=3/6/9/12/15/18/21/24/27/30/33/36/39/42/45/48/51/54/57/60/63/66/69/72,area=64/-15/43/" + "13,class=od,date=20250506,domain=g,expver=0001,grid=.25/" + ".25,levtype=sfc,option=normal,packing=simple,param=140217/140218/140229/140230/140231/140232/140234/140235/" + "140236/140237/140238/140239/140120,stream=wave,target=NTI:HT,time=0000/1200", + "disseminate,step=78/84/90/96/102/108/114/120/126/132/138/144/150/156/162/168/174/180/186/192/198/204/210/216/" + "222/228/234/240,area=64/-15/43/13,class=od,date=20250506,domain=g,expver=0001,grid=.25/" + ".25,levtype=sfc,option=normal,packing=simple,param=140217/140218/140229/140230/140231/140232/140234/140235/" + "140236/140237/140238/140239/140120,stream=wave,target=NTI:HT,time=0000/1200,type=fc"}; + + expand(text, expected, false); +} + +CASE("test_metkit_files") { + + eckit::LocalPathName testFolder{"expand"}; + ASSERT(testFolder.exists()); + + eckit::StdDir d(testFolder); + + for (;;) { + struct dirent* e = d.dirent(); + if (e == nullptr) { + break; + } + + if (::strstr(e->d_name, ".req")) { + try { + // look for the corresponding .expected file + std::string reqFileName{testFolder / e->d_name}; + eckit::PathName expFileName{reqFileName.substr(0, reqFileName.find_last_of('.')) + ".expected"}; + ASSERT(expFileName.exists()); + + std::ifstream reqFile(reqFileName); + std::stringstream req; + req << reqFile.rdbuf(); + + std::ifstream expFile(expFileName); + std::stringstream exp; + exp << expFile.rdbuf(); + + expand(req.str(), exp.str()); + } + catch (...) { + std::cerr << "ERROR processing file: " << e->d_name << std::endl; + throw; + } + } + } +} //----------------------------------------------------------------------------- } // namespace metkit::mars::test diff --git a/tests/test_filter.cc b/tests/test_filter.cc index 11865fed..cc0d9027 100644 --- a/tests/test_filter.cc +++ b/tests/test_filter.cc @@ -38,13 +38,8 @@ using ExpectedOutput = std::map>; void filter(MarsRequest& r, const MarsRequest& f, const ExpectedOutput& expected, const std::vector dates) { - std::cout << r << std::endl; - std::cout << f << std::endl; - r.filter(f); - std::cout << r << std::endl; - for (const auto& e : expected) { if (!r.has(e.first)) { std::cerr << eckit::Colour::red << "Missing keyword: " << e.first << eckit::Colour::reset << std::endl; @@ -79,7 +74,7 @@ void filter(MarsRequest& r, const MarsRequest& f, const ExpectedOutput& expected } void filter(const std::string& text, const std::string& filter_text, const ExpectedOutput& expected, - std::vector dates, bool strict = false) { + std::vector dates, bool strict = true) { MarsRequest r = MarsRequest::parse(text, strict); std::string f_text = "filter," + filter_text; std::istringstream in(f_text); @@ -89,7 +84,7 @@ void filter(const std::string& text, const std::string& filter_text, const Expec filter(r, f[0], expected, std::move(dates)); } -void expand(const std::string& text, const std::string& filter_text, const std::string& expected, bool strict = false, +void expand(const std::string& text, const std::string& filter_text, const std::string& expected, bool strict = true, std::vector dates = {}) { ExpectedOutput out; eckit::Tokenizer c(","); diff --git a/tests/test_hypercube.cc b/tests/test_hypercube.cc index 784dd5f8..cf362a30 100644 --- a/tests/test_hypercube.cc +++ b/tests/test_hypercube.cc @@ -34,8 +34,6 @@ CASE("test_metkit_hypercube") { EXPECT(cube.contains(r)); EXPECT(cube.size() == 1); EXPECT(cube.vacantRequests().size() == 1); - EXPECT_EQUAL("sh", r.values("repres").at(0)); - r.unsetValues("repres"); EXPECT(!(r < *cube.vacantRequests().begin())); EXPECT(!(*cube.vacantRequests().begin() < r)); } @@ -50,8 +48,6 @@ CASE("test_metkit_hypercube_subset") { EXPECT(cube.size() == 2); EXPECT(cube.countVacant() == 2); EXPECT(cube.vacantRequests().size() == 1); - EXPECT_EQUAL("sh", r.values("repres").at(0)); - r.unsetValues("repres"); EXPECT(!(r < *cube.vacantRequests().begin())); EXPECT(!(*cube.vacantRequests().begin() < r)); @@ -59,15 +55,11 @@ CASE("test_metkit_hypercube_subset") { "retrieve,class=rd,type=an,stream=oper,levtype=pl,date=20191110,time=0000,step=0,expver=xxxy,domain=g,levelist=" "500,param=138"; MarsRequest r500 = MarsRequest::parse(text500); - EXPECT_EQUAL("sh", r500.values("repres").at(0)); - r500.unsetValues("repres"); const char* text600 = "retrieve,class=rd,type=an,stream=oper,levtype=pl,date=20191110,time=0000,step=0,expver=xxxy,domain=g,levelist=" "600,param=138"; MarsRequest r600 = MarsRequest::parse(text600); - EXPECT_EQUAL("sh", r600.values("repres").at(0)); - r600.unsetValues("repres"); EXPECT_THROWS(cube.contains(r)); EXPECT(cube.contains(r500)); @@ -98,8 +90,6 @@ CASE("test_metkit_hypercube_request") { EXPECT(cube.size() == 4); EXPECT(cube.countVacant() == 4); EXPECT(cube.vacantRequests().size() == 1); - EXPECT_EQUAL("sh", r.values("repres").at(0)); - r.unsetValues("repres"); EXPECT(!(r < *cube.vacantRequests().begin())); EXPECT(!(*cube.vacantRequests().begin() < r)); @@ -107,15 +97,11 @@ CASE("test_metkit_hypercube_request") { "retrieve,class=rd,type=an,stream=oper,levtype=pl,date=20191110,time=0000,step=0,expver=xxxy,domain=g,levelist=" "500,param=138"; MarsRequest r500 = MarsRequest::parse(text500); - EXPECT_EQUAL("sh", r500.values("repres").at(0)); - r500.unsetValues("repres"); const char* text600 = "retrieve,class=rd,type=an,stream=oper,levtype=pl,date=20191110,time=0000,step=0,expver=xxxy,domain=g,levelist=" "600,param=138"; MarsRequest r600 = MarsRequest::parse(text600); - EXPECT_EQUAL("sh", r600.values("repres").at(0)); - r600.unsetValues("repres"); EXPECT_THROWS(cube.contains(r)); EXPECT(cube.contains(r500)); @@ -138,8 +124,6 @@ CASE("test_metkit_hypercube_request") { "retrieve,class=rd,type=an,stream=oper,levtype=pl,date=20191110,time=0000,step=0,expver=xxxy,domain=g,levelist=" "500/600,param=155"; MarsRequest r155 = MarsRequest::parse(text155); - EXPECT_EQUAL("sh", r155.values("repres").at(0)); - r155.unsetValues("repres"); EXPECT(!(r155 < *cube.vacantRequests().begin())); EXPECT(!(*cube.vacantRequests().begin() < r155)); } diff --git a/tests/test_integer_range.cc b/tests/test_integer_range.cc index f50ed887..514c6220 100644 --- a/tests/test_integer_range.cc +++ b/tests/test_integer_range.cc @@ -37,13 +37,14 @@ CASE("Test TypeInteger expansion range=[1,100]") { settings["range"] = ValueList{1, 100}; TypeInteger type("day", settings); Type& tday = type; + MarsRequest r; // in range for (int i = 1; i < 101; ++i) { auto num = std::to_string(i); std::string value = num; - auto ret = tday.expand(ctx, value); + auto ret = tday.expand(ctx, r, value); EXPECT_EQUAL(ret, true); EXPECT_EQUAL(value, num); } @@ -52,13 +53,13 @@ CASE("Test TypeInteger expansion range=[1,100]") { { std::string value = "0"; - auto ret = tday.expand(ctx, value); + auto ret = tday.expand(ctx, r, value); EXPECT_EQUAL(ret, false); } { std::string value = "101"; - auto ret = tday.expand(ctx, value); + auto ret = tday.expand(ctx, r, value); EXPECT_EQUAL(ret, false); } } @@ -71,16 +72,17 @@ CASE("Test TypeInteger expansion range=[1,1]") { settings["range"] = ValueList{1, 1}; TypeInteger type("day", settings); Type& tday = type; + MarsRequest r; { std::string value = "1"; - auto ret = tday.expand(ctx, value); + auto ret = tday.expand(ctx, r, value); EXPECT_EQUAL(ret, true); } { std::string value = "2"; - auto ret = tday.expand(ctx, value); + auto ret = tday.expand(ctx, r, value); EXPECT_EQUAL(ret, false); } } @@ -93,34 +95,35 @@ CASE("Test TypeInteger day expansion range=[-1,1]") { settings["range"] = ValueList{-1, 1}; TypeInteger type("day", settings); Type& tday = type; + MarsRequest r; { std::string value = "-2"; - auto ret = tday.expand(ctx, value); + auto ret = tday.expand(ctx, r, value); EXPECT_EQUAL(ret, false); } { std::string value = "-1"; - auto ret = tday.expand(ctx, value); + auto ret = tday.expand(ctx, r, value); EXPECT_EQUAL(ret, true); } { std::string value = "0"; - auto ret = tday.expand(ctx, value); + auto ret = tday.expand(ctx, r, value); EXPECT_EQUAL(ret, true); } { std::string value = "1"; - auto ret = tday.expand(ctx, value); + auto ret = tday.expand(ctx, r, value); EXPECT_EQUAL(ret, true); } { std::string value = "2"; - auto ret = tday.expand(ctx, value); + auto ret = tday.expand(ctx, r, value); EXPECT_EQUAL(ret, false); } } diff --git a/tests/test_param_axis.cc b/tests/test_param_axis.cc index c5f37ef4..8c66c8d7 100644 --- a/tests/test_param_axis.cc +++ b/tests/test_param_axis.cc @@ -50,12 +50,10 @@ static void test_param_axis(const std::vector& user, const std::vec std::sort(index.begin(), index.end()); - std::cout << "Axis:" << index << std::endl; std::cout << "User:" << params << std::endl; std::cout << "Wind:" << false << std::endl; - ParamID::normalise(ignore, params, index, windRequested, fullTableDropping); std::cout << "Expected Params:" << expected << std::endl; diff --git a/tests/test_request.cc b/tests/test_request.cc index 653ec5aa..a8fd5d01 100644 --- a/tests/test_request.cc +++ b/tests/test_request.cc @@ -42,10 +42,11 @@ CASE("test_request_json") { std::stringstream ss; eckit::JSON plain(ss); r.json(plain); - EXPECT_EQUAL(ss.str(), - "{\"class\":\"od\",\"expver\":\"0079\",\"stream\":\"enfh\",\"date\":\"20240729\",\"time\":[" - "\"0000\",\"1200\"],\"type\":\"fcmean\",\"levtype\":\"sfc\",\"step\":\"24\",\"number\":[\"1\"," - "\"2\"],\"param\":[\"228236\",\"228235\",\"172228\"],\"domain\":\"g\",\"repres\":\"sh\"}"); + EXPECT_EQUAL( + ss.str(), + "{\"class\":\"od\",\"type\":\"fcmean\",\"stream\":\"enfh\",\"levtype\":\"sfc\",\"date\":\"20240729\"," + "\"time\":[\"0000\",\"1200\"],\"step\":\"24\",\"expver\":\"0079\",\"number\":[\"1\",\"2\"],\"param\":[" + "\"228236\",\"228235\",\"172228\"],\"domain\":\"g\"}"); } { std::stringstream ss; @@ -53,9 +54,9 @@ CASE("test_request_json") { r.json(array, true); EXPECT_EQUAL( ss.str(), - "{\"class\":\"od\",\"expver\":\"0079\",\"stream\":\"enfh\",\"date\":[\"20240729\"],\"time\":[" - "\"0000\",\"1200\"],\"type\":\"fcmean\",\"levtype\":\"sfc\",\"step\":[\"24\"],\"number\":[" - "\"1\",\"2\"],\"param\":[\"228236\",\"228235\",\"172228\"],\"domain\":\"g\",\"repres\":\"sh\"}"); + "{\"class\":\"od\",\"type\":\"fcmean\",\"stream\":\"enfh\",\"levtype\":\"sfc\",\"date\":[\"20240729\"]," + "\"time\":[\"0000\",\"1200\"],\"step\":[\"24\"],\"expver\":\"0079\",\"number\":[\"1\",\"2\"],\"param\":" + "[\"228236\",\"228235\",\"172228\"],\"domain\":\"g\"}"); } } { @@ -66,25 +67,55 @@ CASE("test_request_json") { std::stringstream ss; eckit::JSON plain(ss); r.json(plain); - EXPECT_EQUAL( - ss.str(), - "{\"class\":\"od\",\"expver\":\"0001\",\"stream\":\"wave\",\"date\":\"20240729\",\"time\":\"0000\"," - "\"type\":\"an\",\"levtype\":\"sfc\",\"step\":\"24\",\"param\":\"140251\",\"domain\":\"g\",\"repres\":" - "\"sh\"}"); + EXPECT_EQUAL(ss.str(), + "{\"class\":\"od\",\"type\":\"an\",\"stream\":\"wave\",\"levtype\":\"sfc\",\"date\":" + "\"20240729\",\"time\":\"0000\",\"step\":\"24\",\"expver\":\"0001\",\"param\":\"140251\"," + "\"domain\":\"g\"}"); } { std::stringstream ss; eckit::JSON array(ss); r.json(array, true); - EXPECT_EQUAL( - ss.str(), - "{\"class\":\"od\",\"expver\":\"0001\",\"stream\":\"wave\",\"date\":[\"20240729\"],\"time\":[\"0000\"]," - "\"type\":\"an\",\"levtype\":\"sfc\",\"step\":[\"24\"],\"param\":[\"140251\"],\"domain\":\"g\"," - "\"repres\":\"sh\"}"); + EXPECT_EQUAL(ss.str(), + "{\"class\":\"od\",\"type\":\"an\",\"stream\":\"wave\",\"levtype\":\"sfc\",\"date\":[" + "\"20240729\"],\"time\":[\"0000\"],\"step\":[\"24\"],\"expver\":\"0001\",\"param\":[" + "\"140251\"],\"domain\":\"g\"}"); } } } +CASE("test_request_count") { + { + const char* text = + "retrieve,class=od,expver=0079,stream=enfh,date=20240729,time=00/" + "12,type=fcmean,levtype=sfc,step=24,number=1/to/2,param=mucin/mucape/tprate"; + MarsRequest r = MarsRequest::parse(text); + EXPECT_EQUAL(12, r.count()); + } + { + const char* text = + "retrieve,accuracy=16,class=od,date=20230810,expver=1,levelist=1/to/" + "137,levtype=ml,number=-1,param=z,process=local,step=000,stream=scda,time=18,type=an,target=reference.data"; + MarsRequest r = MarsRequest::parse(text); + EXPECT_EQUAL(1, r.count()); + } + { + const char* text = + "retrieve,accuracy=16,class=od,date=20230810,expver=1,levelist=1/to/137,levtype=ml,number=-1,param=z/" + "t,process=local,step=000,stream=scda,time=18,type=an,target=reference.data"; + MarsRequest r = MarsRequest::parse(text); + EXPECT_EQUAL(138, r.count()); + } + { + const char* text = + "retrieve,accuracy=16,class=od,date=20230810,expver=1,levelist=1/to/137,levtype=ml,number=-1,param=22/127/" + "128/129/152/u/v,process=local,step=000,stream=scda,time=18,type=an,target=reference.data"; + MarsRequest r = MarsRequest::parse(text); + EXPECT_EQUAL(279, r.count()); + } +} + + //----------------------------------------------------------------------------- } // namespace test diff --git a/tests/test_step.cc b/tests/test_step.cc index 37174ac8..0dbdba52 100644 --- a/tests/test_step.cc +++ b/tests/test_step.cc @@ -30,7 +30,7 @@ using ::eckit::BadValue; void assertTypeExpansion(const std::string& name, std::vector values, const std::vector& expected) { static MarsLanguage language("retrieve"); - language.type(name)->expand(DummyContext(), values); + language.type(name)->expand(DummyContext{}, MarsRequest{}, values); EXPECT_EQUAL(expected, values); } diff --git a/tests/test_time.cc b/tests/test_time.cc index 4d01c142..502c4fcf 100644 --- a/tests/test_time.cc +++ b/tests/test_time.cc @@ -34,7 +34,7 @@ using ::eckit::Value; void assertTypeExpansion(const std::string& name, std::vector values, const std::vector& expected) { static MarsLanguage language("retrieve"); - language.type(name)->expand(DummyContext(), values); + language.type(name)->expand(DummyContext(), MarsRequest{}, values); EXPECT_EQUAL(expected, values); } @@ -43,32 +43,33 @@ CASE("Test TypeTime expansions") { TypeTime ttime("time", Value()); Type& tt(ttime); DummyContext ctx; + MarsRequest r; // 1 and 2-digit times { std::string value = "0"; - tt.expand(ctx, value); + tt.expand(ctx, r, value); EXPECT(value == "0000"); } { std::string value = "00"; - tt.expand(ctx, value); + tt.expand(ctx, r, value); EXPECT(value == "0000"); } { std::string value = "12"; - tt.expand(ctx, value); + tt.expand(ctx, r, value); EXPECT(value == "1200"); } { std::string value = "6"; - tt.expand(ctx, value); + tt.expand(ctx, r, value); EXPECT(value == "0600"); } { std::string value = "06"; - tt.expand(ctx, value); + tt.expand(ctx, r, value); EXPECT(value == "0600"); } @@ -76,162 +77,162 @@ CASE("Test TypeTime expansions") { { std::string value = "000"; - tt.expand(ctx, value); + tt.expand(ctx, r, value); EXPECT(value == "0000"); } { std::string value = "0000"; - tt.expand(ctx, value); + tt.expand(ctx, r, value); EXPECT(value == "0000"); } { std::string value = "012"; - tt.expand(ctx, value); + tt.expand(ctx, r, value); EXPECT(value == "0012"); } { std::string value = "0012"; - tt.expand(ctx, value); + tt.expand(ctx, r, value); EXPECT(value == "0012"); } { std::string value = "1234"; - tt.expand(ctx, value); + tt.expand(ctx, r, value); EXPECT(value == "1234"); } { std::string value = "623"; - tt.expand(ctx, value); + tt.expand(ctx, r, value); EXPECT(value == "0623"); } { std::string value = "0623"; - tt.expand(ctx, value); + tt.expand(ctx, r, value); EXPECT(value == "0623"); } { std::string value = "675"; - EXPECT_THROWS_AS(tt.expand(ctx, value), BadTime); + EXPECT_THROWS_AS(tt.expand(ctx, r, value), BadTime); } // 5 and 6-digit times { std::string value = "000000"; - tt.expand(ctx, value); + tt.expand(ctx, r, value); EXPECT(value == "0000"); } { // We don't support seconds yet. std::string value = "000012"; - EXPECT_THROWS_AS(tt.expand(ctx, value), BadValue); + EXPECT_THROWS_AS(tt.expand(ctx, r, value), BadValue); } { std::string value = "001200"; - tt.expand(ctx, value); + tt.expand(ctx, r, value); EXPECT(value == "0012"); } { std::string value = "123400"; - tt.expand(ctx, value); + tt.expand(ctx, r, value); EXPECT(value == "1234"); } { std::string value = "062300"; - tt.expand(ctx, value); + tt.expand(ctx, r, value); EXPECT(value == "0623"); } { std::string value = "62300"; - tt.expand(ctx, value); + tt.expand(ctx, r, value); EXPECT(value == "0623"); } { // We don't support seconds yet. std::string value = "123456"; - EXPECT_THROWS_AS(tt.expand(ctx, value), BadValue); + EXPECT_THROWS_AS(tt.expand(ctx, r, value), BadValue); } { // We don't support time > 24h std::string value = "283456"; - EXPECT_THROWS_AS(tt.expand(ctx, value), BadValue); + EXPECT_THROWS_AS(tt.expand(ctx, r, value), BadValue); } // times with colons { std::string value = "0:0"; - tt.expand(ctx, value); + tt.expand(ctx, r, value); EXPECT(value == "0000"); } { std::string value = "00:00"; - tt.expand(ctx, value); + tt.expand(ctx, r, value); EXPECT(value == "0000"); } { std::string value = "00:00:00"; - tt.expand(ctx, value); + tt.expand(ctx, r, value); EXPECT(value == "0000"); } { std::string value = "0:12"; - tt.expand(ctx, value); + tt.expand(ctx, r, value); EXPECT(value == "0012"); } { std::string value = "00:12"; - tt.expand(ctx, value); + tt.expand(ctx, r, value); EXPECT(value == "0012"); } { std::string value = "00:62"; - EXPECT_THROWS_AS(tt.expand(ctx, value), BadTime); + EXPECT_THROWS_AS(tt.expand(ctx, r, value), BadTime); } { std::string value = "12:34"; - tt.expand(ctx, value); + tt.expand(ctx, r, value); EXPECT(value == "1234"); } { std::string value = "6:23"; - tt.expand(ctx, value); + tt.expand(ctx, r, value); EXPECT(value == "0623"); } { std::string value = "06:23"; - tt.expand(ctx, value); + tt.expand(ctx, r, value); EXPECT(value == "0623"); } { // We don't support seconds yet. std::string value = "00:00:12"; - EXPECT_THROWS_AS(tt.expand(ctx, value), BadValue); + EXPECT_THROWS_AS(tt.expand(ctx, r, value), BadValue); } { std::string value = "00:12:00"; - tt.expand(ctx, value); + tt.expand(ctx, r, value); EXPECT(value == "0012"); } { std::string value = "12:34:00"; - tt.expand(ctx, value); + tt.expand(ctx, r, value); EXPECT(value == "1234"); } { std::string value = "06:23:00"; - tt.expand(ctx, value); + tt.expand(ctx, r, value); EXPECT(value == "0623"); } { std::string value = "6:23:00"; - tt.expand(ctx, value); + tt.expand(ctx, r, value); EXPECT(value == "0623"); } { // We don't support seconds yet. std::string value = "12:34:56"; - EXPECT_THROWS_AS(tt.expand(ctx, value), BadValue); + EXPECT_THROWS_AS(tt.expand(ctx, r, value), BadValue); } // times with units diff --git a/tests/test_type_levelist.cc b/tests/test_type_levelist.cc index 70127479..7d2b13cf 100644 --- a/tests/test_type_levelist.cc +++ b/tests/test_type_levelist.cc @@ -38,7 +38,7 @@ CASE("test_metkit_exists_to-by-list-float") { void assertTypeExpansion(const std::string& name, std::vector values, const std::vector& expected) { static MarsLanguage language("retrieve"); - language.type(name)->expand(DummyContext(), values); + language.type(name)->expand(DummyContext{}, MarsRequest{}, values); ASSERT(values == expected); }