def test_refresh(self): "User refreshes the current, non-default template" w = self.window with temp_directory_with_files(TESTDATA / 'test.inselect_template') as tempdir,\ patch.object(QSettings, 'setValue') as mock_setvalue: path = tempdir / 'test.inselect_template' retval = str(path), w.view_metadata.popup_button.FILE_FILTER # Load the test template in tempdir with patch.object(QFileDialog, 'getOpenFileName', return_value=retval) as mock_gofn: w.view_metadata.popup_button.choose() self.assertEqual(1, mock_gofn.call_count) self.assertEqual('Test user template', user_template_choice().current.name) self.assertEqual('Test user template', self.window.view_metadata.popup_button.text()) # Write a new template to the file and refresh template = """Name: An updated test template Fields: - Name: catalogNumber """ with path.open('w') as outfile: outfile.write(template) # Refresh loaded template with patch.object(QSettings, 'value', return_value=str(path)) as mock_value: w.view_metadata.popup_button.refresh() self.assertEqual(1, mock_value.call_count) self.assertEqual("An updated test template", user_template_choice().current.name) self.assertEqual('An updated test template', self.window.view_metadata.popup_button.text())
def test_open_save_existing_modified(self, mock_question): "User chooses to save the existing modified document" w = self.window # Create a temporary inselect document so that it can be modified with temp_directory_with_files(TESTDATA / 'test_segment.inselect', TESTDATA / 'test_segment.png') as tempdir: # Oopen the temp doc and modify it self._load_and_modify(tempdir / 'test_segment.inselect') # Open another doc - user says not to save w.open_file(TESTDATA / 'test_subsegment.inselect') self.assertTrue(mock_question.called) expected = "Save the document before closing?" self.assertTrue(expected in mock_question.call_args[0]) self.assertEqual(1, w.model.rowCount()) self.assertEqual('Inselect [test_subsegment]', w.windowTitle()) # Original document should have changed - it should contain no boxes w.open_file(tempdir / 'test_segment.inselect') self.assertEqual(0, w.model.rowCount()) self.assertEqual('Inselect [test_segment]', w.windowTitle())
def test_cancel_save_crops(self): "User cancels save crops" with temp_directory_with_files(TESTDATA / 'shapes.inselect', TESTDATA / 'shapes.png') as tempdir: doc = InselectDocument.load(tempdir / 'shapes.inselect') # Create crops dir with some data doc.crops_dir.mkdir() with doc.crops_dir.joinpath('a_file').open('w') as outfile: outfile.write('Some data\n') class CancelExport(Exception): pass def progress(msg): "A progress function that cancels the export" raise CancelExport() self.assertRaises(CancelExport, DocumentExport(self.TEMPLATE).save_crops, doc, progress=progress) # Nothing should have changed within tempdir self.assertEqual( ['shapes.inselect', 'shapes.png', doc.crops_dir.name], sorted(p.name for p in tempdir.iterdir())) self.assertEqual(['a_file'], [p.name for p in doc.crops_dir.iterdir()])
def test_export_do_not_overwite_existing_csv(self, mock_information, mock_question): "User does not want to overwrite existing CSV file" w = self.window # Load document and write the CSV file with temp_directory_with_files(TESTDATA / 'test_segment.inselect', TESTDATA / 'test_segment.png') as tempdir: # Create a CSV file to force the GUI to prompt for over-write (tempdir / 'test_segment.csv').open('w') # Load document and export CSV file w.open_document(tempdir / 'test_segment.inselect') w.export_csv() # File should not have been altered self.assertEqual('', (tempdir / 'test_segment.csv').open().read()) # User should not have been told about the export self.assertFalse(mock_information.called) # User should have been prompted to overwrite the existing file self.assertTrue(mock_question.called) question = 'Overwrite the existing CSV file?' self.assertTrue(question in mock_question.call_args[0])
def test_load_images(self): "Load document's images" source = TESTDATA / 'shapes.inselect' with temp_directory_with_files(TESTDATA / 'shapes.inselect') as tempdir: doc_temp = tempdir / 'shapes.inselect' with doc_temp.open('w') as outfile, source.open() as infile: outfile.write(infile.read()) # Document load with neither scanned image file nor thumbnail self.assertRaises(InselectError, InselectDocument.load, doc_temp) # Document load with thumbnail but no scanned image file thumbnail_temp = tempdir / 'shapes_thumbnail.jpg' thumbnail_temp.touch() # File only needs to exist doc = InselectDocument.load(doc_temp) self.assertFalse(doc.scanned.available) self.assertTrue(doc.thumbnail.available) # Document load with both scanned and thumbnail files scanned_temp = tempdir / 'shapes.png' scanned_temp.touch() # File only needs to exist actual = InselectDocument.load(doc_temp) self.assertEqual(InselectDocument.load(source).items, actual.items) self.assertTrue(actual.scanned.available) self.assertTrue(actual.thumbnail.available) # Document load with scanned image file but not thumbnail os.unlink(str(thumbnail_temp)) actual = InselectDocument.load(doc_temp) self.assertEqual(InselectDocument.load(source).items, actual.items) self.assertTrue(actual.scanned.available) self.assertFalse(actual.thumbnail.available)
def test_export_do_not_overwite_existing_csv(self, mock_information, mock_question): "User does not want to overwrite existing CSV file" w = self.window # Load document and write the CSV file with temp_directory_with_files(TESTDATA / 'shapes.inselect', TESTDATA / 'shapes.png') as tempdir: # Create a CSV file to force the GUI to prompt for over-write (tempdir / 'shapes.csv').touch() # Load document and export CSV file w.open_document(tempdir / 'shapes.inselect') w.export_csv(user_template=DWC) # File should not have been altered with (tempdir / 'shapes.csv').open() as infile: self.assertEqual('', infile.read()) # User should not have been told about the export self.assertFalse(mock_information.called) # User should have been prompted to overwrite the existing file self.assertTrue(mock_question.called) question = 'Overwrite the existing CSV file?' self.assertTrue(question in mock_question.call_args[0])
def test_export_overwite_existing_csv(self, mock_information, mock_question): "User wants to overwrite existing CSV file" w = self.window # Load document and write the CSV file with temp_directory_with_files(TESTDATA / 'test_segment.inselect', TESTDATA / 'test_segment.png') as tempdir: # Create a CSV file to force the GUI to prompt for over-write (tempdir / 'test_segment.csv').open('w') # Load document and export CSV file w.open_document(tempdir / 'test_segment.inselect') w.export_csv() self._test_csv() # User should have been told about the export self.assertTrue(mock_information.called) expected = u"Data for 5 boxes written to {0}" expected = expected.format(tempdir / 'test_segment.csv') self.assertTrue(expected in mock_information.call_args[0]) # User should have been prompted to overwrite the existing file self.assertTrue(mock_question.called) question = 'Overwrite the existing CSV file?' self.assertTrue(question in mock_question.call_args[0])
def test_export_overwite_existing_csv(self, mock_information, mock_question): "User wants to overwrite existing CSV file" w = self.window # Load document and write the CSV file with temp_directory_with_files(TESTDATA / 'shapes.inselect', TESTDATA / 'shapes.png') as tempdir: # Create a CSV file to force the GUI to prompt for over-write (tempdir / 'shapes.csv').touch() # Load document and export CSV file w.open_document(path=tempdir / 'shapes.inselect') w.export_csv(user_template=DWC) self._test_csv() # User should have been told about the export self.assertTrue(mock_information.called) expected = "Data for 5 boxes written to {0}" expected = expected.format(tempdir / 'shapes.csv') self.assertTrue(expected in mock_information.call_args[0]) # User should have been prompted to overwrite the existing file self.assertTrue(mock_question.called) question = 'Overwrite the existing CSV file?' self.assertTrue(question in mock_question.call_args[0])
def test_save_crops(self): "Save crops" with temp_directory_with_files(TESTDATA / 'shapes.inselect', TESTDATA / 'shapes.png') as tempdir: main([str(tempdir)]) crops = tempdir / 'shapes_crops' self.assertEqual(5, len(list(crops.glob('*jpg'))))
def test_copy_to_new_document(self, mock_new_document): "User copies boxes to a new document" # open_file delegates to new_document, which runs an operation runs in a # worker thread - I could not think of a way to test the complete # operation in a single test. # This test checks that new_document is called as expected. w = self.window w.open_file(path=TESTDATA / 'shapes.inselect') # Take a copy of the metadata expected_metadata = w.document.items with temp_directory_with_files(TESTDATA / 'shapes.png') as tempdir: image = tempdir / 'other_image.png' (tempdir / 'shapes.png').rename(image) retval = str(image), w.IMAGE_FILE_FILTER with patch.object(QFileDialog, 'getOpenFileName', return_value=retval) as mock_gofn: w.copy_to_new_document() self.assertEqual(1, mock_gofn.call_count) # New document should have been called with the path to the image self.assertTrue(mock_new_document.called) mock_new_document.assert_called_once_with( image, default_metadata_items=expected_metadata ) # Orignal document should have been closed self.assertIsNone(self.window.document)
def test_cancel_save_crops(self): "User cancels save crops" with temp_directory_with_files(TESTDATA / 'shapes.inselect', TESTDATA / 'shapes.png') as tempdir: doc = InselectDocument.load(tempdir / 'shapes.inselect') # Create crops dir with some data doc.crops_dir.mkdir() with doc.crops_dir.joinpath('a_file').open('w') as outfile: outfile.write('Some data\n') class CancelExport(Exception): pass def progress(msg): "A progress function that cancels the export" raise CancelExport() self.assertRaises( CancelExport, DocumentExport(self.TEMPLATE).save_crops, doc, progress=progress ) # Nothing should have changed within tempdir self.assertEqual( ['shapes.inselect', 'shapes.png', doc.crops_dir.name], sorted(p.name for p in tempdir.iterdir())) self.assertEqual( ['a_file'], [p.name for p in doc.crops_dir.iterdir()] )
def test_read_barcodes_no_scanned_image(self, mock_warning): """The user is informed that barcodes cannot be read without the scanned image """ with temp_directory_with_files(TESTDATA / 'barcodes.inselect') as tempdir: # Create thumbnail file shutil.copy(str(TESTDATA.joinpath('barcodes.jpg')), str(tempdir.joinpath('barcodes_thumbnail.jpg'))) self.window.open_document(path=tempdir / 'barcodes.inselect') self.window.run_plugin(2) expected = ('Unable to read barcodes because the original ' 'full-resolution image file does not exist.') self.assertTrue(expected in mock_warning.call_args[0]) model = self.window.model # Metadata should be unaltered indexes = (model.index(row, 0) for row in range(3)) self.assertEqual( [None, None, None], [model.data(i, MetadataRole).get('catalogNumber') for i in indexes] ) self.assertFalse(model.is_modified)
def test_export_csv(self): "Export metadata to CSV" with temp_directory_with_files(TESTDATA / 'shapes.inselect', TESTDATA / 'shapes.png') as tempdir: # Create an empty CSV file csv = tempdir / 'shapes.csv' with csv.open('w'): pass main([str(tempdir), '--overwrite']) csv = tempdir / 'shapes.csv' self.assertTrue(csv.is_file()) # Check CSV contents doc = InselectDocument.load(tempdir / 'shapes.inselect') with csv.open('rb') as f: res = unicodecsv.DictReader(f, encoding='utf-8') for index, item, row in zip(count(), doc.items, res): expected = item['fields'] expected.update({ 'ItemNumber': str(1+index), 'Cropped_image_name': '{0:04}.jpg'.format(1+index) }) actual = { k: v for k, v in row.items() if v and k not in BOUNDING_BOX_FIELD_NAMES } self.assertEqual(expected, actual)
def test_csv_export(self): "CSV data are exported as expected" with temp_directory_with_files(TESTDATA / 'shapes.inselect', TESTDATA / 'shapes.png') as tempdir: doc = InselectDocument.load(tempdir / 'shapes.inselect') csv_path = DocumentExport(self.TEMPLATE).export_csv(doc) self.assertEqual(csv_path, tempdir / 'shapes.csv') # Check CSV contents with csv_path.open('rb') as f: reader = unicodecsv.reader(f, encoding='utf8') headers = [ 'Cropped_image_name', 'ItemNumber', 'NormalisedLeft', 'NormalisedTop', 'NormalisedRight', 'NormalisedBottom', 'ThumbnailLeft', 'ThumbnailTop', 'ThumbnailRight', 'ThumbnailBottom', 'OriginalLeft', 'OriginalTop', 'OriginalRight', 'OriginalBottom', 'catalogNumber', 'Department', 'scientificName', 'scientificName-value' ] self.assertEqual(headers, next(reader)) # Check only the metadata columns and 'original' coordinates # columns, ignoring thumbnail (which doesn't exist) # and normalised (which are floating point) coordinates metadata_cols = itemgetter(0, 1, 10, 11, 12, 13, 14, 15, 16, 17) self.assertEqual( ('01_1.png', '1', '0', '0', '189', '189', '1', 'Entomology', 'A', '1'), metadata_cols(next(reader)) ) self.assertEqual( ('02_2.png', '2', '271', '0', '459', '189', '2', 'Entomology', 'B', '2'), metadata_cols(next(reader)) ) self.assertEqual( ('03_10.png', '3', '194', '196', '257', '232', '3', 'Entomology', 'インセクト', '10'), metadata_cols(next(reader)) ) self.assertEqual( ('04_3.png', '4', '0', '248', '189', '437', '4', 'Entomology', 'Elsinoë', '3'), metadata_cols(next(reader)) ) self.assertEqual( ('05_4.png', '5', '271', '248', '459', '437', '5', 'Entomology', 'D', '4'), metadata_cols(next(reader)) ) self.assertIsNone(next(reader, None))
def test_reveal_path_windows(self, mock_subprocess): "User reveals a path" with temp_directory_with_files() as tempdir: path = tempdir / 'xyz' path.touch() reveal_path(path) expected = "explorer.exe /select,{0}".format(path.resolve()) mock_subprocess.assert_called_once_with(expected)
def test_new_from_thumbnail(self): "Can't create a document from a thumbnail image" with temp_directory_with_files(TESTDATA / 'test_segment.png') as tempdir: doc = InselectDocument.new_from_scan(tempdir / 'test_segment.png') doc.ensure_thumbnail(width=2048) doc = None self.assertRaises(InselectError, InselectDocument.new_from_scan, tempdir / 'test_segment_thumbnail.png')
def test_ensure_thumbnail(self): "Thumbnail is created" source_doc = TESTDATA / 'test_segment.inselect' source_img = TESTDATA / 'test_segment.png' with temp_directory_with_files(source_doc, source_img) as tempdir: # Document load with no scanned image file doc = InselectDocument.load(tempdir / 'test_segment.inselect') self.assertTrue(doc.thumbnail is None) doc.ensure_thumbnail(width=2048) self.assertEqual(2048, doc.thumbnail.array.shape[1])
def test_ensure_thumbnail_silly_size(self): "Can't create thumbnail with a silly size" source_doc = TESTDATA / 'test_segment.inselect' source_img = TESTDATA / 'test_segment.png' with temp_directory_with_files(source_doc, source_img) as tempdir: doc = InselectDocument.load(tempdir / 'test_segment.inselect') self.assertRaises(InselectError, doc.ensure_thumbnail, -1) self.assertRaises(InselectError, doc.ensure_thumbnail, 50) self.assertRaises(InselectError, doc.ensure_thumbnail, 20000)
def test_new_from_thumbnail(self): "Can't create a document from a thumbnail image" with temp_directory_with_files(TESTDATA / 'shapes.png') as tempdir: doc = InselectDocument.new_from_scan(tempdir / 'shapes.png', thumbnail_width_pixels=2048) thumbnail = tempdir / 'shapes_thumbnail.jpg' self.assertTrue(thumbnail.is_file()) self.assertTrue(doc.thumbnail.available) self.assertEqual(2048, doc.thumbnail.array.shape[1]) self.assertRaises(InselectError, InselectDocument.new_from_scan, thumbnail)
def test_new_from_scan(self): "New document is created and saved" with temp_directory_with_files(TESTDATA / 'shapes.png') as tempdir: doc = InselectDocument.new_from_scan(tempdir / 'shapes.png') self.assertTrue(doc.document_path.is_file()) self.assertEqual(tempdir / 'shapes.png', doc.scanned.path) # Saved on time should be within last 2 seconds now = datetime.now(pytz.timezone("UTC")) created_on = doc.properties['Created on'] self.assertLessEqual((now - created_on).seconds, 2)
def test_new_from_scan(self): "New document is created and saved" with temp_directory_with_files(TESTDATA / 'test_segment.png') as tempdir: doc = InselectDocument.new_from_scan(tempdir / 'test_segment.png') self.assertTrue(doc.document_path.is_file()) self.assertEqual(tempdir / 'test_segment.png', doc.scanned.path) # Saved on time should be within last 2 seconds now = datetime.now(pytz.timezone("UTC")) created_on = doc.properties['Created on'] self.assertLessEqual((now - created_on).seconds, 2)
def test_new_from_thumbnail(self): "Can't create a document from a thumbnail image" with temp_directory_with_files(TESTDATA / 'test_segment.png') as tempdir: doc = InselectDocument.new_from_scan( tempdir / 'test_segment.png', thumbnail_width_pixels=2048 ) thumbnail = tempdir / 'test_segment_thumbnail.jpg' self.assertTrue(thumbnail.is_file()) self.assertEqual(2048, doc.thumbnail.array.shape[1]) self.assertRaises(InselectError, InselectDocument.new_from_scan, thumbnail)
def test_thumbnail_silly_size(self): "Can't create thumbnail with a silly size" with temp_directory_with_files(TESTDATA / 'shapes.png') as tempdir: self.assertRaisesRegex(InselectError, "width should be between", InselectDocument.new_from_scan, tempdir / 'shapes.png', -1) self.assertRaisesRegex(InselectError, "width should be between", InselectDocument.new_from_scan, tempdir / 'shapes.png', 50) self.assertRaisesRegex(InselectError, "width should be between", InselectDocument.new_from_scan, tempdir / 'shapes.png', 20000)
def test_reveal_path_os_x(self, mock_subprocess): "User reveals a path" with temp_directory_with_files() as tempdir: path = tempdir / 'xyz' path.touch() reveal_path(path) expected = [ '/usr/bin/osascript', '-e', 'tell application "Finder" to reveal POSIX file "{0}"'.format( str(path.resolve())) ] mock_subprocess.assert_any_call(expected)
def test_save_crops_with_existing(self): "Attempt to save crops over an existing directory" with temp_directory_with_files(TESTDATA / 'shapes.inselect', TESTDATA / 'shapes.png') as tempdir: # Create crops dir crops = tempdir / 'shapes_crops' crops.mkdir() main([str(tempdir)]) # nose hooks up stdout to a file-like object stdout = sys.stdout.getvalue() self.assertIn('exists - skipping', stdout)
def test_shapes(self): "Segment an existing document" with temp_directory_with_files(TESTDATA / 'shapes.png') as tempdir: # Create a new document ingest_image(tempdir / 'shapes.png', tempdir) main([str(tempdir)]) doc_path = tempdir / 'shapes.inselect' self.assertTrue(doc_path.is_file()) doc = InselectDocument.load(doc_path) self.assertEqual(5, len(doc.items))
def test_segment(self): "Segment an existing document" with temp_directory_with_files(TESTDATA / 'test_segment.png') as tempdir: # Create a new document ingest_image(tempdir / 'test_segment.png', tempdir) main([unicode(tempdir)]) doc_path = tempdir / 'test_segment.inselect' self.assertTrue(doc_path.is_file()) doc = InselectDocument.load(doc_path) self.assertEqual(5, len(doc.items))
def test_new_document(self, mock_new_document): """Open an image file for which no inselect document exists """ # open_file delegates to new_document, which runs an operation runs in a # worker thread - I could not think of a way to test the complete # operation in a single test. # This test checks that new_document is called as expected. with temp_directory_with_files(TESTDATA / 'test_segment.png') as tempdir: self.window.open_file(tempdir / 'test_segment.png') self.assertTrue(mock_new_document.called) self.assertEqual(tempdir / 'test_segment.png', mock_new_document.call_args[0][0])
def test_open_readonly_doc(self, mock_warning): "User is warned when opening a read-only inselect document" with temp_directory_with_files(TESTDATA / 'test_segment.inselect', TESTDATA / 'test_segment.png', ) as tempdir: make_readonly(tempdir / 'test_segment.inselect') self.window.open_file(tempdir / 'test_segment.inselect') self.assertTrue(mock_warning.called) expected = (u'The file [test_segment.inselect] is read-only.\n\n' u'You will not be able to save any changes that you ' 'make.') self.assertTrue(expected in mock_warning.call_args[0])
def test_path_is_thumbnail_file(self): with temp_directory_with_files() as tempdir: thumbnail = tempdir / 'xx_thumbnail.jpg' thumbnail.open('w') # File only needs to exist # Thumbnail file exists but there is no corresponding .inselect doc self.assertFalse(InselectDocument.path_is_thumbnail_file(thumbnail)) doc = tempdir / 'xx.inselect' doc.open('w') # File only needs to exist # Thumbnail file and corresponding .inselect file both exist self.assertTrue(InselectDocument.path_is_thumbnail_file(thumbnail))
def test_thumbnail_read_only(self): "Can't write thumbnail to a read-only directory" # This case is doing more than simply testing filesystem behavour # because it tests the failure code in InselectDocument with temp_directory_with_files(TESTDATA / 'shapes.png') as tempdir: mode = make_readonly(tempdir) self.assertRaises(InselectError, InselectDocument.new_from_scan, tempdir / 'shapes.png', thumbnail_width_pixels=2048) # Restor the original mode tempdir.chmod(mode)
def test_reveal_path_os_x(self, mock_subprocess): "User reveals a path" with temp_directory_with_files() as tempdir: path = tempdir / 'xyz' path.touch() reveal_path(path) expected = [ '/usr/bin/osascript', '-e', 'tell application "Finder" to reveal POSIX file "{0}"'.format( str(path.resolve()) ) ] mock_subprocess.assert_any_call(expected)
def test_path_is_thumbnail_file(self): with temp_directory_with_files() as tempdir: thumbnail = tempdir / 'xx_thumbnail.jpg' thumbnail.touch() # File only needs to exist # Thumbnail file exists but there is no corresponding .inselect doc self.assertFalse( InselectDocument.path_is_thumbnail_file(thumbnail)) doc = tempdir / 'xx.inselect' doc.touch() # File only needs to exist # Thumbnail file and corresponding .inselect file both exist self.assertTrue(InselectDocument.path_is_thumbnail_file(thumbnail))
def test_save(self): "Document save writes items" source = TESTDATA / 'test_segment.inselect' temp = tempfile.mkdtemp() with temp_directory_with_files(TESTDATA / 'test_segment.inselect', TESTDATA / 'test_segment.png') as tempdir: items = [ {'fields': {}, 'rect': Rect(0.1, 0.2, 0.5, 0.5) }, ] doc_temp = tempdir / 'test_segment.inselect' d = InselectDocument.load(doc_temp) d.set_items(items) d.save() self.assertEqual(items, InselectDocument.load(doc_temp).items)
def test_thumbnail_read_only(self): "Can't write thumbnail to a read-only directory" # This case is doing more than simply testing filesystem behavour # because it tests the failure code in InselectDocument with temp_directory_with_files(TESTDATA / 'test_segment.png') as tempdir: mode = make_readonly(tempdir) self.assertRaises( InselectError, InselectDocument.new_from_scan, tempdir / 'test_segment.png', thumbnail_width_pixels=2048 ) # Restor the original mode tempdir.chmod(mode)
def test_new_document(self, mock_new_document): """Open an image file for which no inselect document exists """ # open_file delegates to new_document, which runs an operation runs in a # worker thread - I could not think of a way to test the complete # operation in a single test. # This test checks that new_document is called as expected. with temp_directory_with_files() as tempdir: # Check that open_file accepts images with a file extension that is # not all lower case. shutil.copy(str(TESTDATA / 'shapes.png'), str(tempdir / 'shapes.Png')) self.window.open_file(path=tempdir / 'shapes.Png') mock_new_document.assert_called_once_with(tempdir / 'shapes.Png')
def test_open_readonly_doc(self, mock_warning): "User is warned when opening a read-only inselect document" with temp_directory_with_files( TESTDATA / 'shapes.inselect', TESTDATA / 'shapes.png', ) as tempdir: make_readonly(tempdir / 'shapes.inselect') self.window.open_file(path=tempdir / 'shapes.inselect') self.assertTrue(mock_warning.called) expected = ('The file [shapes.inselect] is read-only.\n\n' 'You will not be able to save any changes that you ' 'make.') self.assertTrue(expected in mock_warning.call_args[0])
def test_new_document(self, mock_new_document): """Open an image file for which no inselect document exists """ # open_file delegates to new_document, which runs an operation runs in a # worker thread - I could not think of a way to test the complete # operation in a single test. # This test checks that new_document is called as expected. with temp_directory_with_files() as tempdir: # Check that open_file accepts images with a file extension that is # not all lower case. shutil.copy(str(TESTDATA / 'test_segment.png'), str(tempdir / 'test_segment.Png')) self.window.open_file(tempdir / 'test_segment.Png') mock_new_document.assert_called_once_with(tempdir / 'test_segment.Png')
def test_open_non_ascii(self): "Open an inselect document with non-ascii characters in the filename" with temp_directory_with_files() as tempdir: stem = 'åland' path = tempdir.joinpath('{0}.inselect'.format(stem)) shutil.copy(str(TESTDATA.joinpath('shapes.inselect')), str(path)) shutil.copy(str(TESTDATA.joinpath('shapes.png')), str(tempdir.joinpath('{0}.png'.format(stem)))) doc = InselectDocument.load(path) # Properties are as expected self.assertEqual(doc.document_path, path)
def test_ensure_thumbnail_read_only(self): "Can't write thumbnail to a read-only directory" # This case is doing more than simply testing filesystem behavour # because it tests the failure code in InselectDocument source_doc = TESTDATA / 'test_segment.inselect' source_img = TESTDATA / 'test_segment.png' with temp_directory_with_files(source_doc, source_img) as tempdir: doc = InselectDocument.load(tempdir / 'test_segment.inselect') mode = make_readonly(tempdir) self.assertRaises(InselectError, doc.ensure_thumbnail) # Restor the original mode tempdir.chmod(mode)
def test_thumbnail_silly_size(self): "Can't create thumbnail with a silly size" with temp_directory_with_files(TESTDATA / 'test_segment.png') as tempdir: self.assertRaisesRegexp( InselectError, "width should be between", InselectDocument.new_from_scan, tempdir / 'test_segment.png', -1 ) self.assertRaisesRegexp( InselectError, "width should be between", InselectDocument.new_from_scan, tempdir / 'test_segment.png', 50 ) self.assertRaisesRegexp( InselectError, "width should be between", InselectDocument.new_from_scan, tempdir / 'test_segment.png', 20000 )
def test_open_non_ascii(self): "Open an inselect document with non-ascii characters in the filename" with temp_directory_with_files() as tempdir: stem = 'åland' path = tempdir.joinpath('{0}.inselect'.format(stem)) shutil.copy(str(TESTDATA.joinpath('shapes.inselect')), str(path)) shutil.copy( str(TESTDATA.joinpath('shapes.png')), str(tempdir.joinpath('{0}.png'.format(stem))) ) doc = InselectDocument.load(path) # Properties are as expected self.assertEqual(doc.document_path, path)
def test_open_thumbnail_of_doc(self): """Open the thumbnail image file of an existing inselect document - the inselect document should be opened """ with temp_directory_with_files(TESTDATA / 'test_segment.inselect', TESTDATA / 'test_segment.png', ) as tempdir: thumbnail = tempdir / 'test_segment_thumbnail.jpg' # The test document contains no thumbnail file - create one now shutil.copy(str(tempdir / 'test_segment.png'), str(thumbnail)) self.window.open_file(thumbnail) self.assertEqual(5, self.window.model.rowCount()) self.assertFalse(self.window.model.is_modified) self.assertWindowTitleOpenDocument()
def test_save_crops(self): "Cropped specimen images are written correctly" with temp_directory_with_files(TESTDATA / 'test_segment.inselect', TESTDATA / 'test_segment.png') as tempdir: doc = InselectDocument.load(tempdir / 'test_segment.inselect') crops_dir = doc.save_crops() self.assertTrue(crops_dir.is_dir()) self.assertEqual(crops_dir, doc.crops_dir) self.assertEqual(5, len(list(crops_dir.glob('*.png')))) # Check the contents of each file boxes = doc.scanned.from_normalised([i['rect'] for i in doc.items]) for box, path in izip(boxes, sorted(crops_dir.glob('*.png'))): x0, y0, x1, y1 = box.coordinates self.assertTrue(np.all(doc.scanned.array[y0:y1, x0:x1] == cv2.imread(str(path))))
def test_modified_cleared(self): "Alter document and clear" with temp_directory_with_files(TESTDATA / 'shapes.inselect', TESTDATA / 'shapes.png') as tempdir: m = Model() m.from_document(InselectDocument.load(tempdir / 'shapes.inselect')) # Alter data mock_modified_changed = self._new_mock_modified_changed(m) m.setData(m.index(0, 0), -90, RotationRole) mock_modified_changed.assert_called_once_with() self.assertTrue(m.is_modified) # Clear m.clear() self.assertEqual(2, mock_modified_changed.call_count) self.assertFalse(m.is_modified)
def test_export_no_existing_csv(self, mock_information): "User exported CSV" w = self.window # Load document and write the CSV file with temp_directory_with_files(TESTDATA / 'shapes.inselect', TESTDATA / 'shapes.png') as tempdir: # Load document and export CSV file w.open_document(path=tempdir / 'shapes.inselect') w.export_csv(user_template=DWC) self._test_csv() # User should have been told about the export self.assertTrue(mock_information.called) expected = "Data for 5 boxes written to {0}" expected = expected.format(tempdir / 'shapes.csv') self.assertTrue(expected in mock_information.call_args[0])
def test_export_csv_with_template(self): "Export metadata to CSV using a metadata template" with temp_directory_with_files(TESTDATA / 'shapes.inselect', TESTDATA / 'shapes.png') as tempdir: main([str(tempdir), '--template={0}'.format(TESTDATA / 'test.inselect_template')]) # nose hooks up stdout to a file-like object stdout = sys.stdout.getvalue() self.assertIn('because there are validation problems', stdout) self.assertIn('Box [1] [0001] lacks mandatory field [Taxonomy]', stdout) self.assertIn('Box [1] [0001] lacks mandatory field [Location]', stdout) self.assertIn( 'Could not parse value of [catalogNumber] [1] for box [1] [0001]', stdout ) csv = tempdir / 'shapes.csv' self.assertFalse(csv.is_file())
def test_modified_cleared(self): "Alter document and clear" with temp_directory_with_files(TESTDATA / 'test_segment.inselect', TESTDATA / 'test_segment.png') as tempdir: m = Model() m.from_document(InselectDocument.load(tempdir / 'test_segment.inselect')) # Alter data mock_modified_changed = self._new_mock_modified_changed(m) m.setData(m.index(0, 0), -90, RotationRole) mock_modified_changed.assert_called_once_with() self.assertTrue(m.is_modified) # Clear m.clear() self.assertEqual(2, mock_modified_changed.call_count) self.assertFalse(m.is_modified)
def test_save_crops_no_scanned_image(self, mock_warning): "The user is informed that there is no scanned image" with temp_directory_with_files(TESTDATA / 'shapes.inselect') as tempdir: # Create thumbnail file img = cv2.imread(str(TESTDATA.joinpath('shapes.png'))) cv2.imwrite(str(tempdir.joinpath('shapes_thumbnail.jpg')), img) self.window.open_document(path=tempdir / 'shapes.inselect') crops_dir = tempdir / 'shapes_crops' self.assertFalse(crops_dir.is_dir()) self.window.save_crops(user_template=DWC) expected = ('Unable to save crops because the original ' 'full-resolution image file does not exist.') self.assertTrue(expected in mock_warning.call_args[0]) # Crops should not have been written self.assertFalse(crops_dir.is_dir())
def test_save_crops_overwrite(self, mock_warning, mock_information): "The user is prompted to overwrite existing crops" with temp_directory_with_files(TESTDATA / 'shapes.inselect', TESTDATA / 'shapes.png') as tempdir: self.window.open_document(path=tempdir / 'shapes.inselect') crops_dir = tempdir / 'shapes_crops' crops_dir.mkdir() self.assertTrue(crops_dir.is_dir()) # Answer with 'no' with patch.object(QMessageBox, 'question', return_value=QMessageBox.No) as mock_question: self.window.save_crops(user_template=DWC) expected = 'Overwrite the existing object images?' self.assertTrue(expected in mock_question.call_args[0]) # Crops dir still contains no files self.assertTrue(crops_dir.is_dir()) self.assertEqual(0, len(list(crops_dir.iterdir()))) # Confirmation of saving crops was not shown self.assertFalse(mock_information.called) # Answer with 'no' with patch.object(QMessageBox, 'question', return_value=QMessageBox.Yes) as mock_question: self.run_async_operation( partial(self.window.save_crops, user_template=DWC) ) expected = 'Overwrite the existing object images?' self.assertTrue(expected in mock_question.call_args[0]) # Five crops written self.assertTrue(crops_dir.is_dir()) self.assertEqual(5, len(list(crops_dir.iterdir()))) # Confirmation of saving crops was shown self.assertTrue(mock_information.called) # User should not have been warned about missing scanned image self.assertFalse(mock_warning.called)
def test_read_barcodes(self): "Read barcodes" with temp_directory_with_files(TESTDATA / 'barcodes.inselect', TESTDATA / 'barcodes.jpg') as tempdir: doc_path = tempdir.joinpath('barcodes.inselect') # Doc should not have any catalog numbers doc = InselectDocument.load(doc_path) self.assertFalse( any(v.get('fields', {}).get('catalogNumber') for v in doc.items) ) main([str(tempdir), 'libdmtx']) # Doc should not have expected catalog numbers doc = InselectDocument.load(doc_path) self.assertEqual( ['1681107', '1681110', '1681112'], sorted(v['fields']['catalogNumber'] for v in doc.items) )
def test_save(self): "Save document" with temp_directory_with_files(TESTDATA / 'test_segment.inselect', TESTDATA / 'test_segment.png') as tempdir: items = [{ 'fields': {'type': u'インセクト'}, 'rect': Rect(0.1, 0.2, 0.5, 0.5), }] doc_temp = tempdir / 'test_segment.inselect' d = InselectDocument.load(doc_temp) d.set_items(items) d.save() self.assertEqual(items, InselectDocument.load(doc_temp).items) # Saved on time should be within last 2 seconds now = datetime.now(pytz.timezone("UTC")) saved_on = d.properties['Saved on'] self.assertLessEqual((now - saved_on).seconds, 2)