'Add the specified books to the library. Books should be an iterable of
2-tuples, each 2-tuple of the form :code:`(mi, format_map)` where mi is a
Metadata object and format_map is a dictionary of the form :code:`{fmt: path_or_stream}`,
for example: :code:`{\'EPUB\': \'/path/to/file.epub\'}`.
Returns a pair of lists: :code:`ids, duplicates`. ``ids`` contains the book ids for all newly created books in the
database. ``duplicates`` contains the :code:`(mi, format_map)` for all books that already exist in the database
as per the simple duplicate detection heuristic used by :meth:`has_book`.'

@api
def add_books(self, books, add_duplicates=True, apply_import_tags=True, preserve_uuid=False, run_hooks=True, dbapi=None):

    (duplicates, ids) = ([], [])
    fmt_map = {}
    for (mi, format_map) in books:
        book_id = self.create_book_entry(mi, add_duplicates=add_duplicates, apply_import_tags=apply_import_tags, preserve_uuid=preserve_uuid)
        if (book_id is None):
            duplicates.append((mi, format_map))
        else:
            ids.append(book_id)
            for (fmt, stream_or_path) in format_map.iteritems():
                if self.add_format(book_id, fmt, stream_or_path, dbapi=dbapi, run_hooks=run_hooks):
                    fmt_map[fmt.lower()] = (getattr(stream_or_path, u'name', stream_or_path) or u'<stream>')
        run_plugins_on_postadd((dbapi or self), book_id, fmt_map)
    return (ids, duplicates)
