Skip to content

Commit 5396243

Browse files
authored
Fix inherited readonly props (#560)
* Define validator method for readonly props Some readonly props are inherited from superclasses where the same prop is settable. This will override the validator method for such a property to throw an error if someone tries to set a readonly property * remove debug try/catch * Fix bug with datetime conversion * Update linkTest.m Fix test that broke because of current PR * Minor fixes Only add validator for inherited readonly props Also support boolean read only property values
1 parent 9d77234 commit 5396243

File tree

4 files changed

+51
-12
lines changed

4 files changed

+51
-12
lines changed

+file/fillClass.m

+1-1
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@
122122
classprops,...
123123
namespace);
124124
setterFcns = file.fillSetters(setdiff(nonInherited, union(readonly, hiddenAndReadonly)));
125-
validatorFcns = file.fillValidators(allProperties, classprops, namespace);
125+
validatorFcns = file.fillValidators(allProperties, classprops, namespace, namespace.getFullClassName(name), inherited);
126126
exporterFcns = file.fillExport(nonInherited, class, depnm);
127127
methodBody = strjoin({constructorBody...
128128
'%% SETTERS' setterFcns...

+file/fillValidators.m

+47-8
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,27 @@
1-
function validationStr = fillValidators(propnames, props, namespacereg)
1+
function validationStr = fillValidators(propnames, props, namespacereg, className, inherited)
22
validationStr = '';
33
for i=1:length(propnames)
44
nm = propnames{i};
55
prop = props(nm);
66

7-
% if readonly and value exists then ignore
7+
88
if isa(prop, 'file.Attribute') && prop.readonly && ~isempty(prop.value)
9-
continue;
10-
end
11-
if startsWith(class(prop), 'file.')
12-
validationBody = fillUnitValidation(nm, prop, namespacereg);
13-
else % primitive type
14-
validationBody = fillDtypeValidation(nm, prop);
9+
% Need to add a validator for inherited and readonly properties. In
10+
% the superclass these properties might not be read only and due to
11+
% inheritance its not possible to change property attributes
12+
if any(strcmp(nm, inherited))
13+
validationBody = fillReadOnlyValidator(nm, prop.value, className);
14+
else
15+
continue
16+
end
17+
else
18+
if startsWith(class(prop), 'file.')
19+
validationBody = fillUnitValidation(nm, prop, namespacereg);
20+
else % primitive type
21+
validationBody = fillDtypeValidation(nm, prop);
22+
end
1523
end
24+
1625
headerStr = ['function val = validate_' nm '(obj, val)'];
1726
if isempty(validationBody)
1827
funcstionStr = [headerStr newline 'end'];
@@ -279,4 +288,34 @@
279288
fdvstr = [fdvstr ...
280289
'val = types.util.checkDtype(''' name ''', ''' ts ''', val);'];
281290
end
291+
end
292+
293+
function fdvstr = fillReadOnlyValidator(name, value, className)
294+
295+
classNameSplit = strsplit(className, '.');
296+
shortName = classNameSplit{end};
297+
298+
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);
299+
300+
if ischar(value)
301+
condition = strjoin({ ...
302+
sprintf('if isequal(val, ''%s'')', value), ...
303+
sprintf(' val = ''%s'';', value ), ...
304+
'else' }, newline);
305+
elseif isnumeric(value) || islogical(value)
306+
condition = strjoin({ ...
307+
sprintf('if isequal(val, %d)', value), ...
308+
sprintf(' val = %d;', value ), ...
309+
'else' }, newline);
310+
else
311+
% Note: According to the documentation for Attribute specification keys
312+
% (https://schema-language.readthedocs.io/en/latest/description.html#sec-attributes-spec),
313+
% the above cases should be sufficient.
314+
error('Unhandled case')
315+
end
316+
317+
fdvstr = strjoin({...
318+
condition, ...
319+
sprintf(' %s', errorStr), ...
320+
'end' }, newline );
282321
end

+io/timestamp2datetime.m

+2-2
Original file line numberDiff line numberDiff line change
@@ -48,9 +48,9 @@
4848
, 'Day', ymdStamp(7:8) ...
4949
);
5050
end
51-
Datetime.Year = str2double(YmdToken.Year);
52-
Datetime.Month = str2double(YmdToken.Month);
5351
Datetime.Day = str2double(YmdToken.Day);
52+
Datetime.Month = str2double(YmdToken.Month);
53+
Datetime.Year = str2double(YmdToken.Year);
5454
assert(~isnat(Datetime), errorId, sprintf(errorTemplate, 'non-numeric YMD values detected'));
5555

5656
%% HMiS TZ

+tests/+unit/linkTest.m

+1-1
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ function testExternalResolution(testCase)
6767
'table', types.untyped.ObjectView('/acquisition/es1'),...
6868
'description', 'dtr stub that points to electrical series illegally'); % do not do this at home.
6969
expected = types.core.ElectricalSeries('data', expectedData,...
70-
'data_unit', 'unit',...
70+
'data_unit', 'volts', ...
7171
'electrodes', stubDtr);
7272
nwb.acquisition.set('es1', expected);
7373
nwb.export('test1.nwb');

0 commit comments

Comments
 (0)