Skip to content

Commit

Permalink
592 improve warning message at types util check unset (#593)
Browse files Browse the repository at this point in the history
* Adress issue #592

* Update docstring and comments for io.createParsedType

* Add unittest for io.createParsedType

* Update createParsedType.m

Fix: avoid showing warning twice
  • Loading branch information
ehennestad authored Sep 13, 2024
1 parent 4b280cb commit c51099f
Show file tree
Hide file tree
Showing 5 changed files with 100 additions and 10 deletions.
58 changes: 58 additions & 0 deletions +io/createParsedType.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
function typeInstance = createParsedType(typePath, typeName, varargin)
% createParsedType - Create a neurodata type from a specified type name
%
% This function generates a neurodata type instance from a given type name
% and a corresponding cell array of name-value pairs. It is typically used
% when parsing datasets or groups.
%
% Warnings with the ID "NWB:CheckUnset:InvalidProperties" are captured, and
% the warning message is enhanced with specific details about the dataset or
% group in the NWB file where the issue occurred.
%
% Inputs:
% typePath - (char) Path to the dataset or group in the NWB file where the
% neurodata type is parsed from.
% typeName - (char) Name of the neurodata type to be created.
% varargin - (cell) Cell array of name-value pairs representing the
% properties of the neurodata type.
%
% Outputs:
% typeInstance - The generated neurodata type instance.


warnState = warning('off', 'NWB:CheckUnset:InvalidProperties');
cleanupObj = onCleanup(@(s) warning(warnState)); % Make sure warning state is reset later

[lastWarningMessage, lastWarningID] = lastwarn('', ''); % Clear last warning

typeInstance = feval(typeName, varargin{:}); % Create the type.

[warningMessage, warningID] = lastwarn();

% Handle any warnings if they occured.
if ~isempty(warningMessage)
if strcmp( warningID, 'NWB:CheckUnset:InvalidProperties' )

clear cleanupObj % Reset last warning state

if endsWith(warningMessage, '.')
warningMessage = warningMessage(1:end-1);
end

updatedMessage = sprintf('%s at file location "%s"\n', warningMessage, typePath);

disclaimer = 'NB: The properties in question were dropped while reading the file.';

suggestion = [...
'Consider checking the schema version of the file with '...
'`util.getSchemaVersion(filename)` and comparing with the ' ...
'YAML namespace version present in nwb-schema/core/nwb.namespace.yaml' ];

warning(warningID, '%s\n%s\n\n%s', updatedMessage, disclaimer, suggestion)
else
% Pass, warning has already been displayed
end
else
lastwarn(lastWarningMessage, lastWarningID); % Reset last warning
end
end
2 changes: 1 addition & 1 deletion +io/parseDataset.m
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@
else
props('data') = data;
kwargs = io.map2kwargs(props);
parsed = eval([Type.typename '(kwargs{:})']);
parsed = io.createParsedType(fullpath, Type.typename, kwargs{:});
end
H5D.close(did);
H5F.close(fid);
Expand Down
5 changes: 3 additions & 2 deletions +io/parseGroup.m
Original file line number Diff line number Diff line change
Expand Up @@ -77,12 +77,13 @@
else
file.cloneNwbFileClass(Type.name, Type.typename);
rehash();
parsed = eval([Type.typename '(kwargs{:})']);
parsed = io.createParsedType(info.Name, Type.typename, kwargs{:});

end

return;
end
parsed = eval([Type.typename '(kwargs{:})']);
parsed = io.createParsedType(info.Name, Type.typename, kwargs{:});
end
end

Expand Down
35 changes: 35 additions & 0 deletions +tests/+unit/+io/testCreateParsedType.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
function tests = testCreateParsedType()
tests = functiontests(localfunctions);
end

function setupOnce(testCase)
rootPath = fullfile(fileparts(mfilename('fullpath')), '..', '..', '..');
testCase.applyFixture(matlab.unittest.fixtures.PathFixture(rootPath));

testCase.applyFixture(matlab.unittest.fixtures.WorkingFolderFixture);
generateCore('savedir', '.')
end

function testCreateTypeWithValidInputs(testCase)
testPath = 'some/dataset/path';
testType = 'types.hdmf_common.VectorIndex';
kwargs = {'description', 'this is a test'};

type = io.createParsedType(testPath, testType, kwargs{:});
testCase.verifyClass(type, testType)

testCase.verifyWarningFree(...
@(varargin)io.createParsedType(testPath, testType, kwargs{:}))
end

function testCreateTypeWithInvalidInputs(testCase)
testPath = 'some/dataset/path';
testType = 'types.hdmf_common.VectorIndex';
kwargs = {'description', 'this is a test', 'comment', 'this is another test'};
type = io.createParsedType(testPath, testType, kwargs{:});
testCase.verifyClass(type, testType)

testCase.verifyWarning(...
@(varargin)io.createParsedType(testPath, testType, kwargs{:}), ...
'NWB:CheckUnset:InvalidProperties')
end
10 changes: 3 additions & 7 deletions +types/+util/checkUnset.m
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,8 @@ function checkUnset(obj, argin)
end
dropped = setdiff(argin, union(allProperties, anonNames));
if ~isempty(dropped)
warning('NWB:CheckUnset:InvalidProperties' ...
, ['Unexpected properties {%s}. '...
'\n\nYour schema version may be incompatible with the file. '...
'Consider checking the schema version of the file with '...
'`util.getSchemaVersion(filename)` '...
'and comparing with the YAML namespace version present in '...
'nwb-schema/core/nwb.namespace.yaml'], misc.cellPrettyPrint(dropped));
warning('NWB:CheckUnset:InvalidProperties', ...
'Unexpected properties {%s} for instance of type "%s".', ...
misc.cellPrettyPrint(dropped), class(obj));
end
end

0 comments on commit c51099f

Please sign in to comment.