##// END OF EJS Templates
py3.13: Fix DeprecationWarning: 'count' is passed as positional argument
Mads Kiilerich -
r8791:b9332da7 stable
parent child Browse files
Show More
@@ -1,152 +1,152
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 # This program is free software: you can redistribute it and/or modify
2 # This program is free software: you can redistribute it and/or modify
3 # it under the terms of the GNU General Public License as published by
3 # it under the terms of the GNU General Public License as published by
4 # the Free Software Foundation, either version 3 of the License, or
4 # the Free Software Foundation, either version 3 of the License, or
5 # (at your option) any later version.
5 # (at your option) any later version.
6 #
6 #
7 # This program is distributed in the hope that it will be useful,
7 # This program is distributed in the hope that it will be useful,
8 # but WITHOUT ANY WARRANTY; without even the implied warranty of
8 # but WITHOUT ANY WARRANTY; without even the implied warranty of
9 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 # GNU General Public License for more details.
10 # GNU General Public License for more details.
11 #
11 #
12 # You should have received a copy of the GNU General Public License
12 # You should have received a copy of the GNU General Public License
13 # along with this program. If not, see <http://www.gnu.org/licenses/>.
13 # along with this program. If not, see <http://www.gnu.org/licenses/>.
14
14
15 """
15 """
16 kallithea.lib.feeds
16 kallithea.lib.feeds
17 ~~~~~~~~~~~~~~~~~~~
17 ~~~~~~~~~~~~~~~~~~~
18
18
19 Shared code for providing RSS and ATOM feeds.
19 Shared code for providing RSS and ATOM feeds.
20 """
20 """
21
21
22 import datetime
22 import datetime
23 import re
23 import re
24
24
25 import mako.template
25 import mako.template
26
26
27
27
28 language = 'en-us'
28 language = 'en-us'
29 ttl = "5"
29 ttl = "5"
30
30
31
31
32 # From ``django.utils.feedgenerator`` via webhelpers.feedgenerator
32 # From ``django.utils.feedgenerator`` via webhelpers.feedgenerator
33 def rfc2822_date(date):
33 def rfc2822_date(date):
34 # We do this ourselves to be timezone aware, email.Utils is not tz aware.
34 # We do this ourselves to be timezone aware, email.Utils is not tz aware.
35 if getattr(date, "tzinfo", False):
35 if getattr(date, "tzinfo", False):
36 time_str = date.strftime('%a, %d %b %Y %H:%M:%S ')
36 time_str = date.strftime('%a, %d %b %Y %H:%M:%S ')
37 offset = date.tzinfo.utcoffset(date)
37 offset = date.tzinfo.utcoffset(date)
38 timezone = (offset.days * 24 * 60) + (offset.seconds / 60)
38 timezone = (offset.days * 24 * 60) + (offset.seconds / 60)
39 hour, minute = divmod(timezone, 60)
39 hour, minute = divmod(timezone, 60)
40 return time_str + "%+03d%02d" % (hour, minute)
40 return time_str + "%+03d%02d" % (hour, minute)
41 else:
41 else:
42 return date.strftime('%a, %d %b %Y %H:%M:%S -0000')
42 return date.strftime('%a, %d %b %Y %H:%M:%S -0000')
43
43
44 # From ``django.utils.feedgenerator`` via webhelpers.feedgenerator
44 # From ``django.utils.feedgenerator`` via webhelpers.feedgenerator
45 def rfc3339_date(date):
45 def rfc3339_date(date):
46 if getattr(date, "tzinfo", False):
46 if getattr(date, "tzinfo", False):
47 time_str = date.strftime('%Y-%m-%dT%H:%M:%S')
47 time_str = date.strftime('%Y-%m-%dT%H:%M:%S')
48 offset = date.tzinfo.utcoffset(date)
48 offset = date.tzinfo.utcoffset(date)
49 timezone = (offset.days * 24 * 60) + (offset.seconds / 60)
49 timezone = (offset.days * 24 * 60) + (offset.seconds / 60)
50 hour, minute = divmod(timezone, 60)
50 hour, minute = divmod(timezone, 60)
51 return time_str + "%+03d:%02d" % (hour, minute)
51 return time_str + "%+03d:%02d" % (hour, minute)
52 else:
52 else:
53 return date.strftime('%Y-%m-%dT%H:%M:%SZ')
53 return date.strftime('%Y-%m-%dT%H:%M:%SZ')
54
54
55 # From ``django.utils.feedgenerator`` via webhelpers.feedgenerator
55 # From ``django.utils.feedgenerator`` via webhelpers.feedgenerator
56 def get_tag_uri(url, date):
56 def get_tag_uri(url, date):
57 "Creates a TagURI. See http://diveintomark.org/archives/2004/05/28/howto-atom-id"
57 "Creates a TagURI. See http://diveintomark.org/archives/2004/05/28/howto-atom-id"
58 tag = re.sub('^http://', '', url)
58 tag = re.sub('^http://', '', url)
59 if date is not None:
59 if date is not None:
60 tag = re.sub('/', ',%s:/' % date.strftime('%Y-%m-%d'), tag, 1)
60 tag = re.sub('/', ',%s:/' % date.strftime('%Y-%m-%d'), tag, count=1)
61 tag = re.sub('#', '/', tag)
61 tag = re.sub('#', '/', tag)
62 return 'tag:' + tag
62 return 'tag:' + tag
63
63
64
64
65 class Attributes(object):
65 class Attributes(object):
66 """Simple namespace for attribute dict access in mako and elsewhere"""
66 """Simple namespace for attribute dict access in mako and elsewhere"""
67 def __init__(self, a_dict):
67 def __init__(self, a_dict):
68 self.__dict__ = a_dict
68 self.__dict__ = a_dict
69
69
70
70
71 class _Feeder(object):
71 class _Feeder(object):
72
72
73 content_type = None
73 content_type = None
74 template = None # subclass must provide a mako.template.Template
74 template = None # subclass must provide a mako.template.Template
75
75
76 @classmethod
76 @classmethod
77 def render(cls, header, entries):
77 def render(cls, header, entries):
78 try:
78 try:
79 latest_pubdate = max(
79 latest_pubdate = max(
80 pubdate for pubdate in (e.get('pubdate') for e in entries)
80 pubdate for pubdate in (e.get('pubdate') for e in entries)
81 if pubdate
81 if pubdate
82 )
82 )
83 except ValueError: # max() arg is an empty sequence ... or worse
83 except ValueError: # max() arg is an empty sequence ... or worse
84 latest_pubdate = datetime.datetime.now()
84 latest_pubdate = datetime.datetime.now()
85
85
86 return cls.template.render(
86 return cls.template.render(
87 language=language,
87 language=language,
88 ttl=ttl, # rss only
88 ttl=ttl, # rss only
89 latest_pubdate=latest_pubdate,
89 latest_pubdate=latest_pubdate,
90 rfc2822_date=rfc2822_date, # for RSS
90 rfc2822_date=rfc2822_date, # for RSS
91 rfc3339_date=rfc3339_date, # for Atom
91 rfc3339_date=rfc3339_date, # for Atom
92 get_tag_uri=get_tag_uri,
92 get_tag_uri=get_tag_uri,
93 entries=[Attributes(e) for e in entries],
93 entries=[Attributes(e) for e in entries],
94 **header
94 **header
95 )
95 )
96
96
97
97
98 class AtomFeed(_Feeder):
98 class AtomFeed(_Feeder):
99
99
100 content_type = 'application/atom+xml'
100 content_type = 'application/atom+xml'
101
101
102 template = mako.template.Template('''\
102 template = mako.template.Template('''\
103 <?xml version="1.0" encoding="utf-8"?>
103 <?xml version="1.0" encoding="utf-8"?>
104 <feed xmlns="http://www.w3.org/2005/Atom" xml:lang="${language}">
104 <feed xmlns="http://www.w3.org/2005/Atom" xml:lang="${language}">
105 <title>${title}</title>
105 <title>${title}</title>
106 <link href="${link}" rel="alternate"></link>
106 <link href="${link}" rel="alternate"></link>
107 <id>${link}</id>
107 <id>${link}</id>
108 <updated>${rfc3339_date(latest_pubdate)}</updated>
108 <updated>${rfc3339_date(latest_pubdate)}</updated>
109 % for entry in entries:
109 % for entry in entries:
110 <entry>
110 <entry>
111 <title>${entry.title}</title>
111 <title>${entry.title}</title>
112 <link href="${entry.link}" rel="alternate"></link>
112 <link href="${entry.link}" rel="alternate"></link>
113 <updated>${rfc3339_date(entry.pubdate)}</updated>
113 <updated>${rfc3339_date(entry.pubdate)}</updated>
114 <published>${rfc3339_date(entry.pubdate)}</published>
114 <published>${rfc3339_date(entry.pubdate)}</published>
115 <author>
115 <author>
116 <name>${entry.author_name}</name>
116 <name>${entry.author_name}</name>
117 <email>${entry.author_email}</email>
117 <email>${entry.author_email}</email>
118 </author>
118 </author>
119 <id>${get_tag_uri(entry.link, entry.pubdate)}</id>
119 <id>${get_tag_uri(entry.link, entry.pubdate)}</id>
120 <summary type="html">${entry.description}</summary>
120 <summary type="html">${entry.description}</summary>
121 </entry>
121 </entry>
122 % endfor
122 % endfor
123 </feed>
123 </feed>
124 ''', default_filters=['x'], output_encoding='utf-8', encoding_errors='replace')
124 ''', default_filters=['x'], output_encoding='utf-8', encoding_errors='replace')
125
125
126
126
127 class RssFeed(_Feeder):
127 class RssFeed(_Feeder):
128
128
129 content_type = 'application/rss+xml'
129 content_type = 'application/rss+xml'
130
130
131 template = mako.template.Template('''\
131 template = mako.template.Template('''\
132 <?xml version="1.0" encoding="utf-8"?>
132 <?xml version="1.0" encoding="utf-8"?>
133 <rss version="2.0">
133 <rss version="2.0">
134 <channel>
134 <channel>
135 <title>${title}</title>
135 <title>${title}</title>
136 <link>${link}</link>
136 <link>${link}</link>
137 <description>${description}</description>
137 <description>${description}</description>
138 <language>${language}</language>
138 <language>${language}</language>
139 <lastBuildDate>${rfc2822_date(latest_pubdate)}</lastBuildDate>
139 <lastBuildDate>${rfc2822_date(latest_pubdate)}</lastBuildDate>
140 <ttl>${ttl}</ttl>
140 <ttl>${ttl}</ttl>
141 % for entry in entries:
141 % for entry in entries:
142 <item>
142 <item>
143 <title>${entry.title}</title>
143 <title>${entry.title}</title>
144 <link>${entry.link}</link>
144 <link>${entry.link}</link>
145 <description>${entry.description}</description>
145 <description>${entry.description}</description>
146 <author>${entry.author_email} (${entry.author_name})</author>
146 <author>${entry.author_email} (${entry.author_name})</author>
147 <pubDate>${rfc2822_date(entry.pubdate)}</pubDate>
147 <pubDate>${rfc2822_date(entry.pubdate)}</pubDate>
148 </item>
148 </item>
149 % endfor
149 % endfor
150 </channel>
150 </channel>
151 </rss>
151 </rss>
152 ''', default_filters=['x'], output_encoding='utf-8', encoding_errors='replace')
152 ''', default_filters=['x'], output_encoding='utf-8', encoding_errors='replace')
General Comments 0
You need to be logged in to leave comments. Login now