예제 #1
0
 def test_can_read_xml(self):
     """Can parse an xml file directly form the context"""
     context = ExtensionContext.create("24-7880")
     xml = context.local_shared_file(
         "Result XML File (required)", is_xml=True)
     self.assertFalse(0, len(xml.FileInformation.Assay))
     context.cleanup()
예제 #2
0
 def test_can_read_xml(self):
     """Can parse an xml file directly form the context"""
     context = ExtensionContext.create("24-7880")
     xml = context.local_shared_file("Result XML File (required)",
                                     is_xml=True)
     self.assertFalse(0, len(xml.FileInformation.Assay))
     context.cleanup()
예제 #3
0
 def test_can_download_shared_file(self):
     """Can download a single shared file, view it locally and then clean it up"""
     context = ExtensionContext.create("24-3144")
     f = context.local_shared_file("Sample List")
     self.assertNotEqual(0, len(f.name))
     self.assertTrue(os.path.exists(f.name))
     context.cleanup()
     self.assertFalse(os.path.exists(f.name))
예제 #4
0
def mock_context(**kwargs):
    """Creates a mock with the service provided as keyword arguments, filling the rest with MagicMock"""
    # TODO: Needs to be updated when the signature is updated. Fix that (or use a better approach)
    for arg in ["session", "artifact_service", "file_service", "current_user", "step_logger_service",
                "step_repo", "clarity_service", "dilution_service", "process_service",
                "upload_file_service", "validation_service"]:
        kwargs.setdefault(arg, MagicMock())
    return ExtensionContext(**kwargs)
예제 #5
0
 def test_can_fetch_all_output_files(self):
     """Can fetch all output files in a step"""
     context = ExtensionContext.create("24-3144")
     # This will return output result files per input, not those per all
     # inputs
     actual = set(f.id for f in context.output_result_files)
     expected = set(['92-5241', '92-5242'])
     self.assertEqual(expected, actual)
예제 #6
0
 def test_can_fetch_all_output_files(self):
     """Can fetch all output files in a step"""
     context = ExtensionContext.create("24-3144")
     # This will return output result files per input, not those per all
     # inputs
     actual = set(f.id for f in context.output_result_files)
     expected = set(['92-5241', '92-5242'])
     self.assertEqual(expected, actual)
예제 #7
0
 def test_can_download_shared_file(self):
     """Can download a single shared file, view it locally and then clean it up"""
     context = ExtensionContext.create("24-3144")
     f = context.local_shared_file("Sample List")
     self.assertNotEqual(0, len(f.name))
     self.assertTrue(os.path.exists(f.name))
     context.cleanup()
     self.assertFalse(os.path.exists(f.name))
    def run(self, flowcell_name):
        lims = Lims(
            BASEURI, USERNAME, PASSWORD
        )  #Need credentials on stackstorm server for genologics package.
        containers = lims.get_containers(name=flowcell_name)
        processes = list(self.get_processes(containers))
        newest_process_id = self.highest_id(processes)
        cwd = os.getcwd()
        #generate a fresh temp dir to mimic lims behaviour (avoid overwriting samplesheets)
        temp_wd = mkdtemp()
        os.chdir(temp_wd)
        context = ExtensionContext.create(newest_process_id)
        try:
            samplesheet_file = context.local_shared_file("Sample Sheet")
            # samplesheet file can be both single file and zip file with names like 92-102630_HH7LMCCXY_samplesheet.csv in archive.
            if zipfile.is_zipfile(samplesheet_file):
                #extract appropriate zip member
                zf = zipfile.ZipFile(samplesheet_file, 'r')
                zipped_files = zf.namelist()
                flowcell_pattern = re.compile('_' + flowcell_name +
                                              '_samplesheet')
                matching_files = []
                for filename in zipped_files:
                    if flowcell_pattern.search(filename):
                        matching_files.append(filename)
                if len(matching_files) > 1:
                    raise LookupError(
                        'More than one samplesheet matching flowcell name in zipfile!'
                    )
                elif len(matching_files) == 0:
                    raise LookupError('No matching samplesheet in zipfile')
                else:
                    samplesheet = zf.read(matching_files[0])

            else:
                samplesheet_file.seek(0)
                samplesheet = samplesheet_file.read()

        except IOError as err:
            self.logger.error(
                'IOError while attempting to read samplesheet: {}'.format(
                    err.message))
            raise err
        except LookupError as err:
            self.logger.error(
                'LookupError while attempting to read samplesheet in zip: {}'.
                format(err.message))
            raise err

        os.chdir(cwd)
        return (True, samplesheet)
