Image

death and gravity: reader 3.20 released – we're so back

Hi there!

I'm happy to announce version 3.20 ofreader, a Python feed reader library.

What's new? #

Here are the highlights sincereader 3.16.

Web app re-design #

Earlier this year, I started a web appre-designbased onhtmxandBootstrap. I only had time for the main page, but it turned out pretty nice, and I've been using it ever since. What isnewis that I now have free time and some plans;watch this space.

Here are some screenshots; it's not much, but it's honest work:

htmx? ugh, how original

Unsurprisingly, htmx is perfect for this kind of application. As CEO of htmx, I can confirm that all the allegations are true – it is indeed a pleasure to use, not to mention a huge improvement over my home-grown, half-assed JavaScript formsframework.

isn't Bootstrap from like 2010 or something? also, how original

I've tried many modern popular CSS frameworks (since forgotten, for my own sanity), and it turns out tab-navigable form controls are a hard, unsolved problem in 2025. Thankfully, if you're willing to time travel (to the future, surely!), Bootstrap comes with excellent documentation, built-in accessibility, and a comprehensive component library.

Entry deduplication #

I may have accidentally rewritten theentry_dedupeplugin. 😅

Sometimes, the id of some or all the entries in a feed changes (e.g. fromexample.com/123toexample.com/entry-title), causing each entry to appear twice.entry_dedupefixes this by copying user attributes to the new entry and deleting the old one.

What started as a quick and dirty plugin now has:

  • lots of new,data-drivenheuristics to find potential duplicates
    • by title (had this one already)
    • by link
    • by published timestamp
    • by title with common prefixes removed
  • better approximate content matching
  • an extensive test suite
  • extensive internal documentation (like this)

That last one is pretty important: the old logic was data-driven too, but because I didn't document myentirereasoning, I wasted more time than I'd like to admit on a useless title similarity heuristic. It's a trope that you should write code such that others can understand it, and "others" includes you six months from now; I don't know about six months, but four years will definitely do it. (If that sounds like an interesting story and you'd like to hear more,drop me a line.)

It's not all bad, though – a side-effect of better content matching is that imagealtandtitleattributes are also included in thefull-text searchindex now, so you can search xkcd comics by title text.

Project infrastructure #

I've taken some time to modernize the project infrastructure; stuff like:

  • Use GitHub Actions to publish releases to PyPI.
  • Use dependency groups instead of extras for development dependencies.
  • Rewritecontributor documentationandrun.shto optimize for readability.

(I'll admit theuvhype is quite strong, but the vanilla tooling seems fine, for now.)

Read-only Reader #

It's now possible to prevent write operations on aReaderobject through theread_onlymake_reader()argument. Thanks to Roman Milko for the pull request!

Python versions #

reader3.17 added support for PyPy 3.11.

reader3.18 dropped support for Python 3.10.

reader3.19 added support for Python 3.14.


That's it for now. For more details, see the fullchangelog.

Want to contribute?Check out thedocsand theroadmap.

Learned something new today?Share it with others, it really helps!PyCoder's WeeklyHNBlueskylinkedinTwitter

What isreader#

readertakes care of the core functionality required by a feed reader, so you can focus on what makesyoursdifferent.

reader in action
reader in action

readerallows you to:

  • retrieve, store, and manageAtom,RSS, andJSONfeeds
  • mark articles as read or important
  • add arbitrary tags/metadata to feeds and articles
  • filter feeds and articles
  • full-text search articles
  • get statistics on feed and user activity
  • write plugins to extend its functionality

...all these with:

  • a stable, clearly documented API
  • excellent test coverage
  • fully typed Python

To find out more, check out theGitHub repoand thedocs, or give thetutoriala try.

Why use a feed reader library? #

Have you been unhappy with existing feed readers and wanted to make your own, but:

  • never knew where to start?
  • it seemed like too much work?
  • you don't like writing backend code?

Are you already working withfeedparser, but:

  • want an easier way to store, filter, sort and search feeds and entries?
  • want to get back type-annotated objects instead of dicts?
  • want to restrict or deny file-system access?
  • want to change the way feeds are retrieved by usingRequests?
  • want to also supportJSON Feed?
  • want to support custom information sources?

... while still supporting all the feed types feedparser does?

If you answered yes to any of the above,readercan help.

Thereaderphilosophy #

  • readeris a library
  • readeris for the long term
  • readeris extensible
  • readeris stable (within reason)
  • readeris simple to use; API matters
  • readerfeatures work well together
  • readeris tested
  • readeris documented
  • readerhas minimal dependencies

Why make your own feed reader? #

So you can:

  • have full control over your data
  • control what features it has or doesn't have
  • decide how much you pay for it
  • make sure it doesn't get closed while you're still using it
  • really, it'seasier than you think

Obviously, this may not be your cup of tea, but if it is,readercan help.

https://death.andgravity.com/reader-3-20