def test_no_updated_date(self):
        format = 'https://spec-url-for-format'
        content = data_model.CombineArchiveContent('1.txt', format, False)

        archive = data_model.CombineArchive([content])

        archive_file = os.path.join(self.temp_dir, 'test.omex')
        in_dir = os.path.join(self.temp_dir, 'in')
        out_dir = os.path.join(self.temp_dir, 'out')
        os.mkdir(in_dir)
        os.mkdir(out_dir)

        with open(os.path.join(in_dir, content.location), 'w') as file:
            file.write('a')

        io.CombineArchiveWriter().run(archive, in_dir, archive_file)

        archive_b = io.CombineArchiveReader().run(archive_file, out_dir)
        archive_b.contents = list(
            filter(
                lambda content: content.format != data_model.
                CombineArchiveContentFormat.OMEX_METADATA, archive_b.contents))
        self.assertTrue(archive.is_equal(archive_b))

        self.assertEqual(sorted(os.listdir(out_dir)),
                         sorted([
                             content.location,
                             'manifest.xml',
                         ]))
        with open(os.path.join(out_dir, content.location), 'r') as file:
            self.assertEqual('a', file.read())
    def test_write_read_manifest_with_manifest(self):
        manifest_filename = os.path.join(self.temp_dir, 'test.xml')
        contents = [
            data_model.CombineArchiveContent(
                location='1.txt',
                format='http://purl.org/NET/mediatypes/plain/text',
                master=False,
            ),
            data_model.CombineArchiveContent(
                location='2.jpg',
                format='http://purl.org/NET/mediatypes/image/jpeg',
                master=True,
            ),
            data_model.CombineArchiveContent(
                location='manifest.xml',
                format=data_model.CombineArchiveContentFormat.OMEX_MANIFEST,
                master=False,
            ),
        ]

        io.CombineArchiveWriter().write_manifest(contents, manifest_filename)
        contents_2 = io.CombineArchiveReader().read_manifest(manifest_filename)

        archive = data_model.CombineArchive(contents=contents)
        archive_2 = data_model.CombineArchive(contents=contents_2)
        self.assertTrue(archive_2.is_equal(archive))
    def test(self):
        format = 'https://spec-url-for-format'
        content1 = data_model.CombineArchiveContent('1.txt', format, False)
        content2 = data_model.CombineArchiveContent('2/2.txt', format, True)

        archive1 = data_model.CombineArchive([content1, content2])
        archive2 = data_model.CombineArchive([content1, content1])

        archive_file = os.path.join(self.temp_dir, 'test.omex')
        in_dir = os.path.join(self.temp_dir, 'in')
        out_dir = os.path.join(self.temp_dir, 'out')
        out_dir2 = os.path.join(self.temp_dir, 'out2')
        os.mkdir(in_dir)
        os.mkdir(os.path.join(in_dir, '2'))
        os.mkdir(out_dir)

        with open(os.path.join(in_dir, content1.location), 'w') as file:
            file.write('a')
        with open(os.path.join(in_dir, content2.location), 'w') as file:
            file.write('b')

        io.CombineArchiveWriter().run(archive1, in_dir, archive_file)
        archive1b = io.CombineArchiveReader().run(
            archive_file, out_dir, include_omex_metadata_files=False)
        self.assertTrue(archive1.is_equal(archive1b))

        archive1b = io.CombineArchiveReader().run(
            archive_file, out_dir, include_omex_metadata_files=True)
        metadata_contents = [
            content.location for content in archive1b.contents if re.match(
                data_model.CombineArchiveContentFormatPattern.OMEX_METADATA.
                value, content.format)
        ]
        self.assertEqual(metadata_contents, [])

        self.assertEqual(
            sorted(os.listdir(out_dir)),
            sorted([
                content1.location,
                os.path.dirname(content2.location),
                'manifest.xml',
            ]))
        with open(os.path.join(out_dir, content1.location), 'r') as file:
            self.assertEqual('a', file.read())
        with open(os.path.join(out_dir, content2.location), 'r') as file:
            self.assertEqual('b', file.read())

        io.CombineArchiveWriter().run(archive2, in_dir, archive_file)
        archive2b = io.CombineArchiveReader().run(
            archive_file, out_dir2, include_omex_metadata_files=False)
        self.assertTrue(archive2.is_equal(archive2b))
        self.assertEqual(sorted(os.listdir(out_dir2)),
                         sorted([
                             content1.location,
                             'manifest.xml',
                         ]))
        with open(os.path.join(out_dir2, content1.location), 'r') as file:
            self.assertEqual('a', file.read())

        with self.assertRaisesRegex(ValueError, 'is not a file'):
            io.CombineArchiveReader().run(
                os.path.join(self.temp_dir, 'test2.omex'), out_dir)
    def test_write_error_handling(self):
        now = datetime.datetime(2020,
                                1,
                                2,
                                1,
                                2,
                                3,
                                tzinfo=dateutil.tz.tzutc())
        content = data_model.CombineArchiveContent('1.txt', 'plain/text',
                                                   False)
        with open(os.path.join(self.temp_dir, content.location), 'w') as file:
            pass
        archive = data_model.CombineArchive([content])

        archive_file = os.path.join(self.temp_dir, 'archive.omex')
        with self.assertRaisesRegex(Exception, 'could not be saved'):
            with mock.patch.object(libcombine.CombineArchive,
                                   'writeToFile',
                                   return_value=False):
                io.CombineArchiveWriter().run(archive, self.temp_dir,
                                              archive_file)

        with self.assertRaisesRegex(Exception,
                                    'could not be added to the archive'):
            with mock.patch.object(libcombine.CombineArchive,
                                   'addFile',
                                   return_value=False):
                io.CombineArchiveWriter().run(archive, self.temp_dir,
                                              archive_file)

        with self.assertRaisesRegex(ValueError, 'my error'):
            with mock.patch(
                    'biosimulators_utils.combine.io.get_combine_errors_warnings',
                    return_value=([['my error']], [])):
                io.CombineArchiveWriter().run(archive, self.temp_dir,
                                              archive_file)

        with self.assertWarnsRegex(BioSimulatorsWarning, 'my warning'):
            with mock.patch(
                    'biosimulators_utils.combine.io.get_combine_errors_warnings',
                    return_value=([], [['my warning']])):
                io.CombineArchiveWriter().run(archive, self.temp_dir,
                                              archive_file)

        archive_file = os.path.join(os.path.dirname(__file__), '..',
                                    'fixtures',
                                    'invalid-parent-format-in-manifest.omex')
        out_dir = os.path.join(self.temp_dir, 'out-1')
        with self.assertRaisesRegex(ValueError,
                                    'format of the archive must be'):
            io.CombineArchiveReader().run(archive_file,
                                          out_dir,
                                          include_omex_metadata_files=False)

        archive_file = os.path.join(os.path.dirname(__file__), '..',
                                    'fixtures',
                                    'missing-parent-in-manifest.omex')
        out_dir = os.path.join(self.temp_dir, 'out-2')
        with self.assertWarnsRegex(
                BioSimulatorsWarning,
                'Manifests should include their parent COMBINE/OMEX archives'):
            io.CombineArchiveReader().run(archive_file,
                                          out_dir,
                                          include_omex_metadata_files=False)