예제 #9
0
    def test_can_set_any_udf(self):
        """
        Users can set UDFs that are either already defined on the Artifact or are defined in the process type for the
        output (the feature that makes them visible in the UI).

        In addition to this, users should be able to set any other UDF on the artifact, as you can do through the
        lab toolkit or directly through the UI.
        """
        context = ExtensionContext.create("24-1998")
        # NOTE: These do not have the udf "Amount (ng)" available
        for well in context.input_container.occupied:
            well.artifact.udf_map.force("FA Total conc. (ng/ul)", 21)
            context.update(well.artifact)
        context.commit()
예제 #10
0
    def test_can_fetch_containers_from_result_files(self):
        """
        A temporary test that validates that one can fetch containers

        Required setup:
          - The step has been set up so that there are output result files (not analytes)
            which containers need to be accessed. Fetching all analytes will not
            return output analytes in this case.
        """
        context = ExtensionContext.create("24-3144")

        wells = [x for x in context.output_container.list_wells(
            Container.RIGHT_FIRST)]
        self.assertIsNotNone(wells[0].artifact)
예제 #11
0
    def test_can_fetch_containers_from_result_files(self):
        """
        A temporary test that validates that one can fetch containers

        Required setup:
          - The step has been set up so that there are output result files (not analytes)
            which containers need to be accessed. Fetching all analytes will not
            return output analytes in this case.
        """
        context = ExtensionContext.create("24-3144")

        wells = [
            x
            for x in context.output_container.list_wells(Container.RIGHT_FIRST)
        ]
        self.assertIsNotNone(wells[0].artifact)
예제 #12
0
    def test_can_access_patterned_flow_cell_output(self):
        """
        Can access an eight lane patterned flow cell as the output container and access all of its artifacts.

        Condition: The step must have only one output container, which is a Patterned Flow Cell
        """
        item = config.get_by_name("has_one_output_of_type_patterned_flow_cell")
        context = ExtensionContext.create(item.pid)
        containers = context.artifact_service.all_output_containers()
        self.assertEqual(1, len(containers))
        container = containers[0]
        count = 0
        for item in container.enumerate_wells():
            count += 1
            self.assertIsNotNone(item.artifact.input)
            self.assertIsNotNone(item.artifact.input.parent_process)
        self.assertEqual(8, count)
예제 #13
0
    def test_can_access_patterned_flow_cell_output(self):
        """
        Can access an eight lane patterned flow cell as the output container and access all of its artifacts.

        Condition: The step must have only one output container, which is a Patterned Flow Cell
        """
        item = config.get_by_name("has_one_output_of_type_patterned_flow_cell")
        context = ExtensionContext.create(item.pid)
        containers = context.artifact_service.all_output_containers()
        self.assertEqual(1, len(containers))
        container = containers[0]
        count = 0
        for item in container.enumerate_wells():
            count += 1
            self.assertIsNotNone(item.artifact.input)
            self.assertIsNotNone(item.artifact.input.parent_process)
        self.assertEqual(8, count)
예제 #14
0
    def __init__(self):
        session = MagicMock()
        step_repo = MagicMock()
        step_repo.all_artifacts = self._all_artifacts
        user = User("Integration", "Tester", "*****@*****.**", "IT")
        step_repo.get_process = MagicMock(return_value=Process(None, "24-1234", user, None, "http://not-avail"))
        os_service = MagicMock()
        file_repository = MagicMock()
        clarity_service = MagicMock()
        process_type = ProcessType(None, None, name="Some process")
        step_repo.current_user = MagicMock(return_value=user)
        step_repo.get_process_type = MagicMock(return_value=process_type)
        self.context = ExtensionContext.create_mocked(session, step_repo, os_service, file_repository, clarity_service)
        # TODO: only mocking this one method of the validation_service for now (quick fix)
        self.context.validation_service.handle_single_validation = MagicMock()

        self._shared_files = list()
        self._analytes = list()
