Changelog

v0.3.2

Released 2026-03-02

Fixes

  • Sphinx docs — add source_suffix to conf.py so all .md pages are built; remove conflicting index.md that was shadowing index.rst and causing all toctrees to be ignored.

  • Docstrings — add explicit .. code-block:: python to all Example: sections; Napoleon does not wrap section content in literal blocks, causing for x: and if x: to be misinterpreted as RST definition list terms.

  • PyPI metadata — add keywords and classifiers; point Documentation and Changelog URLs to /en/stable/.

  • README — rewritten for v0.3.x multi-source API; adds Unsplash and Reddit examples, source-agnostic protocol usage, and updated badges.


v0.3.0

Released 2026-03-01

New features

  • Reddit sourceReddit and AsyncReddit clients for subreddit media feeds via the Reddit OAuth2 API.

    • iter_media(RedditParams) — iterate images, videos, and GIFs from any subreddit with automatic pagination.

    • aiter_media(RedditParams) — async equivalent.

    • download(post, path=None) — fetch image or video bytes; video posts download the MP4 fallback stream.

    • Gallery post expansion — gallery posts are automatically expanded into individual RedditPost objects.

    • RedditParams — filter by subreddit, sort, time_filter, limit, media_type, and include_nsfw.

    • OAuth2 client_credentials flow — tokens cached and auto-refreshed transparently.

    • REDDIT_CLIENT_ID, REDDIT_CLIENT_SECRET, REDDIT_USER_AGENT environment variable support.

  • MediaType enum — shared IMAGE, VIDEO, GIF, ANY filter across all sources. Importable from xanax.enums.

  • xanax._internal package — internal shared infrastructure (RateLimitHandler, MediaType) decoupled from source packages.

Breaking changes

  • Renamed clientsXanaxWallhaven, AsyncXanaxAsyncWallhaven. Backwards-compatible aliases Xanax and AsyncXanax are retained for one major version.

  • Restructured source packages — Wallhaven code moved from root (xanax.client, xanax.models, etc.) into xanax.sources.wallhaven.*. All public symbols remain importable from xanax directly.

  • Renamed iterator methodsiter_wallpapersiter_media, aiter_wallpapersaiter_media on all clients. Old names removed.

  • Renamed protocolsWallpaperSourceMediaSource, AsyncWallpaperSourceAsyncMediaSource in xanax.sources._base.

  • Docs migrated to Sphinx + Furomkdocs.yml removed; docs/conf.py and docs/index.rst added.

Migration guide

Rename client classes and iterator methods as described in the breaking changes above.


v0.2.1

Released 2026-03-01

New features

  • Multi-source architecturexanax.sources package introduces the MediaSource and AsyncMediaSource protocols. Any source client satisfying download() and iter_media() fits the protocol, enabling interchangeable source-agnostic code.

  • Unsplash sourceUnsplash and AsyncUnsplash clients for royalty-free photography via the Unsplash API v1.

    • search(UnsplashSearchParams) — search by query with orientation, color, order, per-page, and content-filter options.

    • photo(id) — fetch a full photo object (includes EXIF, location, tags).

    • random(params=None) — retrieve a single random photo, optionally filtered by collection, topic, username, query, or orientation.

    • download(photo, path=None) — two-step download: triggers attribution tracking at download_location (required by Unsplash ToS), then fetches image bytes from the CDN.

    • iter_pages(params) / iter_media(params) — auto-paginating generators.

    • aiter_pages(params) / aiter_media(params) — async equivalents.

  • Access key resolutionUNSPLASH_ACCESS_KEY environment variable, mirroring the existing WALLHAVEN_API_KEY pattern.

  • UnsplashPhoto.resolution and UnsplashPhoto.aspect_ratio — convenience properties matching the Wallhaven Wallpaper model’s interface.

  • Retry on 429Unsplash/AsyncUnsplash reuse RateLimitHandler for configurable exponential backoff.


v0.2.0

Released 2026-02-28

New features

  • AsyncWallhaven — a complete async client mirroring Wallhaven, built on httpx.AsyncClient. Supports async with, await, and async generators.

  • iter_pages(params) / aiter_pages(params) — generators that auto-paginate, yielding each SearchResult page.

  • iter_media(params) / aiter_media(params) — convenience generators that flatten pages into individual Wallpaper objects.

  • client.download(wallpaper, path=None) — fetch raw image bytes and optionally save to disk. Available on both sync and async clients.

  • WALLHAVEN_API_KEY environment variable — both clients now pick up the API key from the environment automatically.

  • AsyncWallhaven exported from the top-level xanax package.

  • Avatar and QueryInfo added to the public API exports (they existed as models but weren’t importable from xanax directly).

Bug fixes

  • Double auth header — the API key was previously sent in both the X-API-Key header and as an apikey query parameter on every request. It is now sent in the header only.

  • Default categoriesSearchParams previously defaulted to [Category.GENERAL] only, silently excluding anime and people wallpapers. The default is now all three categories, matching Wallhaven’s actual default.

  • with_page() / with_seed() — these methods previously manually enumerated all fields, meaning any newly added field would silently be dropped in the copy. Both now use model_dump() internally and are future-proof.

  • Collection.public — changed from int to bool. The API returns 0/1; Pydantic coerces this cleanly.

Removed

  • get_query_params() from AuthHandler — it was a redundant method that caused the API key double-send.

  • Module-level has_next_page(), get_next_page(), get_total_pages() from pagination.py — they duplicated PaginationHelper and weren’t part of the public API.


v0.1.1

Released 2025

  • Version metadata fix.

v0.1.0

Released 2025

  • Initial release: synchronous Wallhaven client with search, wallpaper, tag, settings, and collection endpoints.

  • Pydantic v2 models for all responses.

  • Type-safe SearchParams with pre-flight validation.

  • PaginationHelper for manual pagination.

  • Structured exception hierarchy.