From 88fed0ffffc206c10bbddaa3f3fa7bb484210d0b Mon Sep 17 00:00:00 2001 From: Evan Bolyen Date: Wed, 29 Jun 2022 14:52:57 -0700 Subject: [PATCH] TST: added more tests --- lib/galaxy/datatypes/qiime2.py | 33 +++- lib/galaxy/datatypes/test/qiime2.qza | Bin 0 -> 5382 bytes lib/galaxy/datatypes/test/qiime2.qzv | Bin 0 -> 6686 bytes lib/galaxy/datatypes/test/qiime2.tsv | 5 + test/unit/data/datatypes/test_qiime2.py | 216 ++++++++++++++++++------ 5 files changed, 193 insertions(+), 61 deletions(-) create mode 100644 lib/galaxy/datatypes/test/qiime2.qza create mode 100644 lib/galaxy/datatypes/test/qiime2.qzv create mode 100644 lib/galaxy/datatypes/test/qiime2.tsv diff --git a/lib/galaxy/datatypes/qiime2.py b/lib/galaxy/datatypes/qiime2.py index 1002bb97401..7199847efa4 100644 --- a/lib/galaxy/datatypes/qiime2.py +++ b/lib/galaxy/datatypes/qiime2.py @@ -12,7 +12,8 @@ from galaxy.datatypes.tabular import Tabular from galaxy.datatypes.sniff import build_sniff_from_prefix -class _QIIME2Result(CompressedZipArchive): +class _QIIME2ResultBase(CompressedZipArchive): + """Base class for QIIME2Artifact and QIIME2Visualization""" MetadataElement(name="semantic_type", readonly=True) MetadataElement(name="semantic_type_simple", readonly=True, visible=False) MetadataElement(name="uuid", readonly=True) @@ -52,12 +53,13 @@ class _QIIME2Result(CompressedZipArchive): ('Type', dataset.metadata.semantic_type), ('UUID', dataset.metadata.uuid)] if not simple: - if dataset.metadata.format is not None: + if dataset.metadata.semantic_type != 'Visualization': peek.append(('Format', dataset.metadata.format)) peek.append(('Version', dataset.metadata.version)) return peek def _sniff(self, filename): + """Helper method for use in inherited datatypes""" try: if not zipfile.is_zipfile(filename): raise Exception() @@ -66,7 +68,7 @@ class _QIIME2Result(CompressedZipArchive): return False -class QIIME2Artifact(_QIIME2Result): +class QIIME2Artifact(_QIIME2ResultBase): file_ext = "qza" def sniff(self, filename): @@ -74,7 +76,7 @@ class QIIME2Artifact(_QIIME2Result): return metadata and metadata['semantic_type'] != 'Visualization' -class QIIME2Visualization(_QIIME2Result): +class QIIME2Visualization(_QIIME2ResultBase): file_ext = "qzv" def sniff(self, filename): @@ -86,7 +88,7 @@ class QIIME2Visualization(_QIIME2Result): class QIIME2Metadata(Tabular): """ QIIME 2 supports overriding the type of a column to Categorical when - a specific directive `#Q2:types` is present under the ID row. + a specific directive `#q2:types` is present under the ID row. Galaxy already understands column types quite well, however we sometimes want to override its inferred type. @@ -96,16 +98,16 @@ class QIIME2Metadata(Tabular): and interacts best with the current implementation of Tabular. """ file_ext = "qiime2.tabular" - _TYPES_DIRECTIVE = '#q2:types' is_subclass = False + _TYPES_DIRECTIVE = '#q2:types' + _search_lines = 2 def get_column_names(self, first_line=None): if first_line is None: return None return first_line.strip().split('\t') - def set_meta(self, dataset, **kwargs): """ Let Galaxy's Tabular format handle most of this. We will just jump @@ -116,7 +118,7 @@ class QIIME2Metadata(Tabular): if dataset.has_data(): with open(dataset.file_name) as dataset_fh: line = None - for line, _ in zip(dataset_fh, range(2)): + for line, _ in zip(dataset_fh, range(self._search_lines)): if line.startswith(self._TYPES_DIRECTIVE): break if line is None: @@ -144,14 +146,27 @@ class QIIME2Metadata(Tabular): dataset.metadata.column_types[idx] = 'str' def sniff_prefix(self, file_prefix): - for _, line in zip(range(4), file_prefix.line_iterator()): + for _, line in zip(range(self._search_lines), + file_prefix.line_iterator()): if line.startswith(self._TYPES_DIRECTIVE): return True return False +############################################################################## +# Helpers +############################################################################## + + def _strip_properties(expression): + # This is necessary because QIIME 2's semantic types include a limited + # form of intersection type, which means that `A & B` is a subtype of `A` + # as well as a subtype of `B`. This means it is not generally speaking + # possible or practical to enumerate all valid subtypes and then do an + # exact match using + # So instead filter out 90% of the invalid inputs and let QIIME 2 raise an + # error on the finer details such as these "properties". try: expression_tree = ast.parse(expression) reconstructer = _PredicateRemover() diff --git a/lib/galaxy/datatypes/test/qiime2.qza b/lib/galaxy/datatypes/test/qiime2.qza new file mode 100644 index 0000000000000000000000000000000000000000..797ec85769bb06f34a1abc1a6a8b62db11d1a557 GIT binary patch literal 5382 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 a|Ifd7vl_~nSU)haZ$73Q@krtytN#JIsnhZR literal 0 HcmV?d00001 diff --git a/lib/galaxy/datatypes/test/qiime2.qzv b/lib/galaxy/datatypes/test/qiime2.qzv new file mode 100644 index 0000000000000000000000000000000000000000..9bdcb9b83a242978a499a212de4194a26863ceca GIT binary patch literal 6686 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 DQcdl> literal 0 HcmV?d00001 diff --git a/lib/galaxy/datatypes/test/qiime2.tsv b/lib/galaxy/datatypes/test/qiime2.tsv new file mode 100644 index 00000000000..9062ada57a2 --- /dev/null +++ b/lib/galaxy/datatypes/test/qiime2.tsv @@ -0,0 +1,5 @@ +id col1 col2 col3 +#q2:types categorical categorical numeric +id1 a 1 1 +id2 b 2 2 +id3 c 3 3 diff --git a/test/unit/data/datatypes/test_qiime2.py b/test/unit/data/datatypes/test_qiime2.py index 902c78725f9..a14625bdf97 100644 --- a/test/unit/data/datatypes/test_qiime2.py +++ b/test/unit/data/datatypes/test_qiime2.py @@ -1,74 +1,186 @@ -import unittest +from galaxy.datatypes.qiime2 import (_strip_properties, QIIME2Artifact, + QIIME2Visualization, QIIME2Metadata) +from .util import MockDataset, get_input_files -from galaxy.datatypes.qiime2 import strip_properties +# Tests for QIIME2Artifact: + +def test_qza_sniff(): + qza = QIIME2Artifact() + with get_input_files('qiime2.qza') as input_files: + assert qza.sniff(input_files[0]) is True + + +def test_qza_set_meta(): + qza = QIIME2Artifact() + with get_input_files('qiime2.qza') as input_files: + dataset = MockDataset(1) + dataset.file_name = input_files[0] + + qza.set_meta(dataset) + + assert dataset.metadata.uuid == 'ba8c55e1-a2bc-47ea-beb2-b37b0b3b4032' + assert dataset.metadata.version == '2022.2.1' + assert dataset.metadata.format == 'SingleIntDirectoryFormat' + assert dataset.metadata.semantic_type == 'SingleInt1' + assert dataset.metadata.semantic_type_simple == 'SingleInt1' + + +def test_qza_set_peek(): + qza = QIIME2Artifact() + with get_input_files('qiime2.qza') as input_files: + dataset = MockDataset(1) + dataset.file_name = input_files[0] + + qza.set_meta(dataset) + qza.set_peek(dataset) + + assert dataset.peek == '''Type: SingleInt1 +UUID: ba8c55e1-a2bc-47ea-beb2-b37b0b3b4032 +Format: SingleIntDirectoryFormat +Version: 2022.2.1''' + + +# Tests for QIIME2Visualization: + +def test_qzv_sniff(): + qzv = QIIME2Visualization() + with get_input_files('qiime2.qzv') as input_files: + assert qzv.sniff(input_files[0]) is True + + +def test_qzv_set_meta(): + qzv = QIIME2Visualization() + with get_input_files('qiime2.qzv') as input_files: + dataset = MockDataset(1) + dataset.file_name = input_files[0] + + qzv.set_meta(dataset) + + assert dataset.metadata.uuid == '368ba1e7-3a7c-4dbc-98da-79f41aeece63' + assert dataset.metadata.version == '2022.2.1' + assert dataset.metadata.semantic_type == 'Visualization' + assert dataset.metadata.semantic_type_simple == 'Visualization' + + +def test_qzv_set_peek(): + qzv = QIIME2Visualization() + with get_input_files('qiime2.qzv') as input_files: + dataset = MockDataset(1) + dataset.file_name = input_files[0] + + qzv.set_meta(dataset) + qzv.set_peek(dataset) + + assert dataset.peek == '''Type: Visualization +UUID: 368ba1e7-3a7c-4dbc-98da-79f41aeece63 +Version: 2022.2.1''' + + +# Tets for QIIME2Metadata: + +def test_qiime2tabular_sniff(): + q2md = QIIME2Metadata() + with get_input_files('qiime2.tsv') as input_files: + assert q2md.sniff(input_files[0]) is True + + +def test_qiime2tabular_sniff_false(): + q2md = QIIME2Metadata() + with get_input_files('test_tab1.tabular') as input_files: + assert q2md.sniff(input_files[0]) is False + + +def test_qiime2tabular_set_meta(): + q2md = QIIME2Metadata() + with get_input_files('qiime2.tsv') as input_files: + dataset = MockDataset(1) + dataset.file_name = input_files[0] + + q2md.set_meta(dataset) + + # Show override of type inferrence on the second to last column: + assert dataset.metadata.column_types == ['str', 'str', 'str', 'int'] + + +# Tests for _strip_properties, which is rather complicated so worth testing +# on it's own. # Note: Not all the expressions here are completely valid types they are just # representative examples -class TestStripProperties(unittest.TestCase): - def test_simple(self): - simple_expression = 'Taxonomy % Properties("SILVIA")' - stripped_expression = 'Taxonomy' - reconstructed_expression = strip_properties(simple_expression) - self.assertEqual(reconstructed_expression, stripped_expression) +def test_strip_properties_simple(): + simple_expression = 'Taxonomy % Properties("SILVIA")' + stripped_expression = 'Taxonomy' - def test_single(self): - single_expression = 'FeatureData[Taxonomy % Properties("SILVIA")]' - stripped_expression = 'FeatureData[Taxonomy]' + reconstructed_expression = _strip_properties(simple_expression) - reconstructed_expression = strip_properties(single_expression) - self.assertEqual(reconstructed_expression, stripped_expression) + assert reconstructed_expression == stripped_expression - def test_double(self): - double_expression = ('FeatureData[Taxonomy % Properties("SILVIA"), ' - 'DistanceMatrix % Axes("ASV", "ASV")]') - stripped_expression = 'FeatureData[Taxonomy, DistanceMatrix]' - reconstructed_expression = strip_properties(double_expression) - self.assertEqual(reconstructed_expression, stripped_expression) +def test_strip_properties_single(): + single_expression = 'FeatureData[Taxonomy % Properties("SILVIA")]' + stripped_expression = 'FeatureData[Taxonomy]' - def test_nested(self): - nested_expression = ('Tuple[FeatureData[Taxonomy % ' - 'Properties("SILVIA")] % Axes("ASV", "ASV")]') - stripped_expression = 'Tuple[FeatureData[Taxonomy]]' + reconstructed_expression = _strip_properties(single_expression) - reconstructed_expression = strip_properties(nested_expression) - self.assertEqual(reconstructed_expression, stripped_expression) + assert reconstructed_expression == stripped_expression - def test_complex(self): - complex_expression = \ - ('Tuple[FeatureData[Taxonomy % Properties("SILVA")] % Axis("ASV")' - ', DistanceMatrix % Axes("ASV", "ASV")] % Unique') - stripped_expression = 'Tuple[FeatureData[Taxonomy], DistanceMatrix]' - reconstructed_expression = strip_properties(complex_expression) - self.assertEqual(reconstructed_expression, stripped_expression) +def test_strip_properties_double(): + double_expression = ('FeatureData[Taxonomy % Properties("SILVIA"), ' + 'DistanceMatrix % Axes("ASV", "ASV")]') + stripped_expression = 'FeatureData[Taxonomy, DistanceMatrix]' - def test_keep_different_binop(self): - expression_with_different_binop = \ - ('FeatureData[Taxonomy % Properties("SILVIA"), ' - 'Taxonomy & Properties]') - stripped_expression = \ - 'FeatureData[Taxonomy, Taxonomy & Properties]' + reconstructed_expression = _strip_properties(double_expression) - reconstructed_expression = \ - strip_properties(expression_with_different_binop) - self.assertEqual(reconstructed_expression, stripped_expression) + assert reconstructed_expression == stripped_expression - def test_multiple_strings(self): - simple_expression = 'Taxonomy % Properties("SILVIA")' - stripped_simple_expression = 'Taxonomy' - reconstructed_simple_expression = strip_properties(simple_expression) +def test_strip_properties_nested(): + nested_expression = ('Tuple[FeatureData[Taxonomy % ' + 'Properties("SILVIA")] % Axes("ASV", "ASV")]') + stripped_expression = 'Tuple[FeatureData[Taxonomy]]' - single_expression = 'FeatureData[Taxonomy % Properties("SILVIA")]' - stripped_single_expression = 'FeatureData[Taxonomy]' + reconstructed_expression = _strip_properties(nested_expression) - reconstructed_single_expression = strip_properties(single_expression) + assert reconstructed_expression == stripped_expression - self.assertEqual(reconstructed_simple_expression, - stripped_simple_expression) - self.assertEqual(reconstructed_single_expression, - stripped_single_expression) +def test_strip_properties_complex(): + complex_expression = \ + ('Tuple[FeatureData[Taxonomy % Properties("SILVA")] % Axis("ASV")' + ', DistanceMatrix % Axes("ASV", "ASV")] % Unique') + stripped_expression = 'Tuple[FeatureData[Taxonomy], DistanceMatrix]' + + reconstructed_expression = _strip_properties(complex_expression) + + assert reconstructed_expression == stripped_expression + + +def test_strip_properties_keeps_different_binop(): + expression_with_different_binop = \ + ('FeatureData[Taxonomy % Properties("SILVIA"), ' + 'Taxonomy & Properties]') + stripped_expression = \ + 'FeatureData[Taxonomy, Taxonomy & Properties]' + + reconstructed_expression = \ + _strip_properties(expression_with_different_binop) + + assert reconstructed_expression == stripped_expression + + +def test_strip_properties_multiple_strings(): + simple_expression = 'Taxonomy % Properties("SILVIA")' + stripped_simple_expression = 'Taxonomy' + + reconstructed_simple_expression = _strip_properties(simple_expression) + + single_expression = 'FeatureData[Taxonomy % Properties("SILVIA")]' + stripped_single_expression = 'FeatureData[Taxonomy]' + + reconstructed_single_expression = _strip_properties(single_expression) + + assert reconstructed_simple_expression == stripped_simple_expression + assert reconstructed_single_expression == stripped_single_expression