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
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)
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)
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
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)
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)
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
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
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"]) ]
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)
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)
def test_client_fixture(self): return GoodreadsClient(os.environ.get("GOODREADS_KEY"), os.environ.get("GOODREADS_SECRET"))