예제 #15
0
    def __init__(self):
        session = MagicMock()
        step_repo = MagicMock()
        step_repo.all_artifacts = self._all_artifacts
        user = User("Integration", "Tester", "*****@*****.**", "IT")
        step_repo.get_process = MagicMock(return_value=Process(None, "24-1234", user, None, "http://not-avail"))
        os_service = MagicMock()
        file_repository = MagicMock()
        clarity_service = MagicMock()
        process_type = ProcessType(None, None, name="Some process")
        step_repo.current_user = MagicMock(return_value=user)
        step_repo.get_process_type = MagicMock(return_value=process_type)
        self.context = ExtensionContext.create_mocked(session, step_repo, os_service, file_repository, clarity_service)
        # TODO: only mocking this one method of the validation_service for now (quick fix)
        self.context.validation_service.handle_single_validation = MagicMock()

        self._shared_files = list()
        self._analytes = list()
예제 #16
0
    def test_placed_samples(self):
        """
        Required setup:
          - Step 24-3643 (TODO: configurable) has placed samples on 96 well plates
          - Input:
            - Plate1: D5
            - Plate2: A5, B7, E12
          - Output:
            - Plate1: B5, D6
            - Plate2: A3, E9
        """
        context = ExtensionContext.create("24-3643")
        pairs = filter(lambda pair: isinstance(pair[0], Analyte) and
                       isinstance(pair[1], Analyte), context.step_repo.all_artifacts())
        # Of all the artifacts, we're only going to examine those that map from analytes
        # to analytes:

        self.assertNotEqual(0, len(pairs))
        self.assertTrue(all([input.sample.id == output.sample.id for input, output in pairs]),
                        "Input and output analytes are not correctly paired")

        def group_analytes(analytes):
            keyfunc = lambda analyte: analyte.container.id
            grouped = itertools.groupby(
                sorted(analytes, key=keyfunc), key=keyfunc)
            return {key: set(x.well.position.__repr__() for x in value) for key, value in grouped}

        inputs = [inp for inp, outp in pairs]
        actual_inputs = group_analytes(inputs)
        expected_inputs = {
            "27-629": set(["B:7", "E:12", "A:5"]),
            "27-628": set(["D:5"]),
        }
        self.assertEqual(expected_inputs, actual_inputs)

        # TODO: Uses non-constant container names
        outputs = [outp for inp, outp in pairs]
        actual_outputs = group_analytes(outputs)
        expected_outputs = {
            "27-630": set(["B:5", "D:6"]),
            "27-631": set(["A:3", "E:9"]),
        }

        self.assertEqual(expected_outputs, actual_outputs)
    def run(self, flowcell_name):
        lims = Lims(BASEURI, USERNAME, PASSWORD) #Need credentials on stackstorm server for genologics package.
        containers = lims.get_containers(name=flowcell_name)
        processes = list(self.get_processes(containers))
        newest_process_id = self.highest_id(processes)
        cwd = os.getcwd()
        #generate a fresh temp dir to mimic lims behaviour (avoid overwriting samplesheets)
        temp_wd = mkdtemp()
        os.chdir(temp_wd)
        context = ExtensionContext.create(newest_process_id)
        try:
            samplesheet_file = context.local_shared_file("Sample Sheet")
            # samplesheet file can be both single file and zip file with names like 92-102630_HH7LMCCXY_samplesheet.csv in archive.
            if zipfile.is_zipfile(samplesheet_file):
                #extract appropriate zip member
                zf = zipfile.ZipFile(samplesheet_file, 'r')
                zipped_files = zf.namelist()
                flowcell_pattern = re.compile('_' + flowcell_name + '_samplesheet')
                matching_files = []
                for filename in zipped_files:
                    if flowcell_pattern.search(filename):
                        matching_files.append(filename)
                if len(matching_files) > 1:
                    raise LookupError('More than one samplesheet matching flowcell name in zipfile!')
                elif len(matching_files) == 0:
                    raise LookupError('No matching samplesheet in zipfile')
                else:
                    samplesheet = zf.read(matching_files[0])

            else:
                samplesheet_file.seek(0)
                samplesheet = samplesheet_file.read()

        except IOError as err:
            self.logger.error('IOError while attempting to read samplesheet: {}'.format(err.message))
            raise err
        except LookupError as err:
            self.logger.error('LookupError while attempting to read samplesheet in zip: {}'.format(err.message))
            raise err

        os.chdir(cwd)
        return (True, samplesheet)
