From 6734b24cdad8a6c098dc09c578f9d7f3e08a8249 Mon Sep 17 00:00:00 2001 From: tcezard Date: Fri, 27 Apr 2018 17:00:18 +0100 Subject: [PATCH 1/2] Support for Decimals in UDFDictionary Add tests to make sure we can create samples with UDFs Support Queue with multipages --- pyclarity_lims/descriptors.py | 24 ++++++++++++--- tests/test_descriptors.py | 56 +++++++++++++++++++++++++++++++++-- tests/test_entities.py | 5 +++- 3 files changed, 78 insertions(+), 7 deletions(-) diff --git a/pyclarity_lims/descriptors.py b/pyclarity_lims/descriptors.py index 453409a3..7703bc88 100644 --- a/pyclarity_lims/descriptors.py +++ b/pyclarity_lims/descriptors.py @@ -5,6 +5,7 @@ Per Kraulis, Science for Life Laboratory, Stockholm, Sweden. Copyright (C) 2012 Per Kraulis """ +from decimal import Decimal from pyclarity_lims.constants import nsmap @@ -36,8 +37,8 @@ def __init__(self, nesting): else: self.rootkeys = [] - def rootnode(self, instance): - _rootnode = instance.root + def rootnode_from_root(self, root): + _rootnode = root for rootkey in self.rootkeys: childnode = _rootnode.find(rootkey) if childnode is None: @@ -46,6 +47,9 @@ def rootnode(self, instance): _rootnode = childnode return _rootnode + def rootnode(self, instance): + self.rootnode_from_root(instance.root) + class XmlMutable(XmlElement): """Class that receive an instance so it can be mutated in place""" @@ -172,7 +176,7 @@ def _setitem(self, key, value): if not self._is_string(value): raise TypeError('Text UDF requires str or unicode value') elif vtype == 'numeric': - if not isinstance(value, (int, float)): + if not isinstance(value, (int, float, Decimal)): raise TypeError('Numeric UDF requires int or float value') value = str(value) elif vtype == 'boolean': @@ -200,7 +204,7 @@ def _setitem(self, key, value): elif isinstance(value, bool): vtype = 'Boolean' value = value and 'true' or 'false' - elif isinstance(value, (int, float)): + elif isinstance(value, (int, float, Decimal)): vtype = 'Numeric' value = str(value) elif isinstance(value, datetime.date): @@ -769,6 +773,16 @@ def _parse_element(self, element, lims, **kwargs): queue_date = datetime.datetime.strptime(qt, date_format) list.append(self, (input_art, queue_date, location)) + def _update_elems(self): + root = self.instance.root + self._elems = [] + while root: + self._elems += self.rootnode_from_root(root).findall(self.tag) + if root.find('next-page') is not None: + root = self.instance.lims.get(root.find('next-page').attrib.get('uri')) + else: + root = None + # Descriptors: This section contains the object that can be used in entities class BaseDescriptor(XmlElement): @@ -888,6 +902,8 @@ def __set__(self, instance, value): node = ElementTree.Element(self.tag) self.rootnode(instance).append(node) node.attrib['uri'] = value.uri + # if value._TAG in ['project', 'sample', 'artifact', 'container']: + # node.attrib['limsid'] = value.id class DimensionDescriptor(TagDescriptor): diff --git a/tests/test_descriptors.py b/tests/test_descriptors.py index bd8a42f4..5f248429 100644 --- a/tests/test_descriptors.py +++ b/tests/test_descriptors.py @@ -767,7 +767,7 @@ def test_set(self): class TestQueuedArtifactList(TestCase): def setUp(self): - et = ElementTree.fromstring(''' + queue_txt = ''' @@ -792,10 +792,52 @@ def setUp(self): - '''.format(url='http://testgenologics.com:4040/api/v2')) + ''' + + + self.et_page1 = ElementTree.fromstring(''' + + + + 2011-12-25T01:10:10.050+00:00 + + + A:1 + + + + + '''.format(url='http://testgenologics.com:4040/api/v2')) + self.et_page2 = ElementTree.fromstring(''' + + + + 2011-12-25T01:10:10.200+01:00 + + + A:2 + + + + + '''.format(url='http://testgenologics.com:4040/api/v2')) + self.et_page3 = ElementTree.fromstring(''' + + + + 2011-12-25T01:10:10.050-01:00 + + + A:3 + + + + '''.format(url='http://testgenologics.com:4040/api/v2')) + et = ElementTree.fromstring(queue_txt.format(url='http://testgenologics.com:4040/api/v2')) self.lims = Lims('http://testgenologics.com:4040', username='test', password='password') self.instance1 = Mock(root=et, lims=self.lims) + self.instance2 = Mock(root=self.et_page1, lims=self.lims) def get_queue_art(self, art_id, pos, microsec, time_delta): if version_info[0] == 2: @@ -826,4 +868,14 @@ def test_set(self): with pytest.raises(NotImplementedError): queued_artifacts.append(qart) + def test_parse_multipage(self): + self.lims.get = Mock(side_effect=[self.et_page2, self.et_page3]) + queued_artifacts = QueuedArtifactList(self.instance2) + qart = self.get_queue_art('a1', 'A:1', 50000, datetime.timedelta(0, 0)) + assert queued_artifacts[0] == qart + qart = self.get_queue_art('a2', 'A:2', 200000, datetime.timedelta(0, 3600)) + assert queued_artifacts[1] == qart + qart = self.get_queue_art('a3', 'A:3', 50000, datetime.timedelta(0, -3600)) + assert queued_artifacts[2] == qart + diff --git a/tests/test_entities.py b/tests/test_entities.py index c874d396..ecde88d2 100644 --- a/tests/test_entities.py +++ b/tests/test_entities.py @@ -423,14 +423,17 @@ def test_create_entity(self): container=Container(self.lims, uri='container'), position='1:1', name='s1', + udf={'test1': 'test1value'} ) data = ''' - + s1 1:1 + test1value ''' + print(patch_post.call_args_list[0][1]['data']) assert elements_equal(ElementTree.fromstring(patch_post.call_args_list[0][1]['data']), ElementTree.fromstring(data)) From ae0736b46a08004ddeb07b1107576500a3f3ba64 Mon Sep 17 00:00:00 2001 From: tcezard Date: Fri, 27 Apr 2018 17:02:29 +0100 Subject: [PATCH 2/2] add missing return --- pyclarity_lims/descriptors.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyclarity_lims/descriptors.py b/pyclarity_lims/descriptors.py index 7703bc88..2f6ee32b 100644 --- a/pyclarity_lims/descriptors.py +++ b/pyclarity_lims/descriptors.py @@ -48,7 +48,7 @@ def rootnode_from_root(self, root): return _rootnode def rootnode(self, instance): - self.rootnode_from_root(instance.root) + return self.rootnode_from_root(instance.root) class XmlMutable(XmlElement):