def test_load_with_archive_filepath_modified(self): # Save a visualization for use in the following test case. fp = os.path.join(self.test_dir.name, 'visualization.qza') Visualization._from_data_dir(self.data_dir, None).save(fp) # Load the visualization from a filepath then save a different # visualization to the same filepath. Assert that both visualizations # access the correct data. # # `load` used to be lazy, only extracting data when it needed to (e.g. # when `save` or `get_index_paths` was called). This was buggy as the # filepath could have been deleted, or worse, modified to contain a # different .qzv file. Thus, the wrong archive could be extracted on # demand, or the archive could be missing altogether. There isn't an # easy cross-platform compatible way to solve this problem, so # Visualization.load is no longer lazy and always extracts its data # immediately. The real motivation for lazy loading was for quick # inspection of archives without extracting/copying data, so that API # is now provided through Visualization.peek. visualization1 = Visualization.load(fp) new_data_dir = os.path.join(self.test_dir.name, 'viz-output2') os.mkdir(new_data_dir) most_common_viz(new_data_dir, collections.Counter(range(42))) Visualization._from_data_dir(new_data_dir, None).save(fp) visualization2 = Visualization.load(fp) self.assertEqual(visualization1.get_index_paths(), {'html': 'data/index.html'}) self.assertEqual(visualization2.get_index_paths(), {'html': 'data/index.html', 'tsv': 'data/index.tsv'})
def test_load_with_archive_filepath_modified(self): # Save a visualization for use in the following test case. fp = os.path.join(self.test_dir.name, 'visualization.qzv') Visualization._from_data_dir(self.data_dir).save(fp) # Load the visualization from a filepath then save a different # visualization to the same filepath. Assert that both visualizations # access the correct data. # # `load` used to be lazy, only extracting data when it needed to (e.g. # when `save` or `get_index_paths` was called). This was buggy as the # filepath could have been deleted, or worse, modified to contain a # different .qzv file. Thus, the wrong archive could be extracted on # demand, or the archive could be missing altogether. There isn't an # easy cross-platform compatible way to solve this problem, so # Visualization.load is no longer lazy and always extracts its data # immediately. The real motivation for lazy loading was for quick # inspection of archives without extracting/copying data, so that API # is now provided through Visualization.peek. visualization1 = Visualization.load(fp) new_data_dir = os.path.join(self.test_dir.name, 'viz-output2') os.mkdir(new_data_dir) most_common_viz(new_data_dir, collections.Counter(range(42))) Visualization._from_data_dir(new_data_dir).save(fp) visualization2 = Visualization.load(fp) self.assertEqual(visualization1.get_index_paths(), {'html': 'data/index.html'}) self.assertEqual(visualization2.get_index_paths(), { 'html': 'data/index.html', 'tsv': 'data/index.tsv' })
def test_load_artifact_as_visualization(self): artifact = Artifact._from_view(FourInts, [0, 0, 42, 1000], list, self.provenance) fp = os.path.join(self.test_dir.name, 'artifact.qza') artifact.save(fp) with self.assertRaisesRegex( TypeError, 'Artifact.*Visualization.load.*Artifact.load'): Visualization.load(fp)
def test_roundtrip(self): fp1 = os.path.join(self.test_dir.name, 'visualization1.qzv') fp2 = os.path.join(self.test_dir.name, 'visualization2.qzv') visualization = Visualization._from_data_dir(self.data_dir) visualization.save(fp1) visualization1 = Visualization.load(fp1) visualization1.save(fp2) visualization2 = Visualization.load(fp2) self.assertEqual(visualization1.type, visualization2.type) self.assertEqual(visualization1.uuid, visualization2.uuid)
def test_roundtrip(self): fp1 = os.path.join(self.test_dir.name, 'visualization1.qzv') fp2 = os.path.join(self.test_dir.name, 'visualization2.qzv') visualization = Visualization._from_data_dir( self.data_dir, self.make_provenance_capture()) visualization.save(fp1) visualization1 = Visualization.load(fp1) visualization1.save(fp2) visualization2 = Visualization.load(fp2) self.assertEqual(visualization1.type, visualization2.type) self.assertEqual(visualization1.uuid, visualization2.uuid)
def test_load_and_save(self): fp1 = os.path.join(self.test_dir.name, 'visualization1.qzv') fp2 = os.path.join(self.test_dir.name, 'visualization2.qzv') visualization = Visualization._from_data_dir(self.data_dir) visualization.save(fp1) visualization = Visualization.load(fp1) # Overwriting its source file works. visualization.save(fp1) # Saving to a new file works. visualization.save(fp2) root_dir = str(visualization.uuid) expected = { 'VERSION', 'metadata.yaml', 'data/index.html', 'data/css/style.css' } self.assertArchiveMembers(fp1, root_dir, expected) root_dir = str(visualization.uuid) expected = { 'VERSION', 'metadata.yaml', 'data/index.html', 'data/css/style.css' } self.assertArchiveMembers(fp2, root_dir, expected)
def test_load_and_save(self): fp1 = os.path.join(self.test_dir.name, 'visualization1.qzv') fp2 = os.path.join(self.test_dir.name, 'visualization2.qzv') visualization = Visualization._from_data_dir(self.data_dir, self.provenance) visualization.save(fp1) visualization = Visualization.load(fp1) # Overwriting its source file works. visualization.save(fp1) # Saving to a new file works. visualization.save(fp2) with zipfile.ZipFile(fp1, mode='r') as zf: fps = set(zf.namelist()) expected = { 'visualization1/VERSION', 'visualization1/metadata.yaml', 'visualization1/README.md', 'visualization1/data/index.html', 'visualization1/data/css/style.css' } self.assertEqual(fps, expected) with zipfile.ZipFile(fp2, mode='r') as zf: fps = set(zf.namelist()) expected = { 'visualization2/VERSION', 'visualization2/metadata.yaml', 'visualization2/README.md', 'visualization2/data/index.html', 'visualization2/data/css/style.css' } self.assertEqual(fps, expected)
def test_eq_same_uuid(self): fp = os.path.join(self.test_dir.name, 'visualization.qzv') visualization1 = Visualization._from_data_dir(self.data_dir) visualization1.save(fp) visualization2 = Visualization.load(fp) self.assertEqual(visualization1, visualization2)
def test_get_index_paths_single_load(self): fp = os.path.join(self.test_dir.name, 'visualization.qzv') visualization = Visualization._from_data_dir(self.data_dir) visualization.save(fp) visualization = Visualization.load(fp) actual = visualization.get_index_paths() expected = {'html': 'data/index.html'} self.assertEqual(actual, expected)
def test_eq_same_uuid(self): fp = os.path.join(self.test_dir.name, 'visualization.qzv') visualization1 = Visualization._from_data_dir( self.data_dir, self.make_provenance_capture()) visualization1.save(fp) visualization2 = Visualization.load(fp) self.assertEqual(visualization1, visualization2)
def test_load(self): saved_visualization = Visualization._from_data_dir(self.data_dir) fp = os.path.join(self.test_dir.name, 'visualization.qzv') saved_visualization.save(fp) visualization = Visualization.load(fp) self.assertEqual(visualization.type, qiime.core.type.Visualization) self.assertEqual(visualization.uuid, saved_visualization.uuid)
def view_visualization(uuid): try: vis = Visualization.load(VISUALIZATIONS[uuid]) filePath = vis.get_index_paths(relative=False)['html'] ACTIVE_VIS[uuid] = vis except Exception: abort(404) return jsonify({'filePath': filePath})
def test_get_index_paths_single_load(self): fp = os.path.join(self.test_dir.name, 'visualization.qzv') visualization = Visualization._from_data_dir(self.data_dir, self.provenance) visualization.save(fp) visualization = Visualization.load(fp) actual = visualization.get_index_paths() expected = {'html': 'data/index.html'} self.assertEqual(actual, expected)
def test_load(self): saved_visualization = Visualization._from_data_dir(self.data_dir, None) fp = os.path.join(self.test_dir.name, 'visualization.qzv') saved_visualization.save(fp) visualization = Visualization.load(fp) self.assertEqual(visualization.type, qiime.core.type.Visualization) self.assertIsNone(visualization.provenance) self.assertEqual(visualization.uuid, saved_visualization.uuid)
def test_get_index_paths_multiple_load(self): data_dir = os.path.join(self.test_dir.name, 'mc-viz-output1') os.mkdir(data_dir) most_common_viz(data_dir, collections.Counter(range(42))) fp = os.path.join(self.test_dir.name, 'visualization.qzv') visualization = Visualization._from_data_dir(data_dir) visualization.save(fp) visualization = Visualization.load(fp) actual = visualization.get_index_paths() expected = {'html': 'data/index.html', 'tsv': 'data/index.tsv'} self.assertEqual(actual, expected)
def test_get_index_paths_multiple_html_load(self): data_dir = os.path.join(self.test_dir.name, 'multi-html-viz1') os.mkdir(data_dir) multi_html_viz(data_dir, [1, 42]) fp = os.path.join(self.test_dir.name, 'visualization.qzv') visualization = Visualization._from_data_dir(data_dir) visualization.save(fp) visualization = Visualization.load(fp) with self.assertRaises(ValueError): visualization.get_index_paths()
def test_ne_subclass_same_uuid(self): class VisualizationSubclass(Visualization): pass fp = os.path.join(self.test_dir.name, 'visualization.qzv') visualization1 = VisualizationSubclass._from_data_dir(self.data_dir) visualization1.save(fp) visualization2 = Visualization.load(fp) self.assertNotEqual(visualization1, visualization2) self.assertNotEqual(visualization2, visualization1)
def test_ne_subclass_same_uuid(self): class VisualizationSubclass(Visualization): pass fp = os.path.join(self.test_dir.name, 'visualization.qzv') visualization1 = VisualizationSubclass._from_data_dir( self.data_dir, self.make_provenance_capture()) visualization1.save(fp) visualization2 = Visualization.load(fp) self.assertNotEqual(visualization1, visualization2) self.assertNotEqual(visualization2, visualization1)
def test_get_index_paths_multiple_html_load(self): data_dir = os.path.join(self.test_dir.name, 'multi-html-viz1') os.mkdir(data_dir) multi_html_viz(data_dir, [1, 42]) fp = os.path.join(self.test_dir.name, 'visualization.qzv') visualization = Visualization._from_data_dir(data_dir, self.provenance) visualization.save(fp) visualization = Visualization.load(fp) with self.assertRaises(ValueError): visualization.get_index_paths()
def test_get_index_paths_multiple_load(self): data_dir = os.path.join(self.test_dir.name, 'mc-viz-output1') os.mkdir(data_dir) most_common_viz(data_dir, collections.Counter(range(42))) fp = os.path.join(self.test_dir.name, 'visualization.qzv') visualization = Visualization._from_data_dir(data_dir, self.provenance) visualization.save(fp) visualization = Visualization.load(fp) actual = visualization.get_index_paths() expected = {'html': 'data/index.html', 'tsv': 'data/index.tsv'} self.assertEqual(actual, expected)
def test_load_and_save(self): fp1 = os.path.join(self.test_dir.name, 'visualization1.qzv') fp2 = os.path.join(self.test_dir.name, 'visualization2.qzv') visualization = Visualization._from_data_dir( self.data_dir, self.make_provenance_capture()) visualization.save(fp1) visualization = Visualization.load(fp1) # Overwriting its source file works. visualization.save(fp1) # Saving to a new file works. visualization.save(fp2) root_dir = str(visualization.uuid) expected = { 'VERSION', 'metadata.yaml', 'data/index.html', 'data/css/style.css', 'provenance/metadata.yaml', 'provenance/VERSION', 'provenance/action/action.yaml' } self.assertArchiveMembers(fp1, root_dir, expected) root_dir = str(visualization.uuid) expected = { 'VERSION', 'metadata.yaml', 'data/index.html', 'data/css/style.css', 'provenance/metadata.yaml', 'provenance/VERSION', 'provenance/action/action.yaml' } self.assertArchiveMembers(fp2, root_dir, expected)
def test_load_from_externally_created_zipfile(self): # If a user unzips a .qzv to inspect contents and rezips using a # different ZIP library/implementation than the one provided by Python, # loading, saving, etc. should still work as expected. The Python ZIP # implementation doesn't store directories as entries when writing, but # the `zip` Unix and OS X command line utilities include both # directories and filepaths as entries. When reading these files with # Python's ZIP implementation, the directory entries are visible, so # their presence needs to be accounted for when extracting. # # The following visualization was created with: # # visualization = Visualization._from_data_dir(self.data_dir, # self.provenance) # visualization.save('externally_created_zipfile.qzv') # # Unzip and rezip using command line utility: # # unzip externally_created_zipfile.qzv # rm externally_created_zipfile.qzv # zip -r externally_created_zipfile.qzv externally_created_zipfile # fp = pkg_resources.resource_filename( 'qiime.sdk.tests', 'data/externally_created_zipfile.qzv') with zipfile.ZipFile(fp, mode='r') as zf: fps = set(zf.namelist()) expected = { # These are extra directory entries included by `zip` command # line utility. 'externally_created_zipfile/', 'externally_created_zipfile/data/', 'externally_created_zipfile/data/css/', 'externally_created_zipfile/VERSION', 'externally_created_zipfile/metadata.yaml', 'externally_created_zipfile/README.md', 'externally_created_zipfile/data/index.html', 'externally_created_zipfile/data/css/style.css' } self.assertEqual(fps, expected) visualization = Visualization.load(fp) self.assertEqual(visualization.type, qiime.core.type.Visualization) self.assertEqual(visualization.provenance, self.provenance) self.assertIsInstance(visualization.uuid, uuid.UUID) fp = os.path.join(self.test_dir.name, 'visualization.qzv') visualization.save(fp) with zipfile.ZipFile(fp, mode='r') as zf: fps = set(zf.namelist()) expected = { # Directory entries should not be present. 'visualization/VERSION', 'visualization/metadata.yaml', 'visualization/README.md', 'visualization/data/index.html', 'visualization/data/css/style.css' } self.assertEqual(fps, expected)