Пример #1
0
def graph_series(
    gc: GoodreadsClient,
    url: str,
    cut_off: int,
    prompt_new_cutoff: bool,
    sort_by_rating: bool,
):
    """
    Generate a graph of an series' books where average rating is on the y axis and
    the x axis has each book on a scatter plot. Hover over a point to see the book's
    title.

    :param gc: GoodreadsClient
    :param url: str, url containing a series id
    :param cut_off: int, where to cut the graph off
    :param prompt_new_cutoff: bool, whether to prompt for a new cutoff
    :param sort_by_rating: bool, whether to sort the graph by rating descending
    """
    series_id = series_url_to_series_id(url)
    resp = gc.request("series/show", {"id": series_id, "page": 1})
    series_work = resp["series"]["series_works"]["series_work"]
    total = int(resp["series"]["series_works_count"])
    pages = math.ceil(int(total) / DEFAULT_SERIES_BOOKS_PER_PAGE) + 1
    if pages > 1:
        series_work.extend(
            list(
                itertools.chain(*[
                    gc.request("series/show", {
                        "id": series_id,
                        "page": p
                    })["series"]["series_works"]["series_work"]
                    for p in range(2, pages)
                ])))
    series_books = [{
        **work["work"],
        **work["work"]["best_book"],
        "user_position":
        work["user_position"],
    } for work in series_work]
    for i, book in enumerate(series_books):
        del series_books[i]["best_book"]
    series_df = pd.DataFrame(series_books)
    series_df.ratings_sum = series_df.ratings_sum.astype(int)
    series_df.ratings_count = series_df.ratings_count.astype(int)
    series_df.average_rating = series_df.ratings_sum / series_df.ratings_count
    while True:
        if sort_by_rating:
            graph_series_sort_by_average_rating(series_df, cut_off)
        else:
            graph_avg_rating_by_series_order(series_df, cut_off)
        if prompt_new_cutoff:
            NEW_CUT_OFF = int(
                input("New cut off number (Enter to cancel):") or 0)
            if NEW_CUT_OFF == 0:
                break
            else:
                cut_off = NEW_CUT_OFF
        else:
            break
Пример #2
0
    def test_author(self, mock_request):
        client = GoodreadsClient("GOODREADS_KEY", "GOODREADS_SECRET")

        # Goodreads Author data pulled for Jeannette Ng on 2019-04-05. Lightly modified for testing purposes
        with open("tests/unit/fixtures/author.json") as f:
            author_response = f.read()
        mock_request.return_value = json.loads(author_response)
        return client.author(14880958)
Пример #3
0
    def test_review(self, mock_request):
        client = GoodreadsClient("GOODREADS_KEY", "GOODREADS_SECRET")

        # Goodreads Group data pulled on 2019-04-09. Lightly modified for testing purposes
        with open("tests/unit/fixtures/review.json") as f:
            review_response = f.read()
            mock_request.return_value = json.loads(review_response)
        return client.review(12345)
Пример #4
0
    def test_author_with_one_book(self, mock_request):
        client = GoodreadsClient("GOODREADS_KEY", "GOODREADS_SECRET")

        # Goodreads Author data pulled for IACA on 2019-04-05. Lightly modified for testing purposes
        with open("tests/unit/fixtures/author_one_book.json") as f:
            author_response = f.read()
        mock_request.return_value = json.loads(author_response)
        books = client.author(5734084).books
        assert len(books) == 1
Пример #5
0
 def test_owned_book(self):
     client = GoodreadsClient("GOODREADS_KEY", "GOODREADS_SECRET")
     with mock.patch("betterreads.client.GoodreadsSession") as mock_session:
         client.session = mock_session
         with open("tests/unit/fixtures/owned_book.json") as f:
             owned_book_response = f.read()
             client.session.get.return_value = json.loads(
                 owned_book_response)
         return client.owned_book(49488032)
