Skip to content

Commit

Permalink
Add ErrorID and warningID for all user-facing code (#617)
Browse files Browse the repository at this point in the history
* Add warning IDs for where missing

* Add errorID where missing

* Add errorIDs to class generators and update regenerate types with errorIDs

* Add errorID to checkCustomConstraint method of TimeSeries
  • Loading branch information
ehennestad authored Nov 8, 2024
1 parent 5aa27d9 commit d970ef1
Show file tree
Hide file tree
Showing 39 changed files with 120 additions and 67 deletions.
22 changes: 13 additions & 9 deletions +file/Dataset.m
Original file line number Diff line number Diff line change
Expand Up @@ -121,15 +121,19 @@

%constrained
% error unless it defines the object.

if isempty(obj.type)
error('You shouldn''t be calling getProps on an untyped dataset');
end

if obj.isConstrainedSet && ~obj.definesType
error('You shouldn''t be calling getProps on a constrained dataset');
end


assert(...
~isempty(obj.type), ...
'NWB:Dataset:UnsupportedOperation', ...
'The method `getProps` should not be called on an untyped dataset.' ...
);

assert( ...
~obj.isConstrainedSet || obj.definesType, ...
'NWB:Dataset:UnsupportedOperation', ...
'The method `getProps` should not be called on constrained dataset.' ...
);

if ~isempty(obj.dtype)
props('data') = obj.dtype;
end
Expand Down
8 changes: 7 additions & 1 deletion +file/Group.m
Original file line number Diff line number Diff line change
Expand Up @@ -146,8 +146,14 @@
%should never happen

if obj.isConstrainedSet && ~obj.definesType
error('getProps shouldn''t be called on a constrained set.');
error('NWB:Group:UnsupportedOperation', ...
'The method `getProps` should not be called on a constrained dataset.');
end
assert( ...
~obj.isConstrainedSet || obj.definesType, ...
'NWB:Group:UnsupportedOperation', ...
'The method `getProps` should not be called on a constrained group.' ...
);

%datasets
for i=1:length(obj.datasets)
Expand Down
5 changes: 3 additions & 2 deletions +file/fillConstructor.m
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,8 @@
end
end

%warn for missing namespaces/property types
% warn for missing namespaces/property types
warningId = 'NWB:ClassGenerator:NamespaceOrTypeNotFound';
warnmsg = ['`' parentName '`''s constructor is unable to check for type `%1$s` ' ...
'because its namespace or type specifier could not be found. Try generating ' ...
'the namespace or class definition for type `%1$s` or fix its schema.'];
Expand All @@ -109,7 +110,7 @@
invalidWarn = invalid & (dynamicConstrained | isAnonymousType) & ~isAttribute;
invalidVars = varnames(invalidWarn);
for i=1:length(invalidVars)
warning(warnmsg, invalidVars{i});
warning(warningId, warnmsg, invalidVars{i});
end
varnames = lower(varnames);

Expand Down
2 changes: 2 additions & 0 deletions +file/fillCustomConstraint.m
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,11 @@
customConstraintStr = sprintf( [...
'function checkCustomConstraint(obj)\n', ...
' assert(~isempty(obj.timestamps) || ~isempty(obj.starting_time), ...\n', ...
' ''NWB:TimeSeries:TimeNotSpecified'', ...\n ', ...
' "''timestamps'' or ''starting_time'' must be specified")\n', ...
' if ~isempty(obj.starting_time)\n', ...
' assert(~isempty(obj.starting_time_rate), ...\n', ...
' ''NWB:TimeSeries:RateMissing'', ...\n', ...
' "''starting_time_rate'' must be specified when ''starting_time'' is specified")\n', ...
' end\n', ...
'end'] );
Expand Down
6 changes: 4 additions & 2 deletions +file/fillProps.m
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,8 @@
case 'object'
refTypeName = 'Object';
otherwise
error('Invalid reftype found whilst filling Constructor prop docs.');
error('NWB:ClassGenerator:InvalidRefType', ...
'Invalid reftype found while filling description for class property "%s".', propName);
end
typeStr = sprintf('%s Reference to %s', refTypeName, prop.dtype('target_type'));
else
Expand All @@ -71,7 +72,8 @@
case 'object'
refTypeName = 'object';
otherwise
error('Invalid reftype found whilst filling Constructor prop docs.');
error('NWB:ClassGenerator:InvalidRefType', ...
'Invalid reftype found while filling description for class property "%s".', propName);
end
typeStr = sprintf('%s Reference to %s', refTypeName, prop('target_type'));
elseif isa(prop, 'file.interface.HasProps')
Expand Down
8 changes: 4 additions & 4 deletions +file/fillValidators.m
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,7 @@
' return;'...
'end'...
'if ~istable(val) && ~isstruct(val) && ~isa(val, ''containers.Map'')'...
[' error(''Property `' name '` must be a table,struct, or containers.Map.'');']...
[' error(''NWB:Type:InvalidPropertyType'', ''Property `' name '` must be a table, struct, or containers.Map.'');']...
'end'...
'vprops = struct();'...
}, newline);
Expand Down Expand Up @@ -294,8 +294,7 @@

