Files
Python/web_programming/search_books_by_isbn.py
priya-sundaram-devandpre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> bfa655ecea deps: migrate from httpx to httpx2 (pydantic's maintained fork) (#15192)
* deps: migrate from httpx to httpx2 (pydantic's maintained fork)

Mechanical rename of httpx -> httpx2 (API-compatible fork of httpx 0.28.1):
pyproject.toml deps, PEP 723 inline-script headers, and all import/call sites.
Excludes uv.lock (the keeper's allow-list rejects .lock files); the lock
refresh needs a separate maintainer-merged PR.

Refs #15081

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* deps: drop tweepy + migrate remaining requests refs to httpx2

- maths/allocation_number.py: docstring example uses httpx2, not requests
- web_programming/get_imdbtop.py.DISABLED: import httpx2 instead of requests
- remove web_programming/get_user_tweets.py.DISABLED (a Twitter API how-to,
  not an algorithm) and drop the tweepy dependency that was its only user and
  the last high-level dep pulling in requests
- uv.lock intentionally untouched (keeper allow-list)

Refs #15081

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2026-09-05 09:26:45 +02:00

83 lines
2.7 KiB
Python

"""
Get book and author data from https://openlibrary.org
ISBN: https://en.wikipedia.org/wiki/International_Standard_Book_Number
"""
# /// script
# requires-python = ">=3.13"
# dependencies = [
# "httpx2",
# ]
# ///
from json import JSONDecodeError
import httpx2
def get_openlibrary_data(olid: str = "isbn/0140328726") -> dict:
"""
Given an 'isbn/0140328726', return book data from Open Library as a Python dict.
Given an '/authors/OL34184A', return authors data as a Python dict.
This code must work for olids with or without a leading slash ('/').
# Comment out doctests if they take too long or have results that may change
# >>> get_openlibrary_data(olid='isbn/0140328726') # doctest: +ELLIPSIS
{'publishers': ['Puffin'], 'number_of_pages': 96, 'isbn_10': ['0140328726'], ...
# >>> get_openlibrary_data(olid='/authors/OL7353617A') # doctest: +ELLIPSIS
{'name': 'Adrian Brisku', 'created': {'type': '/type/datetime', ...
"""
new_olid = olid.strip().strip("/") # Remove leading/trailing whitespace & slashes
if new_olid.count("/") != 1:
msg = f"{olid} is not a valid Open Library olid"
raise ValueError(msg)
return httpx2.get(
f"https://openlibrary.org/{new_olid}.json", timeout=10, follow_redirects=True
).json()
def summarize_book(ol_book_data: dict) -> dict:
"""
Given Open Library book data, return a summary as a Python dict.
"""
desired_keys = {
"title": "Title",
"publish_date": "Publish date",
"authors": "Authors",
"number_of_pages": "Number of pages",
"isbn_10": "ISBN (10)",
"isbn_13": "ISBN (13)",
}
data = {better_key: ol_book_data[key] for key, better_key in desired_keys.items()}
data["Authors"] = [
get_openlibrary_data(author["key"])["name"] for author in data["Authors"]
]
for key, value in data.items():
if isinstance(value, list):
data[key] = ", ".join(value)
return data
if __name__ == "__main__":
import doctest
doctest.testmod()
while True:
isbn = input("\nEnter the ISBN code to search (or 'quit' to stop): ").strip()
if isbn.lower() in ("", "q", "quit", "exit", "stop"):
break
if len(isbn) not in (10, 13) or not isbn.isdigit():
print(f"Sorry, {isbn} is not a valid ISBN. Please, input a valid ISBN.")
continue
print(f"\nSearching Open Library for ISBN: {isbn}...\n")
try:
book_summary = summarize_book(get_openlibrary_data(f"isbn/{isbn}"))
print("\n".join(f"{key}: {value}" for key, value in book_summary.items()))
except JSONDecodeError:
print(f"Sorry, there are no results for ISBN: {isbn}.")