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())
예제 #2
0
    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()])
예제 #4
0
    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])
예제 #7
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'))))
예제 #10
0
    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()]
            )
예제 #12
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_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))
예제 #16
0
 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)
예제 #17
0
 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)
예제 #18
0
    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')
예제 #19
0
 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])
예제 #20
0
    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)
예제 #21
0
 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)
예제 #22
0
    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)
예제 #23
0
    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)
예제 #24
0
 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)
예제 #25
0
 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)
예제 #26
0
 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)
예제 #28
0
    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))
예제 #29
0
    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))
예제 #30
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(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])
예제 #31
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])
예제 #32
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))
예제 #33
0
    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)
예제 #34
0
 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)
예제 #35
0
    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))
예제 #36
0
    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)
예제 #37
0
    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)
예제 #38
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 / 'shapes.png'),
                     str(tempdir / 'shapes.Png'))
         self.window.open_file(path=tempdir / 'shapes.Png')
         mock_new_document.assert_called_once_with(tempdir / 'shapes.Png')
예제 #39
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 / '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])
예제 #40
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')
예제 #41
0
    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)
예제 #42
0
    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)
예제 #43
0
 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
         )
예제 #44
0
    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)
예제 #45
0
    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()
예제 #46
0
    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())
예제 #50
0
    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])
예제 #51
0
    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)
            )
예제 #55
0
    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)