'Generate a list of books sorted by author.
For books with multiple authors, relist book with additional authors.
Sort the database by author. Report author_sort inconsistencies as warning when
building EPUB or MOBI, error when building MOBI. Collect a list of unique authors
to self.authors.
Inputs:
self.books_to_catalog (list): database, sorted by title
Outputs:
books_by_author: database, sorted by author
authors: list of book authors. Two credited authors are considered an
individual entity
error: author_sort mismatches
Return:
True: no errors
False: author_sort mismatch detected while building MOBI'

def fetch_books_by_author(self):

    self.update_progress_full_step(_('Sorting    database'))
    books_by_author = list(self.books_to_catalog)
    self.detect_author_sort_mismatches(books_by_author)
    if self.opts.generate_descriptions:
        books_by_description = (list(books_by_author) if self.opts.sort_descriptions_by_author else list(self.books_by_title))
    if self.opts.cross_reference_authors:
        books_by_author = self.relist_multiple_authors(books_by_author)
    asl = [i['author_sort'] for i in books_by_author]
    las = max(asl, key=len)
    if self.opts.generate_descriptions:
        self.books_by_description = sorted(books_by_description, key=(lambda x: sort_key(self._kf_books_by_author_sorter_author_sort(x, len(las)))))
    books_by_author = sorted(books_by_author, key=(lambda x: sort_key(self._kf_books_by_author_sorter_author_sort(x, len(las)))))
    if (self.DEBUG and self.opts.verbose):
        tl = [i['title'] for i in books_by_author]
        lt = max(tl, key=len)
        fs = ('{:<6}{:<%d}    {:<%d}    {!s}' % (len(lt), len(las)))
        print fs.format('', 'Title', 'Author', 'Series')
        for i in books_by_author:
            print fs.format('', i['title'], i['author_sort'], i['series'])
    authors = [(record['author'], capitalize(record['author_sort'])) for record in books_by_author]
    books_by_current_author = 0
    current_author = authors[0]
    multiple_authors = False
    unique_authors = []
    individual_authors = set()
    for (i, author) in enumerate(authors):
        if (author != current_author):
            multiple_authors = True
            unique_authors.append((current_author[0], icu_title(current_author[1]), books_by_current_author))
            current_author = author
            books_by_current_author = 1
        elif ((i == 0) and (len(authors) == 1)):
            unique_authors.append((current_author[0], icu_title(current_author[1]), books_by_current_author))
        else:
            books_by_current_author += 1
    else:
        if (((current_author == author) and (len(authors) > 1)) or (not multiple_authors)):
            unique_authors.append((current_author[0], icu_title(current_author[1]), books_by_current_author))
    self.authors = list(unique_authors)
    self.books_by_author = books_by_author
    for ua in unique_authors:
        for ia in ua[0].replace('    &amp;    ', '    &    ').split('    &    '):
            individual_authors.add(ia)
    self.individual_authors = list(individual_authors)
    if (self.DEBUG and self.opts.verbose):
        self.opts.log.info(('\nfetch_books_by_author():    %d    unique    authors' % len(unique_authors)))
        for author in unique_authors:
            self.opts.log.info((u'    %-50s    %-25s    %2d' % (author[0][0:45], author[1][0:20], author[2])).encode('utf-8'))
        self.opts.log.info(('\nfetch_books_by_author():    %d    individual    authors' % len(individual_authors)))
        for author in sorted(individual_authors):
            self.opts.log.info(('%s' % author))
    return True