예제 #18
0
    def test_can_get_parent_input_artifacts(self):
        """
        The step describing a Patterned Flow Cell should have 8 lanes with pooled samples in them.

        The test ensures that if we enumerate those, we can get to the parent input artifacts and
        look at information hanging on them.
        """
        item = config.get_by_name("has_one_output_of_type_patterned_flow_cell")
        context = ExtensionContext.create(item.pid)
        all_samples = list()
        for output_container in context.artifact_service.all_output_containers():
            for lane in output_container.enumerate_wells():
                for sample in lane.artifact.samples:
                    all_samples.append(sample)
        unique_samples = list(utils.unique(
            all_samples, lambda sample: sample.id))
        self.assertTrue(len(unique_samples) >= 2)
        for sample in unique_samples:
            parent = utils.single(context.artifact_service.get_parent_input_artifact(sample))
            self.assertEqual(sample.name, parent.name)
예제 #19
0
def mock_context(artifact_service=None, step_repo=None):
    # NOTE: Will be replaced with a simpler to use mock_context function in
    # another commit
    session = MagicMock()
    file_service = MagicMock()
    current_user = MagicMock()
    step_logger_service = MagicMock()
    artifact_service = artifact_service or MagicMock()
    step_repo = step_repo or MagicMock()
    return ExtensionContext(session=session,
                            artifact_service=artifact_service,
                            file_service=file_service,
                            current_user=current_user,
                            step_logger_service=step_logger_service,
                            step_repo=step_repo,
                            clarity_service=MagicMock(),
                            dilution_service=MagicMock(),
                            process_service=MagicMock(),
                            upload_file_service=MagicMock(),
                            validation_service=MagicMock())
예제 #20
0
    def test_can_get_parent_input_artifacts(self):
        """
        The step describing a Patterned Flow Cell should have 8 lanes with pooled samples in them.

        The test ensures that if we enumerate those, we can get to the parent input artifacts and
        look at information hanging on them.
        """
        item = config.get_by_name("has_one_output_of_type_patterned_flow_cell")
        context = ExtensionContext.create(item.pid)
        all_samples = list()
        for output_container in context.artifact_service.all_output_containers(
        ):
            for lane in output_container.enumerate_wells():
                for sample in lane.artifact.samples:
                    all_samples.append(sample)
        unique_samples = list(
            utils.unique(all_samples, lambda sample: sample.id))
        self.assertTrue(len(unique_samples) >= 2)
        for sample in unique_samples:
            parent = context.artifact_service.get_parent_input_artifact(sample)
            self.assertEqual(sample.name, parent.name)
    def run(self, flowcell_name):
        lims = Lims(
            BASEURI, USERNAME, PASSWORD
        )  #Need credentials on stackstorm server for genologics package.
        containers = lims.get_containers(name=flowcell_name)
        processes = list(self.get_processes(containers))
        newest_process_id = self.highest_id(processes)
        context = ExtensionContext.create(newest_process_id)
        cwd = os.getcwd()
        try:
            #generate a fresh temp directory to mimic LIMS behaviour (avoid overwriting samplesheets)
            temp_wd = mkdtemp()
            os.chdir(temp_wd)
            samplesheet_file = context.local_shared_file("Sample Sheet")
            samplesheet = samplesheet_file.read()
            os.chdir(cwd)

        except IOError as err:
            self.logger.error(
                'IOError while attempting to read samplesheet: {}'.format(
                    err.message))
            raise err

        return (True, samplesheet)
예제 #22
0
 def test_can_fetch_single_output_file(self):
     context = ExtensionContext.create("24-3144")
     result = context.output_result_file_by_id("92-5242")
     self.assertIsNotNone(result)
     self.assertIsInstance(result, ResultFile)
예제 #23
0
 def test_can_fetch_single_output_file(self):
     context = ExtensionContext.create("24-3144")
     result = context.output_result_file_by_id("92-5242")
     self.assertIsNotNone(result)
     self.assertIsInstance(result, ResultFile)
예제 #24
0
 def test_can_fetch_shared_files(self):
     """Can fetch a set of shared files from a step"""
     context = ExtensionContext.create("24-3144")
     expected = set(["92-5245", "92-5246", "92-5243", "92-5244"])
     actual = set(f.id for f in context.shared_files)
     self.assertEqual(expected, actual)
예제 #25
0
 def test_can_fetch_shared_files(self):
     """Can fetch a set of shared files from a step"""
     context = ExtensionContext.create("24-3144")
     expected = set(["92-5245", "92-5246", "92-5243", "92-5244"])
     actual = set(f.id for f in context.shared_files)
     self.assertEqual(expected, actual)
예제 #26
0
 def fetch():
     context = ExtensionContext.create("24-7880")
     result_file = context.output_result_file_by_id("92-20742")
     return context, result_file