A simple Python wrapper for reading data from Discourse forums
Project description
discourse-reader
A typed, read-only Python client for the Discourse forum API.
Install
pip install discourse-reader
Quick start
from discourse_reader import DiscourseClient
client = DiscourseClient("https://meta.discourse.org")
# Browse categories
for cat in client.categories():
print(f"{cat.name}: {cat.topic_count} topics")
# Get a topic with all its posts
topic = client.topics.get(12345)
print(topic.title)
print(topic.opening_post.cooked) # the original post (HTML)
print(topic.accepted_answer) # accepted answer or None
for reply in topic.posts.replies():
print(reply.username, reply.cooked)
API
Site-level (flat on client)
client.about() # About
client.statistics() # SiteStatistics
client.categories() # list[Category]
client.tags() # list[TagDetail]
client.user("username") # User
client.search("query", limit=50) # Iterator[SearchPost]
Topics (client.topics)
client.topics.latest(limit=100) # Iterator[Topic]
client.topics.top(period="monthly") # Iterator[Topic]
client.topics.by_category(cat) # Iterator[Topic] (pass a Category)
client.topics.by_tag("tag-name") # Iterator[Topic]
client.topics.get(topic_id) # TopicResult
All listing methods are lazy iterators with optional limit.
TopicResult
topics.get() returns a TopicResult which delegates to TopicDetail for attributes like title, category_id, views, etc.
topic = client.topics.get(12345)
topic.title # str (delegated to TopicDetail)
topic.opening_post # Post -- the original post
topic.accepted_answer # Post | None
topic.detail # raw TopicDetail model
Posts (topic.posts)
Discourse delivers ~20 posts with the topic detail. The rest are fetched lazily in batches when you iterate.
topic.posts.all() # Iterator[Post] -- everything
topic.posts.replies() # Iterator[Post] -- everything except OP
len(topic.posts) # total post count
for post in topic.posts: # same as .all()
...
Single post
client.posts.get(post_id) # Post by global ID
Extra fields
All models use extra="allow" -- core fields are typed, plugin fields land in model_extra:
topic.detail.model_extra.get("accepted_answer") # solved plugin data
post.model_extra.get("accepted_answer") # per-post flag
Rate limiting
Default: 4 requests/second. Configurable via constructor. Automatic 429 retry with Retry-After.
client = DiscourseClient("https://...", requests_per_second=2) # slower
client = DiscourseClient("https://...", requests_per_second=None) # no limit
Development
uv sync
uv run pre-commit install
uv run pre-commit run --all-files
uv run pytest
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file discourse_reader-1.0.0.tar.gz.
File metadata
- Download URL: discourse_reader-1.0.0.tar.gz
- Upload date:
- Size: 38.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5e5893c0f7495217ced61f49d608327823af3343222b0b1d8fa329fe3359a3e6
|
|
| MD5 |
46c393042912f988e0fc438347f7d9b6
|
|
| BLAKE2b-256 |
c80b460fd52d8482468e684a1b617f1bf1c71f7df25b13a49e1ee3d828d77c38
|
Provenance
The following attestation bundles were made for discourse_reader-1.0.0.tar.gz:
Publisher:
publish.yml on elninotech/discourse-reader
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
discourse_reader-1.0.0.tar.gz -
Subject digest:
5e5893c0f7495217ced61f49d608327823af3343222b0b1d8fa329fe3359a3e6 - Sigstore transparency entry: 1318632583
- Sigstore integration time:
-
Permalink:
elninotech/discourse-reader@edaf00712ea4d0ab56a24e8ab57bf078f418574a -
Branch / Tag:
refs/tags/v1.0.0 - Owner: https://github.com/elninotech
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@edaf00712ea4d0ab56a24e8ab57bf078f418574a -
Trigger Event:
release
-
Statement type:
File details
Details for the file discourse_reader-1.0.0-py3-none-any.whl.
File metadata
- Download URL: discourse_reader-1.0.0-py3-none-any.whl
- Upload date:
- Size: 8.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
54064a139afca9a255cccda55540934a2f10d73658988b99fa676e25e82f890b
|
|
| MD5 |
cfa29d1fc96c117496a73952f299960b
|
|
| BLAKE2b-256 |
00ccab1f423b8a93a8426f509528a61d1a70d2e224467536c5f254ccbb1686a8
|
Provenance
The following attestation bundles were made for discourse_reader-1.0.0-py3-none-any.whl:
Publisher:
publish.yml on elninotech/discourse-reader
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
discourse_reader-1.0.0-py3-none-any.whl -
Subject digest:
54064a139afca9a255cccda55540934a2f10d73658988b99fa676e25e82f890b - Sigstore transparency entry: 1318632652
- Sigstore integration time:
-
Permalink:
elninotech/discourse-reader@edaf00712ea4d0ab56a24e8ab57bf078f418574a -
Branch / Tag:
refs/tags/v1.0.0 - Owner: https://github.com/elninotech
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@edaf00712ea4d0ab56a24e8ab57bf078f418574a -
Trigger Event:
release
-
Statement type: