From f316792cd0d94a0e52e87d2ad09236b6506406a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Karsten=20M=C3=BCller?= <52325194+karstenm1987@users.noreply.github.com> Date: Wed, 30 Sep 2026 22:41:39 +0200 Subject: [PATCH 1/2] Translate CS source aliases with any slot number normalizeSourceName translated CS_ to the file name _ only when the name had 7 characters, so two-digit slots such as CS10_ITA requested CS10_ITA.dta, which does not exist. It now matches ^CS(\d+)_([A-Za-z]{3})$ case-insensitively and also returns the CS column prefix, which loadSourceData uses to select and list variables. Other source names are unchanged. Adds a trimmed ITA_10 fixture and offline tests for CS10_ITA, cs10_ita, ITA_10 and the variable error message. Co-Authored-By: Claude Opus 5.5 --- +globalmacrodata/gmd.m | 8 +---- .../private/normalizeSourceName.m | 14 +++++---- tests/fixtures/clean/combined/ITA_10.dta | Bin 0 -> 1421 bytes tests/tGmdOffline.m | 28 ++++++++++++++++++ 4 files changed, 38 insertions(+), 12 deletions(-) create mode 100644 tests/fixtures/clean/combined/ITA_10.dta diff --git a/+globalmacrodata/gmd.m b/+globalmacrodata/gmd.m index b133ba0..7e5fc20 100644 --- a/+globalmacrodata/gmd.m +++ b/+globalmacrodata/gmd.m @@ -434,13 +434,7 @@ end function out = loadSourceData(srcName, anything, countryArg) - csColPrefix = ''; - name = strtrim(srcName); - if numel(name) == 7 && startsWith(name, 'CS') - parts = strsplit(name, '_'); - csColPrefix = parts{1}; - name = normalizeSourceName(name); - end + [name, csColPrefix] = normalizeSourceName(srcName); srcTokens = tokens(name); if numel(srcTokens) > 1 fail(498, 'Warning: Please specify exactly one source.'); diff --git a/+globalmacrodata/private/normalizeSourceName.m b/+globalmacrodata/private/normalizeSourceName.m index de87abd..771b6b4 100644 --- a/+globalmacrodata/private/normalizeSourceName.m +++ b/+globalmacrodata/private/normalizeSourceName.m @@ -1,9 +1,13 @@ -function s = normalizeSourceName(source) -%NORMALIZESOURCENAME Convert a 7-char CS alias (e.g. "CS1_ARG") to "ARG_1". -% Ports the Python _normalize_source_name helper. +function [s, csPrefix] = normalizeSourceName(source) +%NORMALIZESOURCENAME Convert a CS alias (e.g. "CS1_ARG", "CS10_ITA") to "ARG_1". +% Also returns the column prefix inside the file ("CS1"), or '' when the +% name is not a CS alias. Ports the Python _normalize_source_name helper. s = strtrim(char(source)); - if numel(s) == 7 && startsWith(s, 'CS') - s = sprintf('%s_%s', s(end-2:end), s(3)); + csPrefix = ''; + tok = regexp(s, '^CS(\d+)_([A-Za-z]{3})$', 'tokens', 'once', 'ignorecase'); + if ~isempty(tok) + csPrefix = ['CS', tok{1}]; + s = sprintf('%s_%s', upper(tok{2}), tok{1}); end end diff --git a/tests/fixtures/clean/combined/ITA_10.dta b/tests/fixtures/clean/combined/ITA_10.dta new file mode 100644 index 0000000000000000000000000000000000000000..d1a71c9ba066b62f5c3b9fbc287fd4ac72187cf3 GIT binary patch literal 1421 zcmXS7Vq{=t;9{TwFg8#KPAyO{GB7ezFfy_-wq#)b`~Uxc&tQLJytY-QCKlmU;2dmd z5bqq|iBl0+L7uxy04^0^1x0uiAZt`LE=J}OW~&++=^3OGRtHz1YG^RnG{D_9$`}m+ z(nG*A#4&>%tnENGYnVfZUeh{<{l^`EA_`aaPB;LiGa=Fmul|HO7&pxnjx#<1l1{K_ z1WRW@q#Mj0hdR8g2=?6636^fSb{s674Uv8zd@0ny%TYn|nZ!wu?gJgRCqahiK%^Hm zoeXt2duq4YJl0bnX$KGul+H!c4HO1~2lYVWK*}nxbRI++>~gRyL|VbV?leeuK1AB# t Date: Wed, 30 Sep 2026 22:47:33 +0200 Subject: [PATCH 2/2] Fix normalizeSourceName help text and test trimming and near misses The help line read as if CS10_ITA mapped to ARG_1; it now gives both examples with their own file names. Adds offline tests that " CS10_ITA " is trimmed and translated, and that CS1_ARGX is not a CS alias and does not resolve to ARG_1. Co-Authored-By: Claude Opus 5.5 --- +globalmacrodata/private/normalizeSourceName.m | 7 ++++--- tests/tGmdOffline.m | 10 ++++++++++ 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/+globalmacrodata/private/normalizeSourceName.m b/+globalmacrodata/private/normalizeSourceName.m index 771b6b4..32eb278 100644 --- a/+globalmacrodata/private/normalizeSourceName.m +++ b/+globalmacrodata/private/normalizeSourceName.m @@ -1,7 +1,8 @@ function [s, csPrefix] = normalizeSourceName(source) -%NORMALIZESOURCENAME Convert a CS alias (e.g. "CS1_ARG", "CS10_ITA") to "ARG_1". -% Also returns the column prefix inside the file ("CS1"), or '' when the -% name is not a CS alias. Ports the Python _normalize_source_name helper. +%NORMALIZESOURCENAME Convert a CS alias to its file name. +% "CS1_ARG" -> "ARG_1", "CS10_ITA" -> "ITA_10". Also returns the column +% prefix inside the file ("CS1", "CS10"), or '' when the name is not a CS +% alias. Ports the Python _normalize_source_name helper. s = strtrim(char(source)); csPrefix = ''; diff --git a/tests/tGmdOffline.m b/tests/tGmdOffline.m index 07b5451..599b529 100644 --- a/tests/tGmdOffline.m +++ b/tests/tGmdOffline.m @@ -133,6 +133,16 @@ function sourceCsAliasIgnoresCase(tc) tc.verifyTrue(ismember('CS10_rGDP', df.Properties.VariableNames)); end + function sourceCsAliasTrimsWhitespace(tc) + df = globalmacrodata.gmd('sources',' CS10_ITA ','variables','CPI'); + tc.verifyEqual(df.Properties.VariableNames, {'ISO3','year','CS10_CPI'}); + end + + function sourceCsNearMissNotTranslated(tc) + % CS1_ARGX is not a CS alias, so it must not resolve to ARG_1. + tc.verifyError(@() globalmacrodata.gmd('sources','CS1_ARGX'), 'GMD:e498'); + end + function sourceFileNameLoads(tc) df = globalmacrodata.gmd('sources','ITA_10'); tc.verifyTrue(ismember('CS10_CPI', df.Properties.VariableNames));