Skip to content

Commit

Permalink
Merge pull request #19 from EdinburghGenomics/queued_artifacts
Browse files Browse the repository at this point in the history
Queued artifacts
  • Loading branch information
Timothee Cezard committed Jan 10, 2018
2 parents 82c1b93 + bed8bb9 commit 834cb0a
Show file tree
Hide file tree
Showing 3 changed files with 119 additions and 6 deletions.
42 changes: 42 additions & 0 deletions pyclarity_lims/descriptors.py
Original file line number Diff line number Diff line change
Expand Up @@ -721,6 +721,48 @@ def _parse_element(self, element, **kwargs):
list.append(self, (element.attrib.get('id'), element.attrib.get('uri')))


class QueuedArtifactList(TagXmlList):
"""This is a list of Artifact associated with the time they spent in the queue and their location on a plate.
The list contains tuples organise as follow:
(A, B, (C, D)) where
A is an artifact
B is a datetime object,
C is a container
D is a string specifying the location such as "1:1"
"""

def __init__(self, instance, *args, **kwargs):
TagXmlList.__init__(self, instance, tag='artifact', nesting=['artifacts'], *args, **kwargs)

def _parse_element(self, element, lims, **kwargs):
from pyclarity_lims.entities import Artifact, Container
input_art = Artifact(lims, uri=element.attrib['uri'])
loc = element.find('location')
location = (None, None)
if loc:
location = (
Container(lims, uri=loc.find('container').attrib['uri']),
loc.find('value').text
)
qt = element.find('queue-time')
queue_date = None
if qt is not None:
h, s, t = qt.text.rpartition(':')
qt = h + t
microsec = ''
if '.' in qt:
microsec = '.%f'
date_format = '%Y-%m-%dT%H:%M:%S' + microsec
try:
queue_date = datetime.datetime.strptime(qt, date_format + '%z')
except ValueError:
# support for python 2.7 ignore time zone
# use python 3 for timezone support
qt = qt.split('+')[0]
queue_date = datetime.datetime.strptime(qt, date_format)
list.append(self, (input_art, queue_date, location))


# Descriptors: This section contains the object that can be used in entities
class BaseDescriptor(XmlElement):
"""Abstract base descriptor for an instance attribute."""
Expand Down
23 changes: 19 additions & 4 deletions pyclarity_lims/entities.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
InputOutputMapList, LocationDescriptor, IntegerAttributeDescriptor, \
StringAttributeDescriptor, EntityListDescriptor, StringListDescriptor, PlacementDictionaryDescriptor, \
ReagentLabelList, AttributeListDescriptor, StringDictionaryDescriptor, OutputPlacementListDescriptor, \
XmlActionList, MutableDescriptor, XmlPooledInputDict
XmlActionList, MutableDescriptor, XmlPooledInputDict, QueuedArtifactList

try:
from urllib.parse import urlsplit, urlparse, parse_qs, urlunparse
Expand Down Expand Up @@ -1041,13 +1041,28 @@ def __init__(self, lims, uri=None, id=None):
self.sequence = child.attrib.get("value")

class Queue(Entity):
"""Queue of a given step"""
"""Queue of a given workflow stage"""
_URI = "queues"
_TAG= "queue"
_PREFIX = "que"

artifacts = EntityListDescriptor("artifact", Artifact, nesting=["artifacts"])
"""List of :py:class:`artifacts <pyclarity_lims.entities.Artifact>` associated with this workflow."""
queued_artifacts = MutableDescriptor(QueuedArtifactList)
"""
List of :py:class:`artifacts <pyclarity_lims.entities.Artifact>` associated with this workflow stage.
alongside the time the've been added to that queue and the container they're in.
The list contains tuples organise as follow:
(A, B, (C, D)) where
A is an :py:class:`artifacts <pyclarity_lims.entities.Artifact>`
B is a :py:class:`datetime <datetime.datetime>` object,
C is a :py:class:`container <pyclarity_lims.entities.Container>`
D is a string specifying the location such as "1:1"
"""

@property
def artifacts(self):
"""List of :py:class:`artifacts <pyclarity_lims.entities.Artifact>` associated with this workflow stage."""
return [i[0] for i in self.queued_artifacts]


Sample.artifact = EntityDescriptor('artifact', Artifact)
StepActions.step = EntityDescriptor('step', Step)
Expand Down
60 changes: 58 additions & 2 deletions tests/test_descriptors.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,15 @@
from unittest import TestCase
from xml.etree import ElementTree

import datetime
import pytest

from pyclarity_lims.constants import nsmap
from pyclarity_lims.descriptors import StringDescriptor, StringAttributeDescriptor, StringListDescriptor, \
StringDictionaryDescriptor, IntegerDescriptor, BooleanDescriptor, UdfDictionary, EntityDescriptor, \
InputOutputMapList, EntityListDescriptor, PlacementDictionary, EntityList, SubTagDictionary, ExternalidList,\
XmlElementAttributeDict, XmlAttributeList, XmlReagentLabelList, XmlPooledInputDict, XmlAction
from pyclarity_lims.entities import Artifact, ProtocolStep
XmlElementAttributeDict, XmlAttributeList, XmlReagentLabelList, XmlPooledInputDict, XmlAction, QueuedArtifactList
from pyclarity_lims.entities import Artifact, ProtocolStep, Container
from pyclarity_lims.lims import Lims
from tests import elements_equal

Expand Down Expand Up @@ -728,3 +729,58 @@ def test_set(self):

with pytest.raises(KeyError):
action['whatever'] = 'youwant'


class TestQueuedArtifactList(TestCase):
def setUp(self):
et = ElementTree.fromstring('''<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<test-entry>
<artifacts>
<artifact uri="{url}/artifacts/a1">
<queue-time>2011-12-25T01:10:10.050+00:00</queue-time>
<location>
<container uri="{url}/containers/c1"/>
<value>A:1</value>
</location>
</artifact>
<artifact uri="{url}/artifacts/a2">
<queue-time>2011-12-25T01:10:10.200+01:00</queue-time>
<location>
<container uri="{url}/containers/c1"/>
<value>A:2</value>
</location>
</artifact>
</artifacts>
</test-entry>'''.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)

def get_queue_art(self, art_id, pos, microsec, time_delta):
if version_info[0] == 2:
return (
Artifact(self.lims, id=art_id),
datetime.datetime(2011, 12, 25, 1, 10, 10, microsec),
(Container(self.lims, id='c1'), pos)
)
else:
return (
Artifact(self.lims, id=art_id),
datetime.datetime(2011, 12, 25, 1, 10, 10, microsec, tzinfo=datetime.timezone(time_delta)),
(Container(self.lims, id='c1'), pos)
)

def test_parse(self):
queued_artifacts = QueuedArtifactList(self.instance1)
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

def test_set(self):
queued_artifacts = QueuedArtifactList(self.instance1)
qart = self.get_queue_art('a1', 'A:3', 50000, datetime.timedelta(0, 0))
with pytest.raises(NotImplementedError):
queued_artifacts.append(qart)


0 comments on commit 834cb0a

Please sign in to comment.