sphinxfeed-lsaffre 0.3.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,12 @@
1
+ # use glob syntax.
2
+ syntax: glob
3
+
4
+ *.pyc
5
+ *~
6
+ *.egg-info
7
+ .build
8
+ .coverage
9
+ .eggs
10
+ tmp
11
+ .doctrees
12
+ dist
@@ -0,0 +1,23 @@
1
+ Copyright 2011 Fergus Doyle <fergus.doyle@largeblue.com>
2
+ Copyright 2016-2024 Rumma & Ko Ltd <info@saffre-rumma.net>
3
+
4
+ Redistribution and use in source and binary forms, with or without modification,
5
+ are permitted provided that the following conditions are met:
6
+
7
+ 1. Redistributions of source code must retain the above copyright notice, this
8
+ list of conditions and the following disclaimer.
9
+
10
+ 2. Redistributions in binary form must reproduce the above copyright notice,
11
+ this list of conditions and the following disclaimer in the documentation
12
+ and/or other materials provided with the distribution.
13
+
14
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND
15
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
18
+ ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
21
+ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
23
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1,126 @@
1
+ Metadata-Version: 2.3
2
+ Name: sphinxfeed-lsaffre
3
+ Version: 0.3.1
4
+ Summary: Sphinx extension for generating RSS feeds
5
+ Project-URL: homepage, https://github.com/lsaffre/sphinxfeed
6
+ Project-URL: issues, https://github.com/lsaffre/sphinxfeed/issues
7
+ Author-email: Fergus Doyle <fergus.doyle@largeblue.com>, Luc Saffre <luc@saffre-rumma.net>, Jordan Cook <jordan.cook.git@proton.me>
8
+ Maintainer-email: Luc Saffre <luc@saffre-rumma.net>
9
+ License: Copyright 2011 Fergus Doyle <fergus.doyle@largeblue.com>
10
+ Copyright 2016-2024 Rumma & Ko Ltd <info@saffre-rumma.net>
11
+
12
+ Redistribution and use in source and binary forms, with or without modification,
13
+ are permitted provided that the following conditions are met:
14
+
15
+ 1. Redistributions of source code must retain the above copyright notice, this
16
+ list of conditions and the following disclaimer.
17
+
18
+ 2. Redistributions in binary form must reproduce the above copyright notice,
19
+ this list of conditions and the following disclaimer in the documentation
20
+ and/or other materials provided with the distribution.
21
+
22
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND
23
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
24
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
25
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
26
+ ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
27
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
29
+ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
31
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32
+ License-File: LICENSE
33
+ Classifier: Development Status :: 4 - Beta
34
+ Classifier: Environment :: Console
35
+ Classifier: Environment :: Web Environment
36
+ Classifier: Intended Audience :: Developers
37
+ Classifier: License :: OSI Approved :: BSD License
38
+ Classifier: Operating System :: OS Independent
39
+ Classifier: Programming Language :: Python
40
+ Classifier: Topic :: Documentation
41
+ Classifier: Topic :: Utilities
42
+ Requires-Dist: feedgen
43
+ Requires-Dist: python-dateutil
44
+ Requires-Dist: sphinx
45
+ Description-Content-Type: text/x-rst
46
+
47
+ ==========================
48
+ The ``sphinxfeed`` package
49
+ ==========================
50
+
51
+ This Sphinx extension is a fork of Fergus Doyle's `sphinxfeed package
52
+ <https://github.com/junkafarian/sphinxfeed>`__ which itself is derived from Dan
53
+ Mackinlay's `sphinxcontrib.feed
54
+ <http://bitbucket.org/birkenfeld/sphinx-contrib/src/tip/feed/>`_ package. It
55
+ relies on Lars Kiesow's `python-feedgen <https://feedgen.kiesow.be>`__ package
56
+ instead of the defunct `feedformatter
57
+ <https://code.google.com/archive/p/feedformatter/>`_ package or of Django utils to
58
+ generate the feed.
59
+
60
+
61
+ Installation
62
+ ============
63
+
64
+ Soon you can install it using pip::
65
+
66
+ pip install sphinxfeed-lsaffre
67
+
68
+ How to test whether the right version of sphinxfeed is installed:
69
+
70
+ >>> import sphinxfeed
71
+ >>> sphinxfeed.__version__
72
+ '0.3.1'
73
+
74
+
75
+ Usage
76
+ =====
77
+
78
+ #. Add ``sphinxfeed`` to the list of extensions in your ``conf.py``::
79
+
80
+ extensions = [..., 'sphinxfeed']
81
+
82
+ #. Customise the necessary configuration options to correctly generate
83
+ the feed::
84
+
85
+ feed_base_url = 'https://YOUR_HOST_URL'
86
+ feed_author = 'YOUR NAME'
87
+ feed_description = "A longer description"
88
+
89
+ # optional options
90
+ feed_field_name = 'date' # default value is "Publish Date"
91
+ feed_use_atom = False
92
+ use_dirhtml = False
93
+
94
+ #. Optionally use the following metadata fields:
95
+
96
+ - date (or any other name configured using feed_field_name)
97
+ - author
98
+ - tags
99
+ - category
100
+
101
+ #. Sphinxfeed will include only `.rst` files that have a ``:date:`` field with a
102
+ date that does not lie in the future.
103
+
104
+
105
+ Maintenance
106
+ ===========
107
+
108
+ See also the files `LICENSE` and `CHANGELOG.rst`.
109
+
110
+ Install a developer version::
111
+
112
+ git clone https://github.com/lsaffre/sphinxfeed.git
113
+ pip install -e sphinxfeed
114
+
115
+ Run the test suite::
116
+
117
+ $ pytest
118
+
119
+ Release a new version to PyPI::
120
+
121
+ $ python -m build
122
+ $ twine check --strict dist/*
123
+ $ twine upload dist/*
124
+
125
+ The ``twine upload`` step requires authentication credentials in your
126
+ `~/.pypirc` file.
@@ -0,0 +1,80 @@
1
+ ==========================
2
+ The ``sphinxfeed`` package
3
+ ==========================
4
+
5
+ This Sphinx extension is a fork of Fergus Doyle's `sphinxfeed package
6
+ <https://github.com/junkafarian/sphinxfeed>`__ which itself is derived from Dan
7
+ Mackinlay's `sphinxcontrib.feed
8
+ <http://bitbucket.org/birkenfeld/sphinx-contrib/src/tip/feed/>`_ package. It
9
+ relies on Lars Kiesow's `python-feedgen <https://feedgen.kiesow.be>`__ package
10
+ instead of the defunct `feedformatter
11
+ <https://code.google.com/archive/p/feedformatter/>`_ package or of Django utils to
12
+ generate the feed.
13
+
14
+
15
+ Installation
16
+ ============
17
+
18
+ Soon you can install it using pip::
19
+
20
+ pip install sphinxfeed-lsaffre
21
+
22
+ How to test whether the right version of sphinxfeed is installed:
23
+
24
+ >>> import sphinxfeed
25
+ >>> sphinxfeed.__version__
26
+ '0.3.1'
27
+
28
+
29
+ Usage
30
+ =====
31
+
32
+ #. Add ``sphinxfeed`` to the list of extensions in your ``conf.py``::
33
+
34
+ extensions = [..., 'sphinxfeed']
35
+
36
+ #. Customise the necessary configuration options to correctly generate
37
+ the feed::
38
+
39
+ feed_base_url = 'https://YOUR_HOST_URL'
40
+ feed_author = 'YOUR NAME'
41
+ feed_description = "A longer description"
42
+
43
+ # optional options
44
+ feed_field_name = 'date' # default value is "Publish Date"
45
+ feed_use_atom = False
46
+ use_dirhtml = False
47
+
48
+ #. Optionally use the following metadata fields:
49
+
50
+ - date (or any other name configured using feed_field_name)
51
+ - author
52
+ - tags
53
+ - category
54
+
55
+ #. Sphinxfeed will include only `.rst` files that have a ``:date:`` field with a
56
+ date that does not lie in the future.
57
+
58
+
59
+ Maintenance
60
+ ===========
61
+
62
+ See also the files `LICENSE` and `CHANGELOG.rst`.
63
+
64
+ Install a developer version::
65
+
66
+ git clone https://github.com/lsaffre/sphinxfeed.git
67
+ pip install -e sphinxfeed
68
+
69
+ Run the test suite::
70
+
71
+ $ pytest
72
+
73
+ Release a new version to PyPI::
74
+
75
+ $ python -m build
76
+ $ twine check --strict dist/*
77
+ $ twine upload dist/*
78
+
79
+ The ``twine upload`` step requires authentication credentials in your
80
+ `~/.pypirc` file.
@@ -0,0 +1,55 @@
1
+ [build-system]
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "sphinxfeed-lsaffre"
7
+ dynamic = ["version"]
8
+ description = "Sphinx extension for generating RSS feeds"
9
+ readme = "README.rst"
10
+ license = {file = "LICENSE"}
11
+
12
+ authors = [
13
+ { name = "Fergus Doyle", email = "fergus.doyle@largeblue.com" },
14
+ { name = "Luc Saffre", email = "luc@saffre-rumma.net" },
15
+ { name = "Jordan Cook", email = "jordan.cook.git@proton.me" },
16
+ ]
17
+
18
+ maintainers = [
19
+ { name = "Luc Saffre", email = "luc@saffre-rumma.net" },
20
+ ]
21
+
22
+
23
+ classifiers = [
24
+ "Development Status :: 4 - Beta",
25
+ "Environment :: Console",
26
+ "Environment :: Web Environment",
27
+ "Intended Audience :: Developers",
28
+ "License :: OSI Approved :: BSD License",
29
+ "Operating System :: OS Independent",
30
+ "Programming Language :: Python",
31
+ "Topic :: Documentation",
32
+ "Topic :: Utilities",
33
+ ]
34
+
35
+ dependencies = [
36
+ "feedgen",
37
+ "python-dateutil",
38
+ "Sphinx",
39
+ ]
40
+
41
+ [project.urls]
42
+ homepage = "https://github.com/lsaffre/sphinxfeed"
43
+ issues = "https://github.com/lsaffre/sphinxfeed/issues"
44
+
45
+ [tool.hatch.version]
46
+ path = "sphinxfeed.py"
47
+
48
+ [tool.hatch.build.targets.sdist]
49
+ include = ["sphinxfeed.py"]
50
+
51
+ [tool.hatch.build.targets.wheel]
52
+ packages = ["sphinxfeed"]
53
+
54
+ [tool.hatch.build]
55
+ dev-mode-dirs = ["."]
@@ -0,0 +1,178 @@
1
+ # This application is derived from Dan Mackinlay's sphinxcontrib.feed package.
2
+ # The original can be found at http://bitbucket.org/birkenfeld/sphinx-contrib/src/tip/feed/
3
+ """
4
+ See https://github.com/lsaffre/sphinxfeed
5
+ """
6
+
7
+ __version__ = '0.3.1'
8
+
9
+ import os.path
10
+ import time
11
+ from datetime import datetime
12
+ from dateutil.tz import tzlocal
13
+ from sphinx.util.logging import getLogger
14
+
15
+ from feedgen.feed import FeedGenerator
16
+ from feedgen.feed import FeedEntry
17
+
18
+ doc_trees = [] # for atelier
19
+ logger = getLogger(__name__)
20
+
21
+
22
+ def parse_pubdate(pubdate):
23
+ # tz = "+0002"
24
+ # chunks = pubdate.split()
25
+ # if len(chunks) == 1:
26
+ # chunks.append("23:59")
27
+ # if len(chunks) == 2:
28
+ # chunks.append(tz)
29
+ # fmt = '%Y-%m-%d %H:%M %Z'
30
+ # return time.strptime(' '.join(chunks), fmt)
31
+ fmt = '%Y-%m-%d %H:%M'
32
+ try:
33
+ date = time.strptime(pubdate, fmt)
34
+ except ValueError:
35
+ date = time.strptime(pubdate + " 23:59", fmt)
36
+ return date
37
+
38
+
39
+ def setup(app):
40
+ """ see: http://sphinx.pocoo.org/ext/appapi.html
41
+ this is the primary extension point for Sphinx
42
+ """
43
+ from sphinx.application import Sphinx
44
+ if not isinstance(app, Sphinx): return
45
+ app.add_config_value('feed_base_url', '', 'html')
46
+ app.add_config_value('feed_description', '', 'html')
47
+ app.add_config_value('feed_author', '', 'html')
48
+ app.add_config_value('feed_field_name', 'Publish Date', 'env')
49
+ app.add_config_value('feed_filename', 'rss.xml', 'html')
50
+ app.add_config_value('feed_use_atom', False, 'html')
51
+ app.add_config_value('use_dirhtml', False, 'html')
52
+
53
+ app.connect('html-page-context', create_feed_item)
54
+ app.connect('build-finished', emit_feed)
55
+ app.connect('builder-inited', create_feed_container)
56
+
57
+ #env.process_metadata deletes most of the docinfo, and dates
58
+ #in particular.
59
+
60
+
61
+ def create_feed_container(app):
62
+ #from feedformatter import Feed
63
+ feed = FeedGenerator()
64
+ feed.title(app.config.project)
65
+ feed.link(href=app.config.feed_base_url)
66
+ if app.config.feed_use_atom:
67
+ feed.id(app.config.feed_base_url)
68
+ feed.author({'name': app.config.feed_author})
69
+ feed.description(app.config.feed_description)
70
+
71
+ if app.config.language:
72
+ feed.language(app.config.language)
73
+ if app.config.copyright:
74
+ feed.copyright(app.config.copyright)
75
+ app.builder.env.feed_feed = feed
76
+ if not hasattr(app.builder.env, 'feed_items'):
77
+ app.builder.env.feed_items = {}
78
+
79
+
80
+ def create_feed_item(app, pagename, templatename, ctx, doctree):
81
+ """ Here we have access to nice HTML fragments to use in, say, an RSS feed.
82
+ """
83
+
84
+ env = app.builder.env
85
+ metadata = app.builder.env.metadata.get(pagename, {})
86
+
87
+ pubDate = metadata.get(app.config.feed_field_name, None)
88
+ if not pubDate:
89
+ return
90
+
91
+ pubDate = parse_pubdate(pubDate)
92
+
93
+ if pubDate > time.localtime():
94
+ logger.warning("Skipping %s, publish date is in the future: %s", pagename, pubDate)
95
+ return
96
+
97
+ if not ctx.get('body') or not ctx.get('title'):
98
+ return
99
+
100
+ pubDate = datetime.fromtimestamp(time.mktime(pubDate))
101
+ pubDate = pubDate.replace(tzinfo=tzlocal())
102
+
103
+ item = FeedEntry()
104
+ item.title(ctx.get('title'))
105
+ href = app.config.feed_base_url + '/' + ctx['current_page_name']
106
+ if not app.config.use_dirhtml:
107
+ href += ctx['file_suffix']
108
+ item.link(href=href)
109
+ if app.config.feed_use_atom:
110
+ item.id(href)
111
+ item.description(ctx.get('body'))
112
+ item.published(pubDate)
113
+
114
+ if author := metadata.get('author'):
115
+ # author may be a str (in field list/frontmatter) or a dict (expected by feedgen)
116
+ if isinstance (author, str):
117
+ author = {'name': author}
118
+ item.author(author)
119
+ if cat := metadata.get("category", None):
120
+ item.category(term=cat)
121
+ if tags := metadata.get("tags", None):
122
+ # tags may be a str (in field list/frontmatter), or a list (from sphinx-tags extension)
123
+ if isinstance(tags, str):
124
+ tags = tags.split()
125
+ for tag in tags:
126
+ item.category(term=tag)
127
+
128
+ env.feed_items[pagename] = item
129
+
130
+ #Additionally, we might like to provide our templates with a way to link to the rss output file
131
+ ctx['rss_link'] = app.config.feed_base_url + '/' + app.config.feed_filename
132
+
133
+
134
+ def emit_feed(app, exc):
135
+ ordered_items = list(app.builder.env.feed_items.values())
136
+ feed = app.builder.env.feed_feed
137
+ # ordered_items.sort(key=lambda x: x['pubDate'], reverse=True)
138
+ ordered_items.sort(key=lambda x: x.published())
139
+ for item in ordered_items:
140
+ feed.add_entry(item) # prepends the item
141
+ # for k, v in item.items():
142
+ # getattr(e, k)(v)
143
+
144
+ path = os.path.join(app.builder.outdir, app.config.feed_filename)
145
+
146
+ # print(20190315, path)
147
+ if app.config.feed_use_atom:
148
+ feed.atom_file(path)
149
+ else:
150
+ feed.rss_file(path)
151
+
152
+ return
153
+ # LS 20180204 The following code (pickle the environment and check
154
+ # consistency at this point) caused an error when also bibtex was
155
+ # installed. I deactivated it since I don't know why it's needed.
156
+
157
+ from os import path
158
+ from sphinx.application import ENV_PICKLE_FILENAME
159
+ from sphinx.util.console import bold
160
+ # save the environment
161
+ builder = app.builder
162
+ builder.info(bold('pickling environment... '), nonl=True)
163
+ builder.env.topickle(path.join(builder.doctreedir, ENV_PICKLE_FILENAME))
164
+ builder.info('done')
165
+
166
+ # global actions
167
+ builder.info(bold('checking consistency... '), nonl=True)
168
+ builder.env.check_consistency()
169
+ builder.info('done')
170
+
171
+
172
+ ## Tests
173
+
174
+ # ... TODO
175
+
176
+ if __name__ == '__main__':
177
+ import unittest
178
+ unittest.main()