Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
95 commits
Select commit Hold shift + click to select a range
a99a11d
new config value 'feed_field_name'
lsaffre Aug 1, 2016
2c618e1
avoid problem when bibtex extension is also installed
lsaffre Feb 5, 2018
b76b753
http://luc.lino-framework.org/blog/2018/0902.html
lsaffre Sep 2, 2018
b0d97dc
http://luc.lino-framework.org/blog/2018/0902.html
lsaffre Sep 2, 2018
c3c85dd
http://luc.lino-framework.org/blog/2018/0911.html
lsaffre Sep 11, 2018
35b2d4a
http://luc.lino-framework.org/blog/2018/0913.html
lsaffre Sep 13, 2018
d98823b
http://luc.lino-framework.org/blog/2018/0913.html
lsaffre Sep 13, 2018
6fcfbba
http://luc.lino-framework.org/blog/2018/0913.html
lsaffre Sep 13, 2018
f4d1106
http://luc.lino-framework.org/blog/2018/0917.html
lsaffre Sep 17, 2018
bd7c487
adapted to Sphinx 1.8.1
lsaffre Nov 4, 2018
59e0d7f
http://luc.lino-framework.org/blog/2019/0121.html
lsaffre Jan 21, 2019
1541cff
http://luc.lino-framework.org/blog/2019/0121.html
lsaffre Jan 21, 2019
8def303
http://luc.lino-framework.org/blog/2019/0315.html
lsaffre Mar 15, 2019
edd05bb
http://luc.lino-framework.org/blog/2019/0315.html
lsaffre Mar 15, 2019
6e5bcbd
http://luc.lino-framework.org/blog/2019/0326.html
lsaffre Mar 26, 2019
0dc0fc0
http://luc.lino-framework.org/blog/2019/0409.html
lsaffre Apr 9, 2019
fc15b97
Adapt to new Sphinx version
lsaffre Jun 11, 2019
0af23b4
http://luc.lino-framework.org/blog/2019/0701.html
lsaffre Jul 1, 2019
357f0df
Sphinx version 2.2 is out
lsaffre Sep 19, 2019
f3000b0
pubDate now localtime()
lsaffre Mar 7, 2020
354c941
adapted tests to new sphinx version
lsaffre Apr 21, 2020
0a0ffe3
adapt tests to Sphinx 3.0.3
lsaffre Apr 30, 2020
3256f7b
adapt tests to new Sphinx version number
lsaffre Aug 25, 2020
b12851a
adapt test to new sphinx version
lsaffre Jan 3, 2021
94efdce
adapt for sphinx 3.4.2
lsaffre Jan 5, 2021
89893ad
fix redirected urls
lsaffre Apr 25, 2021
4f1ac13
adapt to new Sphinx version
lsaffre Jun 13, 2021
4389e54
sphinxconf moved from atelier to rstgen
lsaffre May 24, 2022
54fb10a
respect use_dirhtml option from rstgen when calculating the url
lsaffre Jul 10, 2022
1f00ad0
optimize docs
lsaffre Jul 10, 2022
26ce810
adapt test suite to new Sphinx version
lsaffre Sep 6, 2022
5bec28e
adapt to Sphinx 5.3.0
lsaffre Feb 19, 2023
c0c5665
adapted to new Sphinx version
lsaffre Oct 11, 2023
b34b5fd
support the newest Sphinx version
lsaffre Dec 16, 2023
04a7333
code reformatted using yapf
lsaffre Feb 14, 2024
7f5d43d
adapt to new sphinx version
lsaffre Apr 22, 2024
52af67c
add support for ATOM (a quick draft implementation)
lsaffre May 30, 2024
cb99077
changelog
lsaffre May 30, 2024
ec045ab
Add 'category' and 'tags' metadata fields.
lsaffre Jun 1, 2024
67ed894
Log warning instead of exception
JWCook Jul 16, 2024
07ae7ff
Handle author str (if taken from frontmatter) and tags list (produced…
JWCook Jul 16, 2024
3554db9
Generate atom feed with a config option instead of a constant
JWCook Jul 16, 2024
107f41a
Use sphinx config instead of rstgen to get 'use_dirhtml' setting
JWCook Jul 16, 2024
ba688e3
Use Sphinx logging to use correct namespace (sphinx.sphinxfeed)
JWCook Jul 17, 2024
77b3b45
Update expected test output for Sphinx 7.4 and docutils 0.21
JWCook Jul 17, 2024
8d229ee
Add fixed edge cases to test input
JWCook Jul 17, 2024
0f9f9f2
Merge pull request #1 from JWCook/dev
lsaffre Jul 18, 2024
7c47e8b
Update the README file.
lsaffre Jul 18, 2024
6c5222c
Update the README file (continued)
lsaffre Jul 18, 2024
99ebad2
Replace setup.py by pyproject.toml. Release to PyPI.
lsaffre Jul 19, 2024
55571c7
Explicitly include sphinxfeed.py in wheel
JWCook Jul 19, 2024
b602792
Add dev dependencies and minimum python version
JWCook Jul 19, 2024
19152e2
Add minimal GitHub Actions config to publish to PyPI using trusted pu…
JWCook Jul 19, 2024
836e126
Run tests in CI (currently expected to fail)
JWCook Jul 19, 2024
6331a4d
Merge pull request #4 from JWCook/build-config
lsaffre Jul 20, 2024
876f6e3
Merge branch 'master' into ci
lsaffre Jul 20, 2024
7aa3bc3
Merge pull request #5 from JWCook/ci
lsaffre Jul 20, 2024
9e5e970
log future posts as info, not as warning
lsaffre Jul 20, 2024
0a79477
Remove dependency from atelier
lsaffre Jul 20, 2024
a50e790
Update CHANGELOG and README
lsaffre Jul 20, 2024
2cb5c4e
Fix indentation
lsaffre Jul 20, 2024
3c8d846
release to pypi
lsaffre Jul 20, 2024
633345a
release to pypi
lsaffre Jul 21, 2024
c323b4f
Optimize release instructions
lsaffre Jul 21, 2024
894ccc3
Add PyPI badges to Readme
JWCook Jul 21, 2024
fbc5ba0
Add package metadata for supported python versions
JWCook Jul 21, 2024
8ff80db
Use dateutil.parser instead of time.strptime
JWCook Jul 21, 2024
ca05df0
Use timezone if explicitly provided in timestamp
JWCook Jul 21, 2024
18603c7
Remove additional unused code
JWCook Jul 21, 2024
efbb0ec
Update tests
JWCook Jul 21, 2024
a339c55
Update changelog
JWCook Jul 21, 2024
afe4b52
Merge pull request #7 from JWCook/readme
lsaffre Jul 22, 2024
9d9bb30
Merge pull request #8 from JWCook/dateutil
lsaffre Jul 22, 2024
30299b0
Run tests using SphinxTestApp, and parse test output to compare indiv…
JWCook Jul 21, 2024
740ff87
Add test for Atom feeds
JWCook Jul 21, 2024
10d6e61
Handle more edge cases and improve output for attribute comparison
JWCook Jul 21, 2024
7d25104
Report test status in CI
JWCook Jul 21, 2024
8b5e4a3
Add coverage report config with pytest-cov
JWCook Jul 22, 2024
4fd3e7f
Compatibility changes for python 3.8 and Sphinx <=7.1
JWCook Jul 22, 2024
6f846cb
Patch pathlib.Path instead of using (now deprecated) sphinx.testing.path
JWCook Jul 22, 2024
0dbdc75
Mock local timezone in tests so output timestamps are consistent
JWCook Jul 22, 2024
da3d529
Add some missing test coverage
JWCook Jul 22, 2024
f3fcf6a
Merge pull request #9 from JWCook/tests
lsaffre Jul 23, 2024
f747b2a
Add feed_entry_permalink option to toggle setting FeedEntry.guid
JWCook Jul 28, 2024
d611ad1
Update tests and docs
JWCook Jul 28, 2024
94dcaa3
Merge pull request #10 from JWCook/permalink
lsaffre Jul 29, 2024
1f62973
release to pypi
lsaffre Jul 29, 2024
e35413a
Add missing git commit -a in release instructions.
lsaffre Jul 29, 2024
60976d0
Add documentation from PR comment.
lsaffre Jul 29, 2024
2b4dfb9
fix inv test fails with NO TESTS RAN
lsaffre Mar 28, 2025
83a2f5e
Add urn:uuid: prefix to UUIDs for Atom <id>
JWCook Mar 25, 2026
cc45952
Run tests with and without feed_entry_permalink
JWCook Mar 25, 2026
cae1f71
Run tests in CI for python 3.13 and 3.14
JWCook Mar 25, 2026
3b5799c
Handle trailing slashes in feed_base_url
JWCook Mar 25, 2026
099f1f1
Merge pull request #12 from JWCook/validation-fixes
lsaffre Mar 26, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 48 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
name: Test & Publish

on:
push:
branches: [master]
tags: ['v*']
pull_request:
branches: [master]

jobs:
# For all PRs and commits to main, run tests for each supported python version
# Note: This is currently expected to fail due to output variations based on
# dependency versions
test:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
python-version: ['3.8', '3.9', '3.10', '3.11', '3.12', '3.13', '3.14']
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: |
pip install -U pip setuptools
pip install -e .[dev]
- name: Run tests
run: pytest -vs tests

# For git tags, build and publish package to PyPI
publish:
if: ${{ startsWith(github.ref, 'refs/tags/') }}
runs-on: ubuntu-latest
permissions:
id-token: write
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.12'
- name: Build package distributions
run: |
pip install hatch
hatch build
- name: Publish package distributions to PyPI
uses: pypa/gh-action-pypi-publish@release/v1
12 changes: 12 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# use glob syntax.
syntax: glob

*.pyc
*~
*.egg-info
.build
.coverage
.eggs
tmp
.doctrees
dist
47 changes: 47 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
========================
The sphinxfeed changelog
========================

- 20190315 : Support Python 3 (by using feedgen instead of feedformatter).
feed_description is no longer optional.

- new config variable ``feed_field_name`` to change the name of the
metadata field to use for specifying the publication date.
- don't publish items whose publication datetime is in the future.
- respect `use_dirhtml` option from `rstgen` when calculating the url
- 20240530 : add support to write
`ATOM <https://validator.w3.org/feed/docs/atom.html>`__ instead of RSS.

- 20240601 : look for two new fields ``category`` and ``tags`` in the `page
metadata
<https://www.sphinx-doc.org/en/master/usage/restructuredtext/field-lists.html>`__
and if either field or both is present, call the
`feedgen.FeedEntry.category()` method to add ``<category>`` elements to the
feed item. The difference between ``category`` and ``tags`` is that the
``category`` of a blog post may contain whitespace while the ``tags`` metadata
field is a space-separated list of tags, so each tag must be a single word.
Both the category and each tag will become a ``<category>`` element in the
feed item.

- 20240718 : merged 7 commits with minor fixes and config updates from `pull
request suggested by JWCook <https://github.com/lsaffre/sphinxfeed/pull/1>`__

- 20240720 : The message "Skipping %s, publish date is in the future" is now
logged at level INFO instead of WARNING because we don't want the
``sphinx-build -W`` to fail in this situation.

- 20240720 : Removed dependency from ``atelier`` because it's easier to call
`subprocess.check_output()` directly here.

- 20240722 : Support additional timestamp formats (any format supported by
`dateutil <https://dateutil.readthedocs.io/en/stable/examples.html#parse-examples>`__)

- 20240728: Add ``feed_entry_permalink`` option to set a permalink GUID for each
feed entry. If a `guid` value is found in the metadata, that will be used;
otherwise, a new one will be generated based on the entry URL.
Defaults to ``False``, in which case the entry URL will be used as a
non-permalink ID. Applies to both Atom and RSS feeds.

- 20260325: Add `urn:uuid:` prefix to permalink GUIDs so they validate as a full URL.

- 20260325: Handle trailing slashes in feed_base_url
23 changes: 23 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
Copyright 2011 Fergus Doyle <fergus.doyle@largeblue.com>
Copyright 2016-2024 Rumma & Ko Ltd <info@saffre-rumma.net>

Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.

2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
143 changes: 129 additions & 14 deletions README.rst
Original file line number Diff line number Diff line change
@@ -1,25 +1,140 @@
sphinxfeed
==========
==========================
The ``sphinxfeed`` package
==========================
.. image:: https://img.shields.io/github/actions/workflow/status/lsaffre/sphinxfeed/build.yml
:alt: Build status
:target: https://github.com/lsaffre/sphinxfeed/actions
.. image:: https://img.shields.io/pypi/v/sphinxfeed-lsaffre?color=blue
:alt: PyPI - package version
:target: https://pypi.org/project/sphinxfeed-lsaffre
.. image:: https://img.shields.io/pypi/pyversions/sphinxfeed-lsaffre
:alt: PyPI - supported python versions
:target: https://pypi.org/project/sphinxfeed-lsaffre

This Sphinx extension is derived from Dan Mackinlay's `sphinxcontrib.feed
<http://bitbucket.org/birkenfeld/sphinx-contrib/src/tip/feed/>`_ package.
This Sphinx extension is a fork of Fergus Doyle's `sphinxfeed package
<https://github.com/junkafarian/sphinxfeed>`__ which itself is derived from Dan
Mackinlay's `sphinxcontrib.feed
<http://bitbucket.org/birkenfeld/sphinx-contrib/src/tip/feed/>`_ package. It
relies on Lars Kiesow's `python-feedgen <https://feedgen.kiesow.be>`__ package
instead of the defunct `feedformatter
<https://code.google.com/archive/p/feedformatter/>`_ package or of Django utils to
generate the feed.

It relies on the `feedformatter <http://code.google.com/p/feedformatter/>`_
package instead of Django utils to generate the feed.
Features added
==============

Usage
-----
- Support Python 3 (by using feedgen instead of feedformatter).
- Don't publish items having a publication datetime in the future.
- Ability to write
`ATOM <https://validator.w3.org/feed/docs/atom.html>`__ instead of RSS.

- Detect ``category`` and ``tags`` fields in the `page metadata
<https://www.sphinx-doc.org/en/master/usage/restructuredtext/field-lists.html>`__
and if either or both is present, call the `feedgen.FeedEntry.category()`
method to add ``<category>`` elements to the feed item. The difference
between ``category`` and ``tags`` is that the ``category`` of a blog post may
contain whitespace while the ``tags`` metadata field is a space-separated list
of tags, so each tag must be a single word. Both the category and each tag
will become a ``<category>`` element in the feed item.

- Additional Sphinx config variables:

- ``feed_field_name`` to change the name of the
metadata field to use for specifying the publication date.

- ``use_dirhtml`` to specify whether `dirhtml` instead of `html` builder is
used when calculating the url

- ``feed_entry_permalink`` to set a `permalink GUID
<https://python-feedgen.readthedocs.io/en/latest/api.entry.html#feedgen.entry.FeedEntry.guid>`__
for each feed entry. GUIDs are generated based on the entry URL. Or if a
``guid`` value is found in page metadata, that will be used instead. For
example, so it can be manually set if the URL changes. Defaults to `False`,
in which case the entry URL will be used as a non-permalink ID. Applies to
both Atom and RSS feeds.

- ``feed_use_atom`` to generate an Atom feed instead of RSS


Installation
============

#. Install ``sphinxfeed`` using ``easy_install`` / ``pip`` /
``python setup.py install``
You can install it using pip::

pip install sphinxfeed-lsaffre

How to test whether the right version of sphinxfeed is installed:

>>> import sphinxfeed
>>> sphinxfeed.__version__
'0.3.1'


Usage
=====

#. Add ``sphinxfeed`` to the list of extensions in your ``conf.py``::

extensions = [..., 'sphinxfeed']

#. Customise the necessary configuration options to correctly generate the
feed::
#. Customise the necessary configuration options to correctly generate
the feed::

feed_base_url = 'http://YOUR_HOST_URL'
feed_base_url = 'https://YOUR_HOST_URL'
feed_author = 'YOUR NAME'
feed_description = "A longer description"

# optional options
feed_field_name = 'date' # default value is "Publish Date"
feed_use_atom = False
use_dirhtml = False

#. Optionally use the following metadata fields:

- date (or any other name configured using feed_field_name)
- author
- guid
- tags
- category

#. Sphinxfeed will include only `.rst` files that have a ``:date:`` field with a
date that does not lie in the future.


Maintenance
===========

See also the files `LICENSE` and `CHANGELOG.rst`.

Install a developer version::

git clone https://github.com/lsaffre/sphinxfeed.git
pip install -e ".[dev]"

Run the test suite::

$ pytest

Generate an HTML test coverage report::

$ pytest --cov-report=html
$ python -m webbrowser test-reports/index.html

Release a new version to PyPI::

$ hatch version micro
$ git commit -am "release to pypi"
$ git tag v$(hatch version)
$ git push --tags

See `Hatch Versioning <https://hatch.pypa.io/1.8/version/>`__. and `Publishing
to PyPI with a Trusted Publisher <https://docs.pypi.org/trusted-publishers/>`__.

Manually release to PyPI using your machine and token::

$ hatch build
$ twine check --strict dist/*
$ twine upload dist/*

The ``twine upload`` step requires authentication credentials in your
`~/.pypirc` file.
80 changes: 80 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"

[project]
name = "sphinxfeed-lsaffre"
dynamic = ["version"]
description = "Sphinx extension for generating RSS feeds"
readme = "README.rst"
license = {file = "LICENSE"}
requires-python = ">= 3.8"

authors = [
{ name = "Fergus Doyle", email = "fergus.doyle@largeblue.com" },
{ name = "Luc Saffre", email = "luc@saffre-rumma.net" },
{ name = "Jordan Cook", email = "jordan.cook.git@proton.me" },
]

maintainers = [
{ name = "Luc Saffre", email = "luc@saffre-rumma.net" },
]

classifiers = [
"Development Status :: 4 - Beta",
"Environment :: Console",
"Environment :: Web Environment",
"Intended Audience :: Developers",
"License :: OSI Approved :: BSD License",
"Operating System :: OS Independent",
"Programming Language :: Python",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Topic :: Documentation",
"Topic :: Utilities",
]

dependencies = [
"feedgen",
"python-dateutil",
"Sphinx",
]

[project.optional-dependencies]
dev = [
"hatch",
"pytest",
"pytest-cov",
]

[project.urls]
homepage = "https://github.com/lsaffre/sphinxfeed"
issues = "https://github.com/lsaffre/sphinxfeed/issues"

[tool.hatch.version]
path = "sphinxfeed.py"

[tool.hatch.build.targets.sdist]
include = ["sphinxfeed.py"]

[tool.hatch.build.targets.wheel]
only-include = ["sphinxfeed.py"]

[tool.hatch.build]
dev-mode-dirs = ["."]

# Coverage report config: by default, show condensed terminal output
[tool.coverage.run]
branch = true
source = ['.']
omit = ['tests/*', 'tasks.py']

[tool.coverage.html]
directory = 'test-reports'

[tool.pytest.ini_options]
addopts = "--cov --cov-report=term"
Empty file added pytest.ini
Empty file.
Loading