Пример #6
0
    def test_many_authors(self, mock_request):
        client = GoodreadsClient("GOODREADS_KEY", "GOODREADS_SECRET")

        # Goodreads Book data - Practical Data Science with R as of 2019-04-05. Lightly modified for testing purposes.
        with open("tests/unit/fixtures/book_multiple_authors.json") as f:
            book_response = f.read()
        mock_request.return_value = json.loads(book_response)

        book = client.book(18774683)
        assert len(book.authors) == 2
        assert isinstance(book.authors[0], GoodreadsAuthor)
Пример #7
0
def main() -> None:
    args = parse_args()
    gc = GoodreadsClient(client_key=args.client_key,
                         client_secret=args.client_secret)
    if args.series:
        for url in args.urls:
            graph_series(gc, url, args.cut_off, args.prompt_new_cutoff,
                         args.sort_by_rating)
            if args.prompt_more_urls:
                while True:
                    raw_urls = input(
                        "Enter some more urls separated by spaces (Enter to cancel): "
                    )
                    if raw_urls != "":
                        urls = raw_urls.split(" ")
                        for url in urls:
                            graph_series(
                                gc,
                                url,
                                args.cut_off,
                                args.prompt_new_cutoff,
                                args.sort_by_rating,
                            )
                    else:
                        break

    if args.author:
        for url in args.urls:
            graph_author(
                gc,
                url,
                args.cut_off,
                args.prompt_new_cutoff,
                args.sort_by_rating,
                args.min_num_ratings,
            )
        if args.prompt_more_urls:
            while True:
                raw_urls = input(
                    "Enter some more urls separated by spaces (Enter to cancel): "
                )
                if raw_urls != "":
                    urls = raw_urls.split(" ")
                    for url in urls:
                        graph_author(
                            gc,
                            url,
                            args.cut_off,
                            args.prompt_new_cutoff,
                            args.sort_by_rating,
                            args.min_num_ratings,
                        )
                else:
                    break
Пример #8
0
def author_books_total_pages(gc: GoodreadsClient, author_id: int) -> int:
    """
    Get the total of pages for an author's books, sorted by popularity on Goodreads.

    :param gc: GoodReadsClient
    :param author_id: int, id of an author
    :return: int, number of pages
    """
    resp = gc.request("author/list", {"id": author_id})
    total = int(resp["author"]["books"]["@total"])
    return math.ceil(int(total) / DEFAULT_AUTHOR_BOOKS_PER_PAGE) + 1
Пример #9
0
def author_books_for_page(gc: GoodreadsClient, author_id: int,
                          page: int) -> List[GoodreadsBook]:
    """
    Get the books for an author, sorted by popularity on Goodreads at a particular page.

    :param gc: GoodReadsClient
    :param author_id: int, id of an author
    :param page: int, page number to fetch
    :return List[GoodReadsBook]
    """
    return [
        GoodreadsBook({
            **book, "id": int(book["id"]["#text"])
        }, gc) for book in (gc.request("author/list", {
            "id": author_id,
            "page": page
        })["author"]["books"]["book"])
    ]
Пример #10
0
 def test_comment_list(self, mock_request):
     client = GoodreadsClient("GOODREADS_KEY", "GOODREADS_SECRET")
     with open("tests/unit/fixtures/comment.json") as f:
         comment_response = f.read()
         mock_request.return_value = json.loads(comment_response)
     return client.list_comments("user", 1)
Пример #11
0
 def test_book(self, mock_request):
     client = GoodreadsClient("GOODREADS_KEY", "GOODREADS_SECRET")
     with open("tests/unit/fixtures/book.json") as f:
         book_response = f.read()
         mock_request.return_value = json.loads(book_response)
     return client.book(39721925)
Пример #12
0
 def test_client_fixture(self):
     return GoodreadsClient(os.environ.get("GOODREADS_KEY"),
                            os.environ.get("GOODREADS_SECRET"))