def create_sample_params( params: Dict[str, Any]) -> Tuple[Sample, Optional[UUID], Optional[int]]: ''' Process the input from the create_sample API call and translate it into standard types. :param params: The unmarshalled JSON recieved from the API as part of the create_sample call. :returns: A tuple of the sample to save, the UUID of the sample for which a new version should be created or None if an entirely new sample should be created, and the previous version of the sample expected when saving a new version. :raises IllegalParameterError: if any of the arguments are illegal. ''' _check_params(params) if type(params.get('sample')) != dict: raise _IllegalParameterError( 'params must contain sample key that maps to a structure') s = params['sample'] if type(s.get('node_tree')) != list: raise _IllegalParameterError( 'sample node tree must be present and a list') if s.get('name') is not None and type(s.get('name')) != str: raise _IllegalParameterError('sample name must be omitted or a string') nodes = _check_nodes(s) id_ = get_id_from_object(s, ID, name='sample.id') pv = params.get('prior_version') if pv is not None and type(pv) != int: raise _IllegalParameterError( 'prior_version must be an integer if supplied') s = Sample(nodes, s.get('name')) return (s, id_, pv)
def validate_samples_params(params: Dict[str, Any]) -> List[Sample]: ''' Process the input from the validate_samples API call and translate it into standard types. :param params: The unmarshalled JSON recieved from the API as part of the create_sample call. :returns: A tuple of the sample to save, the UUID of the sample for which a new version should be created or None if an entirely new sample should be created, and the previous version of the sample expected when saving a new version. :raises IllegalParameterError: if any of the arguments are illegal. ''' _check_params(params) if type(params.get('samples')) != list or len(params.get('samples', [])) == 0: raise _IllegalParameterError('params must contain list of `samples`') samples = [] for s in params['samples']: if type(s.get('node_tree')) != list: raise _IllegalParameterError( 'sample node tree must be present and a list') if type(s.get('name')) != str or len(s.get('name')) <= 0: raise _IllegalParameterError( 'sample name must be included as non-empty string') nodes = _check_nodes(s) s = Sample(nodes, s.get('name')) samples.append(s) return samples
def test_sample_build(): sn = SampleNode('foo') sn2 = SampleNode('bat') sn3 = SampleNode('bar', type_=SubSampleType.TECHNICAL_REPLICATE, parent='foo') sn4 = SampleNode('baz', type_=SubSampleType.SUB_SAMPLE, parent='foo') sndup = SampleNode('foo') s = Sample([sn]) assert s.nodes == (sndup,) assert s.name is None s = Sample([sn, sn2, sn4, sn3], ' \t foo ') assert s.nodes == (sndup, sn2, sn4, sn3) assert s.name == 'foo' s = Sample([sn], 'a' * 256) assert s.nodes == (sndup,) assert s.name == 'a' * 256 id_ = uuid.UUID('1234567890abcdef1234567890abcdef') s = SavedSample(id_, UserID('user'), [sn], dt(6)) assert s.id == uuid.UUID('1234567890abcdef1234567890abcdef') assert s.user == UserID('user') assert s.nodes == (sndup,) assert s.savetime == dt(6) assert s.name is None assert s.version is None s = SavedSample(id_, UserID('user2'), [sn], dt(6), 'foo') assert s.id == uuid.UUID('1234567890abcdef1234567890abcdef') assert s.user == UserID('user2') assert s.nodes == (sndup,) assert s.savetime == dt(6) assert s.name == 'foo' assert s.version is None s = SavedSample(id_, UserID('user'), [sn], dt(6), 'foo', 1) assert s.id == uuid.UUID('1234567890abcdef1234567890abcdef') assert s.user == UserID('user') assert s.nodes == (sndup,) assert s.savetime == dt(6) assert s.name == 'foo' assert s.version == 1 s = SavedSample(id_, UserID('user'), [sn], dt(6), 'foo', 8) assert s.id == uuid.UUID('1234567890abcdef1234567890abcdef') assert s.user == UserID('user') assert s.nodes == (sndup,) assert s.savetime == dt(6) assert s.name == 'foo' assert s.version == 8 s = SavedSample(id_, UserID('user'), [sn], dt(6), version=8) assert s.id == uuid.UUID('1234567890abcdef1234567890abcdef') assert s.user == UserID('user') assert s.nodes == (sndup,) assert s.savetime == dt(6) assert s.name is None assert s.version == 8
def create_sample_params( params: Dict[str, Any]) -> Tuple[Sample, Optional[UUID], Optional[int]]: ''' Process the input from the create_sample API call and translate it into standard types. :param params: The unmarshalled JSON recieved from the API as part of the create_sample call. :returns: A tuple of the sample to save, the UUID of the sample for which a new version should be created or None if an entirely new sample should be created, and the previous version of the sample expected when saving a new version. :raises IllegalParameterError: if any of the arguments are illegal. ''' _check_params(params) if type(params.get('sample')) != dict: raise _IllegalParameterError( 'params must contain sample key that maps to a structure') s = params['sample'] if type(s.get('node_tree')) != list: raise _IllegalParameterError( 'sample node tree must be present and a list') if s.get('name') is not None and type(s.get('name')) != str: raise _IllegalParameterError('sample name must be omitted or a string') nodes = [] for i, n in enumerate(s['node_tree']): if type(n) != dict: raise _IllegalParameterError( f'Node at index {i} is not a structure') if type(n.get('id')) != str: raise _IllegalParameterError( f'Node at index {i} must have an id key that maps to a string') try: type_ = _SubSampleType(n.get('type')) except ValueError: raise _IllegalParameterError( f'Node at index {i} has an invalid sample type: {n.get("type")}' ) if n.get('parent') and type(n.get('parent')) != str: raise _IllegalParameterError( f'Node at index {i} has a parent entry that is not a string') mc = _check_meta(n.get('meta_controlled'), i, 'controlled metadata') mu = _check_meta(n.get('meta_user'), i, 'user metadata') try: nodes.append( _SampleNode(n.get('id'), type_, n.get('parent'), mc, mu)) # already checked for the missing param error above, for id except _IllegalParameterError as e: raise _IllegalParameterError(f'Error for node at index {i}: ' + _cast(str, e.message)) from e id_ = get_id_from_object(s) pv = params.get('prior_version') if pv is not None and type(pv) != int: raise _IllegalParameterError( 'prior_version must be an integer if supplied') s = Sample(nodes, s.get('name')) return (s, id_, pv)
def test_sample_eq(): sn = SampleNode('foo') sn2 = SampleNode('bar') assert Sample([sn], 'yay') == Sample([sn], 'yay') assert Sample([sn], 'yay') != Sample([sn2], 'yay') assert Sample([sn], 'yay') != Sample([sn], 'yooo') id1 = uuid.UUID('1234567890abcdef1234567890abcdef') id2 = uuid.UUID('1234567890abcdef1234567890abcdea') dt1 = dt(5) dt2 = dt(8) u = UserID('u') u2 = UserID('u2') assert SavedSample(id1, u, [sn], dt1) == SavedSample(id1, u, [sn], dt(5)) assert SavedSample(id1, u, [sn], dt1) != SavedSample(id2, u, [sn], dt1) assert SavedSample(id1, u, [sn], dt1) != SavedSample(id1, u2, [sn], dt1) assert SavedSample(id1, u, [sn], dt1) != SavedSample(id1, u, [sn2], dt1) assert SavedSample(id1, u, [sn], dt1) != SavedSample(id1, u, [sn], dt2) assert SavedSample(id1, u, [sn], dt1, 'yay') == SavedSample(id1, u, [sn], dt1, 'yay') assert SavedSample(id1, u, [sn], dt1, 'yay') != SavedSample(id1, u, [sn], dt1, 'yooo') assert SavedSample(id1, u, [sn], dt2, 'yay', 6) == SavedSample(id1, u, [sn], dt2, 'yay', 6) assert SavedSample(id1, u, [sn], dt1, 'yay', 6) != SavedSample(id1, u, [sn], dt1, 'yay', 7) assert SavedSample(id1, u, [sn], dt1, 'yay') != Sample([sn], 'yay') assert Sample([sn], 'yay') != SavedSample(id1, u, [sn], dt1, 'yay')
def test_create_sample_params_minimal(): params = {'sample': {'version': 7, # should be ignored 'save_date': 9, # should be ignored 'node_tree': [{'id': 'foo', 'type': 'BioReplicate'}] }} expected = Sample([SampleNode('foo')]) assert create_sample_params(params) == (expected, None, None)
def _sample_build_fail(nodes, name, expected): with raises(Exception) as got: Sample(nodes, name) assert_exception_correct(got.value, expected) id_ = uuid.UUID('1234567890abcdef1234567890abcdef') with raises(Exception) as got: SavedSample(id_, UserID('u'), nodes, dt(8), name) assert_exception_correct(got.value, expected)
def test_create_sample_params_maximal(): params = {'sample': {'version': 7, # should be ignored 'save_date': 9, # should be ignored 'id': '706fe9e1-70ef-4feb-bbd9-32295104a119', 'name': 'myname', 'node_tree': [{'id': 'foo', 'type': 'BioReplicate'}, {'id': 'bar', 'parent': 'foo', 'type': 'TechReplicate', 'meta_controlled': {'concentration/NO2': {'species': 'NO2', 'units': 'ppm', 'value': 78.91, 'protocol_id': 782, 'some_boolean_or_other': True } }, 'meta_user': {'location_name': {'name': 'my_buttocks'}} } ] }, 'prior_version': 1} assert create_sample_params(params) == ( Sample([ SampleNode('foo'), SampleNode( 'bar', SubSampleType.TECHNICAL_REPLICATE, 'foo', {'concentration/NO2': {'species': 'NO2', 'units': 'ppm', 'value': 78.91, 'protocol_id': 782, 'some_boolean_or_other': True } }, {'location_name': {'name': 'my_buttocks'}} ) ], 'myname' ), UUID('706fe9e1-70ef-4feb-bbd9-32295104a119'), 1)
def test_sample_build_fail_sample_count(): nodes = [SampleNode('s' + str(i)) for i in range(10000)] s = Sample(nodes) assert s.nodes == tuple(nodes) assert s.name is None id_ = uuid.UUID('1234567890abcdef1234567890abcdef') s = SavedSample(id_, UserID('u'), nodes, dt(8)) assert s.id == uuid.UUID('1234567890abcdef1234567890abcdef') assert s.user == UserID('u') assert s.nodes == tuple(nodes) assert s.savetime == dt(8) assert s.name is None assert s.version is None nodes.append(SampleNode('s10000')) _sample_build_fail(nodes, None, IllegalParameterError( 'At most 10000 nodes are allowed per sample'))
def test_sample_hash(): # hashes will change from instance to instance of the python interpreter, and therefore # tests can't be written that directly test the hash value. See # https://docs.python.org/3/reference/datamodel.html#object.__hash__ sn = SampleNode('foo') sn2 = SampleNode('bar') id1 = uuid.UUID('1234567890abcdef1234567890abcdef') id2 = uuid.UUID('1234567890abcdef1234567890abcdea') dt1 = dt(5) dt2 = dt(8) u = UserID('u') u2 = UserID('u2') assert hash(Sample([sn], 'yay')) == hash(Sample([sn], 'yay')) assert hash(Sample([sn], 'foo')) == hash(Sample([sn], 'foo')) assert hash(Sample([sn], 'yay')) != hash(Sample([sn2], 'yay')) assert hash(Sample([sn], 'yay')) != hash(Sample([sn], 'yo')) assert hash(SavedSample(id1, u, [sn], dt1, 'yay')) == hash(SavedSample( id1, u, [sn], dt(5), 'yay')) assert hash(SavedSample(id2, u, [sn], dt1, 'foo')) == hash(SavedSample( id2, u, [sn], dt1, 'foo')) assert hash(SavedSample(id1, u, [sn], dt1, 'foo')) != hash(SavedSample( id2, u, [sn], dt1, 'foo')) assert hash(SavedSample(id1, u, [sn], dt1, 'foo')) != hash(SavedSample( id1, u2, [sn], dt1, 'foo')) assert hash(SavedSample(id2, u, [sn], dt1, 'foo')) != hash(SavedSample( id2, u, [sn2], dt1, 'foo')) assert hash(SavedSample(id2, u, [sn], dt1, 'foo')) != hash(SavedSample( id2, u, [sn], dt2, 'foo')) assert hash(SavedSample(id2, u, [sn], dt1, 'foo')) != hash(SavedSample( id2, u, [sn], dt1, 'bar')) assert hash(SavedSample(id1, u, [sn], dt1, 'foo', 6)) == hash(SavedSample( id1, u, [sn], dt1, 'foo', 6)) assert hash(SavedSample(id1, u, [sn], dt1, 'foo', 6)) != hash(SavedSample( id1, u, [sn], dt1, 'foo', 7))
def _sample_with_id_build_fail(id_, user, nodes, savetime, name, version, expected): with raises(Exception) as got: SavedSample(id_, user, nodes, savetime, name, version) Sample(nodes, name) assert_exception_correct(got.value, expected)