classNameSplit = strsplit(className, '.');
shortName = classNameSplit{end};

errorStr = sprintf( 'error(''Unable to set the ''''%s'''' property of class ''''<a href="matlab:doc %s">%s</a>'''' because it is read-only.'')', name, className, shortName);
errorStr = sprintf( 'error(''NWB:Type:ReadOnlyProperty'', ''Unable to set the ''''%s'''' property of class ''''<a href="matlab:doc %s">%s</a>'''' because it is read-only.'')', name, className, shortName);

if ischar(value)
condition = strjoin({ ...
Expand All @@ -311,7 +310,8 @@
% Note: According to the documentation for Attribute specification keys
% (https://schema-language.readthedocs.io/en/latest/description.html#sec-attributes-spec),
% the above cases should be sufficient.
error('Unhandled case')
error('NWB:ClassGenerator:ReadOnlyValidatorNotImplemented', ...
'Read-only validator is not implemented for values of type "%s"', class(value))
end

fdvstr = strjoin({...
Expand Down
3 changes: 2 additions & 1 deletion +io/getBaseType.m
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@

id = [prefix suffix];
else
error('Type `%s` is not a supported raw type', type);
error('NWB:IO:UnsupportedBaseType', ...
'Type `%s` is not a supported raw type', type);
end
end
4 changes: 2 additions & 2 deletions +io/parseGroup.m
Original file line number Diff line number Diff line change
Expand Up @@ -116,14 +116,14 @@
if any(leads)
%since set has been edited, we bubble up deletion of the old keys.
subset = elide(pvalue, prop(leads), pvar);
elided = [elided; subset];
elided = [elided; subset]; %#ok<AGROW>
if pvalue.Count == 0
drop(i) = true;
elseif any(strcmp(pvar, prop))
elided(pvar) = pvalue;
drop(i) = true;
else
warning('Unable to match property `%s` under prefix `%s`',...
warning('NWB:Parse:UnmatchedProperty', 'Unable to match property `%s` under prefix `%s`',...
pvar, prefix);
end
end
Expand Down
3 changes: 1 addition & 2 deletions +io/resolvePath.m
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@

%process slash tokens
o = nwb;
errmsg = 'Could not resolve path `%s`.';
while ~isempty(tokens)
if isa(o, 'types.untyped.Set')
[o, tokens] = resolveSet(o, tokens);
Expand All @@ -18,7 +17,7 @@
[o, tokens] = resolveObj(o, tokens);
end
if isempty(o)
error(errmsg, path);
error('NWB:IO:UnresolvedPath', 'Could not resolve path `%s`.', path);
end
end
end
Expand Down
7 changes: 3 additions & 4 deletions +io/timestamp2datetime.m
Original file line number Diff line number Diff line change
Expand Up @@ -113,9 +113,8 @@
elseif ischar(timestamps)
cells = {timestamps};
else
errorId = "NWB:timestamp2datetime:MustBeCharCellArrayOrString";
errorMsg = ['timestamps must be a string, character array, ', ...
'or cell array of strings/character arrays.'];
error(errorId, errorMsg);
error('NWB:timestamp2datetime:MustBeCharCellArrayOrString', ...
[ 'Timestamps must be a string, character array, ', ...
'or cell array of strings/character arrays.' ]);
end
end
31 changes: 30 additions & 1 deletion +io/writeCompound.m
Original file line number Diff line number Diff line change
@@ -1,4 +1,32 @@
function writeCompound(fid, fullpath, data, varargin)
% writeCompound - Write structured data to an HDF5 compound dataset.
%
% io.writeCompound(fid, fullpath, data, varargin) converts data (in table,
% struct, or containers.Map format) into a scalar struct, optimizes it for
% HDF5 storage, and writes it to an HDF5 compound dataset specified by fid
% and fullpath.
%
% Inputs:
% fid - File identifier for an open HDF5 file.
% fullpath - Full path within the HDF5 file where data will be stored.
% data - Data to write, provided as a table, struct, or containers.Map.
% varargin - Additional optional arguments.
%
% Functionality:
% - Converts input data into a scalar struct, rearranging fields and types as needed.
% - Detects data types, sizes, and handles compound HDF5 type creation.
% - Optimizes data for HDF5 by transposing column vectors and converting logicals.
% - Manages references to external data objects, regions, or untyped views.
% - Attempts to extend or overwrite existing datasets if a compound dataset at
% the specified path already exists.
%
% Notes:
% - If `fullpath` already exists in the HDF5 file, the function tries to adjust
% dimensions if the dataset is chunked, and issues a warning if resizing is not allowed.
%
% Example:
% io.writeCompound(fid, '/group/dataset', data);

%convert to a struct
if istable(data)
data = table2struct(data);
Expand Down Expand Up @@ -103,7 +131,8 @@ function writeCompound(fid, fullpath, data, varargin)
if is_chunked
H5D.set_extent(did, dims);
else
warning('Attempted to change size of continuous compound `%s`. Skipping.',...
warning('NWB:WriteCompund:ContinuousCompoundResize', ...
'Attempted to change size of continuous compound `%s`. Skipping.', ...
fullpath);
end
end
Expand Down
3 changes: 2 additions & 1 deletion +io/writeDataset.m
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ function writeDataset(fid, fullpath, data, varargin)
if ~is_same_dims && is_chunked
H5D.set_extent(did, dims);
elseif ~is_same_dims
warning('Attempted to change size of continuous dataset `%s`. Skipping.',...
warning('NWB:WriteDataset:ContinuousDatasetResize', ...
'Attempted to change size of continuous dataset `%s`. Skipping.',...
fullpath);
H5S.close(sid);
H5D.close(did);
Expand Down
4 changes: 3 additions & 1 deletion +misc/str2validName.m
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
% Converts the property name into a valid matlab property name.
% propname: the offending property name
% prefix: optional prefix to use instead of the ambiguous "dyn"

if ~iscell(propname) && isvarname(propname)
valid = propname;
return;
Expand All @@ -12,7 +13,8 @@
prefix = 'dyn_';
else
if ~isvarname(prefix)
warning('Prefix contains invalid variable characters. Reverting to "dyn"');
warning('NWB:CreateValidPropertyName:InvalidPrefix', ...
'Prefix contains invalid variable characters. Reverting to "dyn"');
prefix = 'dyn_';
end
end
Expand Down
10 changes: 5 additions & 5 deletions +schemes/Namespace.m
Original file line number Diff line number Diff line change
Expand Up @@ -41,18 +41,18 @@
function parent = getParent(obj, classname)
class = obj.getClass(classname);
if isempty(class)
error('Could not find class %s', classname);
error('NWB:Namespace:ClassNotFound', 'Could not find class %s', classname);
end

parent = [];
hasParentKey = isKey(class, obj.PARENT_KEYS);
if any(hasParentKey)
parentName = class(obj.PARENT_KEYS{hasParentKey});
parent = obj.getClass(parentName);
assert(~isempty(parent),...
'Parent %s for class %s doesn''t exist! Missing Dependency?',...
parentName,...
classname);
assert(~isempty(parent), ...
'NWB:Namespace:ParentNotFound', ...
'Parent %s for class %s doesn''t exist! Missing Dependency?', ...
parentName, classname);
end
end

Expand Down
4 changes: 2 additions & 2 deletions +types/+core/AnnotationSeries.m
Original file line number Diff line number Diff line change
Expand Up @@ -52,14 +52,14 @@
if isequal(val, -1)
val = -1;
else
error('Unable to set the ''data_resolution'' property of class ''<a href="matlab:doc types.core.AnnotationSeries">AnnotationSeries</a>'' because it is read-only.')
error('NWB:Type:ReadOnlyProperty', 'Unable to set the ''data_resolution'' property of class ''<a href="matlab:doc types.core.AnnotationSeries">AnnotationSeries</a>'' because it is read-only.')
end
end
function val = validate_data_unit(obj, val)
if isequal(val, 'n/a')
val = 'n/a';
else
error('Unable to set the ''data_unit'' property of class ''<a href="matlab:doc types.core.AnnotationSeries">AnnotationSeries</a>'' because it is read-only.')
error('NWB:Type:ReadOnlyProperty', 'Unable to set the ''data_unit'' property of class ''<a href="matlab:doc types.core.AnnotationSeries">AnnotationSeries</a>'' because it is read-only.')
end
end
%% EXPORT
Expand Down
2 changes: 1 addition & 1 deletion +types/+core/CurrentClampSeries.m
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@
if isequal(val, 'volts')
val = 'volts';
else
error('Unable to set the ''data_unit'' property of class ''<a href="matlab:doc types.core.CurrentClampSeries">CurrentClampSeries</a>'' because it is read-only.')
error('NWB:Type:ReadOnlyProperty', 'Unable to set the ''data_unit'' property of class ''<a href="matlab:doc types.core.CurrentClampSeries">CurrentClampSeries</a>'' because it is read-only.')
end
end
%% EXPORT
Expand Down
2 changes: 1 addition & 1 deletion +types/+core/CurrentClampStimulusSeries.m
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
if isequal(val, 'amperes')
val = 'amperes';
else
error('Unable to set the ''data_unit'' property of class ''<a href="matlab:doc types.core.CurrentClampStimulusSeries">CurrentClampStimulusSeries</a>'' because it is read-only.')
error('NWB:Type:ReadOnlyProperty', 'Unable to set the ''data_unit'' property of class ''<a href="matlab:doc types.core.CurrentClampStimulusSeries">CurrentClampStimulusSeries</a>'' because it is read-only.')
end
end
%% EXPORT
Expand Down
2 changes: 1 addition & 1 deletion +types/+core/ElectricalSeries.m
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@
if isequal(val, 'volts')
val = 'volts';
else
error('Unable to set the ''data_unit'' property of class ''<a href="matlab:doc types.core.ElectricalSeries">ElectricalSeries</a>'' because it is read-only.')
error('NWB:Type:ReadOnlyProperty', 'Unable to set the ''data_unit'' property of class ''<a href="matlab:doc types.core.ElectricalSeries">ElectricalSeries</a>'' because it is read-only.')
end
end
function val = validate_electrodes(obj, val)
Expand Down
2 changes: 1 addition & 1 deletion +types/+core/ElectrodeGroup.m
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@
return;
end
if ~istable(val) && ~isstruct(val) && ~isa(val, 'containers.Map')
error('Property `position` must be a table,struct, or containers.Map.');
error('NWB:Type:InvalidPropertyType', 'Property `position` must be a table, struct, or containers.Map.');
end
vprops = struct();
vprops.x = 'single';
Expand Down
2 changes: 1 addition & 1 deletion +types/+core/IZeroClampSeries.m
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@
if isequal(val, 'N/A')
val = 'N/A';
else
error('Unable to set the ''stimulus_description'' property of class ''<a href="matlab:doc types.core.IZeroClampSeries">IZeroClampSeries</a>'' because it is read-only.')
error('NWB:Type:ReadOnlyProperty', 'Unable to set the ''stimulus_description'' property of class ''<a href="matlab:doc types.core.IZeroClampSeries">IZeroClampSeries</a>'' because it is read-only.')
end
end
%% EXPORT
Expand Down
2 changes: 1 addition & 1 deletion +types/+core/IndexSeries.m
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@
if isequal(val, 'N/A')
val = 'N/A';
else
error('Unable to set the ''data_unit'' property of class ''<a href="matlab:doc types.core.IndexSeries">IndexSeries</a>'' because it is read-only.')
error('NWB:Type:ReadOnlyProperty', 'Unable to set the ''data_unit'' property of class ''<a href="matlab:doc types.core.IndexSeries">IndexSeries</a>'' because it is read-only.')
end
end
function val = validate_indexed_images(obj, val)
Expand Down
4 changes: 2 additions & 2 deletions +types/+core/IntervalSeries.m
Original file line number Diff line number Diff line change
Expand Up @@ -52,14 +52,14 @@
if isequal(val, -1)
val = -1;
else
error('Unable to set the ''data_resolution'' property of class ''<a href="matlab:doc types.core.IntervalSeries">IntervalSeries</a>'' because it is read-only.')
error('NWB:Type:ReadOnlyProperty', 'Unable to set the ''data_resolution'' property of class ''<a href="matlab:doc types.core.IntervalSeries">IntervalSeries</a>'' because it is read-only.')
end
end
function val = validate_data_unit(obj, val)
if isequal(val, 'n/a')
val = 'n/a';
else
error('Unable to set the ''data_unit'' property of class ''<a href="matlab:doc types.core.IntervalSeries">IntervalSeries</a>'' because it is read-only.')
error('NWB:Type:ReadOnlyProperty', 'Unable to set the ''data_unit'' property of class ''<a href="matlab:doc types.core.IntervalSeries">IntervalSeries</a>'' because it is read-only.')
end
end
%% EXPORT
Expand Down
2 changes: 1 addition & 1 deletion +types/+core/IntracellularElectrodesTable.m
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
if isequal(val, 'Table for storing intracellular electrode related metadata.')
val = 'Table for storing intracellular electrode related metadata.';
else
error('Unable to set the ''description'' property of class ''<a href="matlab:doc types.core.IntracellularElectrodesTable">IntracellularElectrodesTable</a>'' because it is read-only.')
error('NWB:Type:ReadOnlyProperty', 'Unable to set the ''description'' property of class ''<a href="matlab:doc types.core.IntracellularElectrodesTable">IntracellularElectrodesTable</a>'' because it is read-only.')
end
end
function val = validate_electrode(obj, val)
Expand Down
2 changes: 1 addition & 1 deletion +types/+core/IntracellularRecordingsTable.m
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@
if isequal(val, 'A table to group together a stimulus and response from a single electrode and a single simultaneous recording and for storing metadata about the intracellular recording.')
val = 'A table to group together a stimulus and response from a single electrode and a single simultaneous recording and for storing metadata about the intracellular recording.';
else
error('Unable to set the ''description'' property of class ''<a href="matlab:doc types.core.IntracellularRecordingsTable">IntracellularRecordingsTable</a>'' because it is read-only.')
error('NWB:Type:ReadOnlyProperty', 'Unable to set the ''description'' property of class ''<a href="matlab:doc types.core.IntracellularRecordingsTable">IntracellularRecordingsTable</a>'' because it is read-only.')
end
end
function val = validate_electrodes(obj, val)
Expand Down
2 changes: 1 addition & 1 deletion +types/+core/IntracellularResponsesTable.m
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
if isequal(val, 'Table for storing intracellular response related metadata.')
val = 'Table for storing intracellular response related metadata.';
else
error('Unable to set the ''description'' property of class ''<a href="matlab:doc types.core.IntracellularResponsesTable">IntracellularResponsesTable</a>'' because it is read-only.')
error('NWB:Type:ReadOnlyProperty', 'Unable to set the ''description'' property of class ''<a href="matlab:doc types.core.IntracellularResponsesTable">IntracellularResponsesTable</a>'' because it is read-only.')
end
end
function val = validate_response(obj, val)
Expand Down
Loading

0 comments on commit d970ef1

Please sign in to comment.