Repository: qiime2/qiime2 (python)

Issue:
`_FileFormat` Should Have A `.view` Method
**Improvement Description**
`_FileFormat` should have a `.view` method

**Current Behavior**
`BoundFile` objects have a `.view` method allowing for easy transformation between classes, but `_FileFormat` objects do not. This means the easiest way to transform `_FileFormat` objects is to create a directory format with them as a bound file and then use their `.view`.

**Proposed Behavior**
Add a `.view` method to `_FileFormat`

Pull request:
IMP: Add .view method to _FileFormat
Closes #482 `_FileFormat` objects now have a `.view` method allowing for easy transformation of `_FileFormat` subclasses without them needing to be turned into `BoundFile` objects. I am unsure of how to test this code. Should `.view` tests be added to the tests for every `_FileFormat` subclass testing each of their transformers? Should the `dummy_plugin` be used to test the transformers of the subclasses of `_FileFormat` in `dummy_plugin`?

Patch:
diff --git a/qiime2/plugin/model/file_format.py b/qiime2/plugin/model/file_format.py
index e32f8a1..575ba03 100644
--- a/qiime2/plugin/model/file_format.py
+++ b/qiime2/plugin/model/file_format.py
@@ -8,6 +8,7 @@
 
 import abc
 
+from qiime2.core import transform
 from .base import FormatBase, ValidationError, _check_validation_level
 
 
@@ -39,6 +40,13 @@ class _FileFormat(FormatBase, metaclass=abc.ABCMeta):
             raise NotImplementedError("%r does not implement validate."
                                       % type(self))
 
+    def view(self, view_type):
+        from_type = transform.ModelType.from_view_type(self.__class__)
+        to_type = transform.ModelType.from_view_type(view_type)
+
+        transformation = from_type.make_transformation(to_type)
+        return transformation(self)
+
 
 class TextFileFormat(_FileFormat):
     def open(self):


Test patch:
diff --git a/qiime2/plugin/model/tests/test_file_format.py b/qiime2/plugin/model/tests/test_file_format.py
index 4495781..65185d1 100644
--- a/qiime2/plugin/model/tests/test_file_format.py
+++ b/qiime2/plugin/model/tests/test_file_format.py
@@ -11,6 +11,7 @@ import unittest
 import tempfile
 
 import qiime2.plugin.model as model
+from qiime2.core.testing.plugin import SingleIntFormat
 
 
 class TestTextFileFormat(unittest.TestCase):
@@ -59,5 +60,28 @@ class TestTextFileFormat(unittest.TestCase):
             self.assertEqual(b'S', fh.read(1))
 
 
+class TestFileFormat(unittest.TestCase):
+    def setUp(self):
+        self.test_dir = tempfile.TemporaryDirectory(prefix='qiime2-test-temp-')
+
+        path = os.path.join(self.test_dir.name, 'int')
+        with open(path, 'w') as fh:
+            fh.write('1')
+
+        self.format = SingleIntFormat(path, mode='r')
+
+    def tearDown(self):
+        self.test_dir.cleanup()
+
+    def test_view_expected(self):
+        number = self.format.view(int)
+        self.assertEqual(1, number)
+
+    def test_view_invalid_type(self):
+        with self.assertRaisesRegex(
+                Exception, "No transformation.*SingleIntFormat.*float"):
+            self.format.view(float)
+
+
 if __name__ == '__main__':
     unittest.main()