8687.15.18
by Karl Fogel
Add the copyright header block to files under lib/canonical/. |
1 |
# Copyright 2009 Canonical Ltd. This software is licensed under the
|
2 |
# GNU Affero General Public License version 3 (see the file LICENSE).
|
|
4898.3.2
by Brad Crittenden
feed via template. non-working checkpoint. |
3 |
|
4 |
"""Base classes for feeds.
|
|
5 |
||
6 |
Supported feeds include Atom, Javascript, and HTML-snippets.
|
|
7 |
Future support may include feeds such as sparklines.
|
|
8 |
"""
|
|
9 |
||
10 |
__metaclass__ = type |
|
11 |
||
12 |
__all__ = [ |
|
13 |
'FeedBase', |
|
14 |
'FeedEntry', |
|
4898.3.5
by Brad Crittenden
refactored FeedEntry |
15 |
'FeedPerson', |
16 |
'FeedTypedData', |
|
4898.3.2
by Brad Crittenden
feed via template. non-working checkpoint. |
17 |
'MINUTES', |
18 |
]
|
|
19 |
||
4898.3.21
by Brad Crittenden
Minor code cleanup. |
20 |
import operator |
5038.1.3
by Brad Crittenden
partial update to code in response to review and fixed config files. |
21 |
import os |
4898.5.5
by Edwin Grubbs
Added Expires, Last-Modified, and Cache-Control headers. |
22 |
import time |
5204.6.35
by Brad Crittenden
Correct relative hrefs in feeds. Removed duplicate branch entries. |
23 |
from urlparse import urljoin |
5429.1.1
by Edwin Grubbs
Escaping html in atom feeds in order to get around IE7 not allowing |
24 |
from xml.sax.saxutils import escape as xml_escape |
4898.3.3
by Brad Crittenden
working checkpoing for bug feeds on products |
25 |
|
11382.6.34
by Gavin Panella
Reformat imports in all files touched so far. |
26 |
from BeautifulSoup import BeautifulSoup |
27 |
from z3c.ptcompat import ViewPageTemplateFile |
|
28 |
from zope.component import getUtility |
|
6061.16.1
by Curtis Hovey
Removed deprecation warning supression code. Updated ZCML, tests, and code to use |
29 |
from zope.datetime import rfc1123_date |
5038.1.5
by Brad Crittenden
working checkpoint. added IFeed. |
30 |
from zope.interface import implements |
7849.16.54
by Sidnei da Silva
- Whitespace corrections and a merge accident |
31 |
|
14605.1.1
by Curtis Hovey
Moved canonical.config to lp.services. |
32 |
from lp.services.config import config |
14606.4.3
by William Grant
Move the interfaces across too. |
33 |
from lp.services.feeds.interfaces.feed import ( |
11382.6.34
by Gavin Panella
Reformat imports in all files touched so far. |
34 |
IFeed, |
35 |
IFeedEntry, |
|
36 |
IFeedPerson, |
|
37 |
IFeedTypedData, |
|
38 |
UnsupportedFeedFormat, |
|
39 |
)
|
|
40 |
from lp.services.propertycache import cachedproperty |
|
13333.5.3
by Jonathan Lange
Use the new utc_now() |
41 |
from lp.services.utils import utc_now |
14606.4.3
by William Grant
Move the interfaces across too. |
42 |
from lp.services.webapp import ( |
43 |
canonical_url, |
|
44 |
LaunchpadView, |
|
45 |
urlappend, |
|
46 |
urlparse, |
|
47 |
)
|
|
48 |
# XXX: bac 2007-09-20 bug=153795: modules in canonical.lazr should not import
|
|
49 |
# from canonical.launchpad, but we're doing it here as an expediency to get a
|
|
50 |
# working prototype.
|
|
51 |
from lp.services.webapp.interfaces import ILaunchpadRoot |
|
52 |
from lp.services.webapp.vhosts import allvhosts |
|
11382.6.34
by Gavin Panella
Reformat imports in all files touched so far. |
53 |
|
4898.3.2
by Brad Crittenden
feed via template. non-working checkpoint. |
54 |
|
5062.2.2
by Brad Crittenden
Changes due to review. |
55 |
SUPPORTED_FEEDS = ('.atom', '.html') |
5427.5.2
by Brad Crittenden
Checkpoint. Non-working. |
56 |
MINUTES = 60 # Seconds in a minute. |
5062.2.2
by Brad Crittenden
Changes due to review. |
57 |
|
4898.3.2
by Brad Crittenden
feed via template. non-working checkpoint. |
58 |
|
5578.1.1
by Brad Crittenden
Feed refactoring. Removed unnecessary methods from FeedsBase. Use LaunchpadView. |
59 |
class FeedBase(LaunchpadView): |
5427.5.9
by Brad Crittenden
Added more documentation to the IFeed class. Begin making IFeedEntry, thought it is not used yet. |
60 |
"""See `IFeed`.
|
61 |
||
62 |
Base class for feeds.
|
|
63 |
"""
|
|
4898.3.2
by Brad Crittenden
feed via template. non-working checkpoint. |
64 |
|
5038.1.5
by Brad Crittenden
working checkpoint. added IFeed. |
65 |
implements(IFeed) |
4898.3.2
by Brad Crittenden
feed via template. non-working checkpoint. |
66 |
|
5132.2.1
by Edwin Grubbs
Added configuration options and tests. |
67 |
# convert to seconds
|
68 |
max_age = config.launchpad.max_feed_cache_minutes * MINUTES |
|
4898.3.16
by Brad Crittenden
Merged Edwin's changes, rearranged templates. |
69 |
quantity = 25 |
4898.3.5
by Brad Crittenden
refactored FeedEntry |
70 |
items = None |
5399.3.1
by Elliot Murphy
Fix alternate link for feeds to point to the correct location rather |
71 |
rootsite = 'mainsite' |
4898.3.16
by Brad Crittenden
Merged Edwin's changes, rearranged templates. |
72 |
template_files = {'atom': 'templates/feed-atom.pt', |
73 |
'html': 'templates/feed-html.pt'} |
|
4898.3.2
by Brad Crittenden
feed via template. non-working checkpoint. |
74 |
|
75 |
def __init__(self, context, request): |
|
5427.5.1
by Brad Crittenden
Correcting feed elements for announcements and refactoring. |
76 |
super(FeedBase, self).__init__(context, request) |
5038.1.5
by Brad Crittenden
working checkpoint. added IFeed. |
77 |
self.format = self.feed_format |
5204.6.35
by Brad Crittenden
Correct relative hrefs in feeds. Removed duplicate branch entries. |
78 |
self.root_url = canonical_url(getUtility(ILaunchpadRoot), |
79 |
rootsite=self.rootsite) |
|
4898.3.2
by Brad Crittenden
feed via template. non-working checkpoint. |
80 |
|
5038.1.5
by Brad Crittenden
working checkpoint. added IFeed. |
81 |
@property
|
82 |
def title(self): |
|
5038.1.7
by Brad Crittenden
Fixed docstrings. |
83 |
"""See `IFeed`."""
|
4898.3.2
by Brad Crittenden
feed via template. non-working checkpoint. |
84 |
raise NotImplementedError |
85 |
||
5038.1.5
by Brad Crittenden
working checkpoint. added IFeed. |
86 |
@property
|
5427.5.10
by Brad Crittenden
Added more documentation to IFeed and created IFeedEntry. Renamed some attributes for clarity and consistency. |
87 |
def link_self(self): |
5038.1.7
by Brad Crittenden
Fixed docstrings. |
88 |
"""See `IFeed`."""
|
5549.2.2
by Edwin Grubbs
Call validate_feed() in xx-branch-atom.txt and xx-announcements.txt |
89 |
|
90 |
# The self link is the URL for this particular feed. For example:
|
|
91 |
# http://feeds.launchpad.net/ubuntu/announcments.atom
|
|
92 |
path = "%s.%s" % (self.feedname, self.format) |
|
93 |
return urlappend(canonical_url(self.context, rootsite="feeds"), |
|
94 |
path) |
|
4898.3.2
by Brad Crittenden
feed via template. non-working checkpoint. |
95 |
|
5038.1.5
by Brad Crittenden
working checkpoint. added IFeed. |
96 |
@property
|
97 |
def site_url(self): |
|
5038.1.7
by Brad Crittenden
Fixed docstrings. |
98 |
"""See `IFeed`."""
|
4898.3.32
by Brad Crittenden
working checkpoint for feeds |
99 |
return allvhosts.configs['mainsite'].rooturl[:-1] |
5427.5.1
by Brad Crittenden
Correcting feed elements for announcements and refactoring. |
100 |
|
5399.3.1
by Elliot Murphy
Fix alternate link for feeds to point to the correct location rather |
101 |
@property
|
5427.5.10
by Brad Crittenden
Added more documentation to IFeed and created IFeedEntry. Renamed some attributes for clarity and consistency. |
102 |
def link_alternate(self): |
5399.3.1
by Elliot Murphy
Fix alternate link for feeds to point to the correct location rather |
103 |
"""See `IFeed`."""
|
104 |
return canonical_url(self.context, rootsite=self.rootsite) |
|
4898.3.4
by Brad Crittenden
Working links with correct feed updated element. Added feed logo and entry authors. |
105 |
|
5427.5.1
by Brad Crittenden
Correcting feed elements for announcements and refactoring. |
106 |
@property
|
5427.5.2
by Brad Crittenden
Checkpoint. Non-working. |
107 |
def feed_id(self): |
5427.5.3
by Brad Crittenden
Corrected the creation of <id> tags for feeds and added tests. |
108 |
"""See `IFeed`.
|
109 |
||
110 |
Override this method if the context used does not create a
|
|
111 |
meaningful id.
|
|
112 |
"""
|
|
113 |
# Get the creation date, if available. Otherwise use a fixed date, as
|
|
114 |
# allowed by the RFC.
|
|
6194.3.2
by Paul Hummer
Removed hasattr, replacing it with getattr |
115 |
if getattr(self.context, 'datecreated', None) is not None: |
5427.5.3
by Brad Crittenden
Corrected the creation of <id> tags for feeds and added tests. |
116 |
datecreated = self.context.datecreated.date().isoformat() |
6194.3.2
by Paul Hummer
Removed hasattr, replacing it with getattr |
117 |
elif getattr(self.context, 'date_created', None) is not None: |
5427.5.3
by Brad Crittenden
Corrected the creation of <id> tags for feeds and added tests. |
118 |
datecreated = self.context.date_created.date().isoformat() |
119 |
else: |
|
120 |
datecreated = "2008" |
|
5427.5.10
by Brad Crittenden
Added more documentation to IFeed and created IFeedEntry. Renamed some attributes for clarity and consistency. |
121 |
url_path = urlparse(self.link_alternate)[2] |
5427.5.2
by Brad Crittenden
Checkpoint. Non-working. |
122 |
if self.rootsite != 'mainsite': |
5427.5.3
by Brad Crittenden
Corrected the creation of <id> tags for feeds and added tests. |
123 |
id_ = 'tag:launchpad.net,%s:/%s%s' % ( |
124 |
datecreated, |
|
5427.5.2
by Brad Crittenden
Checkpoint. Non-working. |
125 |
self.rootsite, |
126 |
url_path) |
|
127 |
else: |
|
128 |
id_ = 'tag:launchpad.net,%s:%s' % ( |
|
5427.5.3
by Brad Crittenden
Corrected the creation of <id> tags for feeds and added tests. |
129 |
datecreated, |
5427.5.2
by Brad Crittenden
Checkpoint. Non-working. |
130 |
url_path) |
5427.5.1
by Brad Crittenden
Correcting feed elements for announcements and refactoring. |
131 |
return id_ |
132 |
||
4898.3.2
by Brad Crittenden
feed via template. non-working checkpoint. |
133 |
def getItems(self): |
5038.1.7
by Brad Crittenden
Fixed docstrings. |
134 |
"""See `IFeed`."""
|
5958.2.4
by Brad Crittenden
Added caching to the getItems method for Feeds. |
135 |
if self.items is None: |
5958.2.9
by Brad Crittenden
Fixed naming problem |
136 |
self.items = self._getItemsWorker() |
5958.2.4
by Brad Crittenden
Added caching to the getItems method for Feeds. |
137 |
return self.items |
138 |
||
5958.2.7
by Brad Crittenden
Changed getItemsWorker to _getItemsWorker. |
139 |
def _getItemsWorker(self): |
5958.2.4
by Brad Crittenden
Added caching to the getItems method for Feeds. |
140 |
"""Create the list of items.
|
141 |
||
5958.2.10
by Brad Crittenden
Changes from JamesH review. |
142 |
Called by getItems which may cache the results. The caching is
|
143 |
necessary since `getItems` is called multiple times in the course of
|
|
144 |
constructing a single feed and pulling together the list of items is
|
|
145 |
potentially expensive.
|
|
5958.2.4
by Brad Crittenden
Added caching to the getItems method for Feeds. |
146 |
"""
|
4898.3.2
by Brad Crittenden
feed via template. non-working checkpoint. |
147 |
raise NotImplementedError |
148 |
||
5038.1.5
by Brad Crittenden
working checkpoint. added IFeed. |
149 |
@property
|
150 |
def feed_format(self): |
|
5038.1.7
by Brad Crittenden
Fixed docstrings. |
151 |
"""See `IFeed`."""
|
6768.2.1
by Edwin Grubbs
URL that was raising UnsupportedFeedFormat oops now raises NotFound error. |
152 |
# If the full URL is http://feeds.launchpad.dev/announcements.atom/foo
|
153 |
# getURL() will return http://feeds.launchpad.dev/announcements.atom
|
|
154 |
# when traversing the feed, which will allow os.path.splitext()
|
|
155 |
# to split off ".atom" correctly.
|
|
156 |
path = self.request.getURL() |
|
5038.1.3
by Brad Crittenden
partial update to code in response to review and fixed config files. |
157 |
extension = os.path.splitext(path)[1] |
5062.2.3
by Brad Crittenden
Fixed show_columns, fixed test, removed unnecessary code, commented zcml, other review changes. |
158 |
if extension in SUPPORTED_FEEDS: |
5038.1.3
by Brad Crittenden
partial update to code in response to review and fixed config files. |
159 |
return extension[1:] |
4898.3.21
by Brad Crittenden
Minor code cleanup. |
160 |
else: |
5038.1.5
by Brad Crittenden
working checkpoint. added IFeed. |
161 |
raise UnsupportedFeedFormat('%s is not supported' % path) |
4898.3.21
by Brad Crittenden
Minor code cleanup. |
162 |
|
5038.1.5
by Brad Crittenden
working checkpoint. added IFeed. |
163 |
@property
|
164 |
def logo(self): |
|
5038.1.7
by Brad Crittenden
Fixed docstrings. |
165 |
"""See `IFeed`."""
|
4898.3.4
by Brad Crittenden
Working links with correct feed updated element. Added feed logo and entry authors. |
166 |
raise NotImplementedError |
167 |
||
5038.1.5
by Brad Crittenden
working checkpoint. added IFeed. |
168 |
@property
|
169 |
def icon(self): |
|
5038.1.7
by Brad Crittenden
Fixed docstrings. |
170 |
"""See `IFeed`."""
|
5038.1.5
by Brad Crittenden
working checkpoint. added IFeed. |
171 |
return "%s/@@/launchpad" % self.site_url |
4898.3.19
by Brad Crittenden
Added support for Atom feeds for a single bug and added tests for teams. |
172 |
|
5038.1.4
by Brad Crittenden
checkpoint |
173 |
@cachedproperty
|
174 |
def date_updated(self): |
|
5038.1.7
by Brad Crittenden
Fixed docstrings. |
175 |
"""See `IFeed`."""
|
5038.1.3
by Brad Crittenden
partial update to code in response to review and fixed config files. |
176 |
sorted_items = sorted(self.getItems(), |
5151.1.11
by Mark Shuttleworth
Expose feeds on feeds.launchpad.net |
177 |
key=operator.attrgetter('last_modified'), |
5038.1.3
by Brad Crittenden
partial update to code in response to review and fixed config files. |
178 |
reverse=True) |
179 |
if len(sorted_items) == 0: |
|
5549.2.2
by Edwin Grubbs
Call validate_feed() in xx-branch-atom.txt and xx-announcements.txt |
180 |
# datetime.isoformat() doesn't place the necessary "+00:00"
|
181 |
# for the feedvalidator's check of the iso8601 date format
|
|
182 |
# unless a timezone is specified with tzinfo.
|
|
13333.5.3
by Jonathan Lange
Use the new utc_now() |
183 |
return utc_now() |
5151.1.62
by Mark Shuttleworth
Fix feed dates to comply with RFC 4287 |
184 |
last_modified = sorted_items[0].last_modified |
185 |
if last_modified is None: |
|
5151.1.61
by Mark Shuttleworth
Require a date_updated for feed entries, complying with RFC 4287 |
186 |
raise AssertionError, 'All feed entries require a date updated.' |
5151.1.62
by Mark Shuttleworth
Fix feed dates to comply with RFC 4287 |
187 |
return last_modified |
4898.3.4
by Brad Crittenden
Working links with correct feed updated element. Added feed logo and entry authors. |
188 |
|
4898.3.2
by Brad Crittenden
feed via template. non-working checkpoint. |
189 |
def render(self): |
5038.1.7
by Brad Crittenden
Fixed docstrings. |
190 |
"""See `IFeed`."""
|
4898.5.5
by Edwin Grubbs
Added Expires, Last-Modified, and Cache-Control headers. |
191 |
expires = rfc1123_date(time.time() + self.max_age) |
5038.1.4
by Brad Crittenden
checkpoint |
192 |
if self.date_updated is not None: |
5009.1.5
by Edwin Grubbs
Added tests to verify that the atom/html feeds do not work on the |
193 |
last_modified = rfc1123_date( |
5038.1.6
by Brad Crittenden
Added additional IFeed interfaces per code review. |
194 |
time.mktime(self.date_updated.timetuple())) |
5009.1.5
by Edwin Grubbs
Added tests to verify that the atom/html feeds do not work on the |
195 |
else: |
196 |
last_modified = rfc1123_date(time.time()) |
|
4898.5.5
by Edwin Grubbs
Added Expires, Last-Modified, and Cache-Control headers. |
197 |
response = self.request.response |
198 |
response.setHeader('Expires', expires) |
|
199 |
response.setHeader('Cache-Control', 'max-age=%d' % self.max_age) |
|
200 |
response.setHeader('X-Cache-Control', 'max-age=%d' % self.max_age) |
|
201 |
response.setHeader('Last-Modified', last_modified) |
|
4898.5.7
by Edwin Grubbs
Fixed bug-html.txt tests. |
202 |
|
203 |
if self.format == 'atom': |
|
204 |
return self.renderAtom() |
|
205 |
elif self.format == 'html': |
|
206 |
return self.renderHTML() |
|
207 |
else: |
|
5038.1.6
by Brad Crittenden
Added additional IFeed interfaces per code review. |
208 |
raise UnsupportedFeedFormat("Format %s is not supported" % |
209 |
self.format) |
|
4898.5.7
by Edwin Grubbs
Fixed bug-html.txt tests. |
210 |
|
211 |
def renderAtom(self): |
|
5038.1.7
by Brad Crittenden
Fixed docstrings. |
212 |
"""See `IFeed`."""
|
5475.1.2
by Edwin Grubbs
Removed trailing whitespace. |
213 |
self.request.response.setHeader('content-type', |
5475.1.1
by Edwin Grubbs
Fixes bug 181620. Set the content type for feeds to |
214 |
'application/atom+xml;charset=utf-8') |
215 |
template_file = ViewPageTemplateFile(self.template_files['atom']) |
|
216 |
result = template_file(self) |
|
217 |
# XXX EdwinGrubbs 2008-01-10 bug=181903
|
|
218 |
# Zope3 requires the content-type to start with "text/" if
|
|
219 |
# the result is a unicode object.
|
|
220 |
return result.encode('utf-8') |
|
4898.5.7
by Edwin Grubbs
Fixed bug-html.txt tests. |
221 |
|
222 |
def renderHTML(self): |
|
5038.1.7
by Brad Crittenden
Fixed docstrings. |
223 |
"""See `IFeed`."""
|
4898.5.7
by Edwin Grubbs
Fixed bug-html.txt tests. |
224 |
return ViewPageTemplateFile(self.template_files['html'])(self) |
4898.3.2
by Brad Crittenden
feed via template. non-working checkpoint. |
225 |
|
5038.1.6
by Brad Crittenden
Added additional IFeed interfaces per code review. |
226 |
|
4898.3.2
by Brad Crittenden
feed via template. non-working checkpoint. |
227 |
class FeedEntry: |
5427.5.9
by Brad Crittenden
Added more documentation to the IFeed class. Begin making IFeedEntry, thought it is not used yet. |
228 |
"""See `IFeedEntry`.
|
229 |
||
5427.5.10
by Brad Crittenden
Added more documentation to IFeed and created IFeedEntry. Renamed some attributes for clarity and consistency. |
230 |
An individual entry for a feed.
|
5427.5.9
by Brad Crittenden
Added more documentation to the IFeed class. Begin making IFeedEntry, thought it is not used yet. |
231 |
"""
|
232 |
||
233 |
implements(IFeedEntry) |
|
234 |
||
4898.3.5
by Brad Crittenden
refactored FeedEntry |
235 |
def __init__(self, |
236 |
title, |
|
237 |
link_alternate, |
|
5427.5.1
by Brad Crittenden
Correcting feed elements for announcements and refactoring. |
238 |
date_created, |
5151.1.61
by Mark Shuttleworth
Require a date_updated for feed entries, complying with RFC 4287 |
239 |
date_updated, |
4898.3.5
by Brad Crittenden
refactored FeedEntry |
240 |
date_published=None, |
241 |
authors=None, |
|
242 |
contributors=None, |
|
243 |
content=None, |
|
5204.6.21
by Brad Crittenden
Added branch feed for a person. |
244 |
id_=None, |
4898.3.5
by Brad Crittenden
refactored FeedEntry |
245 |
generator=None, |
246 |
logo=None, |
|
247 |
icon=None): |
|
248 |
self.title = title |
|
249 |
self.link_alternate = link_alternate |
|
250 |
self.content = content |
|
5204.6.21
by Brad Crittenden
Added branch feed for a person. |
251 |
self.date_created = date_created |
5151.1.12
by Mark Shuttleworth
Show both date published and date updated in feeds |
252 |
self.date_updated = date_updated |
4898.3.5
by Brad Crittenden
refactored FeedEntry |
253 |
self.date_published = date_published |
5151.1.62
by Mark Shuttleworth
Fix feed dates to comply with RFC 4287 |
254 |
if date_updated is None: |
255 |
raise AssertionError, 'date_updated is required by RFC 4287' |
|
4898.3.5
by Brad Crittenden
refactored FeedEntry |
256 |
if authors is None: |
257 |
authors = [] |
|
258 |
self.authors = authors |
|
259 |
self.contributors = contributors |
|
5958.2.10
by Brad Crittenden
Changes from JamesH review. |
260 |
if id_ is None: |
261 |
self.id = self.construct_id() |
|
262 |
else: |
|
263 |
self.id = id_ |
|
5204.6.21
by Brad Crittenden
Added branch feed for a person. |
264 |
|
265 |
@property
|
|
266 |
def last_modified(self): |
|
267 |
if self.date_published is not None: |
|
268 |
return max(self.date_published, self.date_updated) |
|
269 |
return self.date_updated |
|
270 |
||
271 |
def construct_id(self): |
|
272 |
url_path = urlparse(self.link_alternate)[2] |
|
273 |
return 'tag:launchpad.net,%s:%s' % ( |
|
274 |
self.date_created.date().isoformat(), |
|
5958.2.1
by Brad Crittenden
Changes to make feeds database access more efficient. |
275 |
url_path) |
4898.3.5
by Brad Crittenden
refactored FeedEntry |
276 |
|
5038.1.6
by Brad Crittenden
Added additional IFeed interfaces per code review. |
277 |
|
4898.3.5
by Brad Crittenden
refactored FeedEntry |
278 |
class FeedTypedData: |
4898.3.21
by Brad Crittenden
Minor code cleanup. |
279 |
"""Data for a feed that includes its type."""
|
5038.1.6
by Brad Crittenden
Added additional IFeed interfaces per code review. |
280 |
|
281 |
implements(IFeedTypedData) |
|
282 |
||
4898.3.5
by Brad Crittenden
refactored FeedEntry |
283 |
content_types = ['text', 'html', 'xhtml'] |
5062.2.2
by Brad Crittenden
Changes due to review. |
284 |
|
5204.6.35
by Brad Crittenden
Correct relative hrefs in feeds. Removed duplicate branch entries. |
285 |
def __init__(self, content, content_type='text', root_url=None): |
5429.1.1
by Edwin Grubbs
Escaping html in atom feeds in order to get around IE7 not allowing |
286 |
self._content = content |
4898.3.5
by Brad Crittenden
refactored FeedEntry |
287 |
if content_type not in self.content_types: |
5062.2.2
by Brad Crittenden
Changes due to review. |
288 |
raise UnsupportedFeedFormat("%s: is not valid" % content_type) |
4898.3.5
by Brad Crittenden
refactored FeedEntry |
289 |
self.content_type = content_type |
5204.6.35
by Brad Crittenden
Correct relative hrefs in feeds. Removed duplicate branch entries. |
290 |
self.root_url = root_url |
4898.3.5
by Brad Crittenden
refactored FeedEntry |
291 |
|
5429.1.1
by Edwin Grubbs
Escaping html in atom feeds in order to get around IE7 not allowing |
292 |
@property
|
293 |
def content(self): |
|
5204.6.35
by Brad Crittenden
Correct relative hrefs in feeds. Removed duplicate branch entries. |
294 |
if (self.content_type in ('html', 'xhtml') and |
295 |
self.root_url is not None): |
|
296 |
# Unqualified hrefs must be qualified using the original subdomain
|
|
297 |
# or they will try be served from http://feeds.launchpad.net,
|
|
298 |
# which will not work.
|
|
299 |
soup = BeautifulSoup(self._content) |
|
300 |
a_tags = soup.findAll('a') |
|
301 |
for a_tag in a_tags: |
|
302 |
if a_tag['href'].startswith('/'): |
|
303 |
a_tag['href'] = urljoin(self.root_url, a_tag['href']) |
|
304 |
altered_content = unicode(soup) |
|
305 |
else: |
|
306 |
altered_content = self._content |
|
307 |
||
5429.1.1
by Edwin Grubbs
Escaping html in atom feeds in order to get around IE7 not allowing |
308 |
if self.content_type in ('text', 'html'): |
5204.6.35
by Brad Crittenden
Correct relative hrefs in feeds. Removed duplicate branch entries. |
309 |
altered_content = xml_escape(altered_content) |
5429.1.1
by Edwin Grubbs
Escaping html in atom feeds in order to get around IE7 not allowing |
310 |
elif self.content_type == 'xhtml': |
5204.6.33
by Brad Crittenden
Use html not xhtml for branch feed content. Use BeautifulSoup to convert HTML entities. |
311 |
soup = BeautifulSoup( |
5204.6.35
by Brad Crittenden
Correct relative hrefs in feeds. Removed duplicate branch entries. |
312 |
altered_content, |
5204.6.33
by Brad Crittenden
Use html not xhtml for branch feed content. Use BeautifulSoup to convert HTML entities. |
313 |
convertEntities=BeautifulSoup.HTML_ENTITIES) |
5204.6.35
by Brad Crittenden
Correct relative hrefs in feeds. Removed duplicate branch entries. |
314 |
altered_content = unicode(soup) |
315 |
return altered_content |
|
5038.1.6
by Brad Crittenden
Added additional IFeed interfaces per code review. |
316 |
|
6736.3.4
by Tim Penhey
Added tests for addition Revision and RevisionSet methods. |
317 |
|
4898.3.5
by Brad Crittenden
refactored FeedEntry |
318 |
class FeedPerson: |
5204.6.26
by Brad Crittenden
Added feed for latest revisions on a given branch. |
319 |
"""See `IFeedPerson`.
|
4898.3.21
by Brad Crittenden
Minor code cleanup. |
320 |
|
321 |
If this class is consistently used we will not accidentally leak email
|
|
322 |
addresses.
|
|
323 |
"""
|
|
5038.1.6
by Brad Crittenden
Added additional IFeed interfaces per code review. |
324 |
|
325 |
implements(IFeedPerson) |
|
326 |
||
4898.3.32
by Brad Crittenden
working checkpoint for feeds |
327 |
def __init__(self, person, rootsite): |
4898.3.5
by Brad Crittenden
refactored FeedEntry |
328 |
self.name = person.displayname |
329 |
# We don't want to disclose email addresses in public feeds.
|
|
330 |
self.email = None |
|
4898.3.32
by Brad Crittenden
working checkpoint for feeds |
331 |
self.uri = canonical_url(person, rootsite=rootsite) |