atom.py (8445B)
1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\carbon\common\lib\werkzeug\contrib\atom.py 2 from datetime import datetime 3 from werkzeug.utils import escape 4 from werkzeug.wrappers import BaseResponse 5 XHTML_NAMESPACE = 'http://www.w3.org/1999/xhtml' 6 7 def _make_text_block(name, content, content_type = None): 8 if content_type == 'xhtml': 9 return u'<%s type="xhtml"><div xmlns="%s">%s</div></%s>\n' % (name, 10 XHTML_NAMESPACE, 11 content, 12 name) 13 if not content_type: 14 return u'<%s>%s</%s>\n' % (name, escape(content), name) 15 return u'<%s type="%s">%s</%s>\n' % (name, 16 content_type, 17 escape(content), 18 name) 19 20 21 def format_iso8601(obj): 22 return obj.strftime('%Y-%m-%dT%H:%M:%SZ') 23 24 25 class AtomFeed(object): 26 default_generator = ('Werkzeug', None, None) 27 28 def __init__(self, title = None, entries = None, **kwargs): 29 self.title = title 30 self.title_type = kwargs.get('title_type', 'text') 31 self.url = kwargs.get('url') 32 self.feed_url = kwargs.get('feed_url', self.url) 33 self.id = kwargs.get('id', self.feed_url) 34 self.updated = kwargs.get('updated') 35 self.author = kwargs.get('author', ()) 36 self.icon = kwargs.get('icon') 37 self.logo = kwargs.get('logo') 38 self.rights = kwargs.get('rights') 39 self.rights_type = kwargs.get('rights_type') 40 self.subtitle = kwargs.get('subtitle') 41 self.subtitle_type = kwargs.get('subtitle_type', 'text') 42 self.generator = kwargs.get('generator') 43 if self.generator is None: 44 self.generator = self.default_generator 45 self.links = kwargs.get('links', []) 46 self.entries = entries and list(entries) or [] 47 if not hasattr(self.author, '__iter__') or isinstance(self.author, (basestring, dict)): 48 self.author = [self.author] 49 for i, author in enumerate(self.author): 50 if not isinstance(author, dict): 51 self.author[i] = {'name': author} 52 53 if not self.title: 54 raise ValueError('title is required') 55 if not self.id: 56 raise ValueError('id is required') 57 for author in self.author: 58 if 'name' not in author: 59 raise TypeError('author must contain at least a name') 60 61 def add(self, *args, **kwargs): 62 if len(args) == 1 and not kwargs and isinstance(args[0], FeedEntry): 63 self.entries.append(args[0]) 64 else: 65 kwargs['feed_url'] = self.feed_url 66 self.entries.append(FeedEntry(*args, **kwargs)) 67 68 def __repr__(self): 69 return '<%s %r (%d entries)>' % (self.__class__.__name__, self.title, len(self.entries)) 70 71 def generate(self): 72 if not self.author: 73 if False in map(lambda e: bool(e.author), self.entries): 74 self.author = ({'name': u'unbekannter Autor'},) 75 if not self.updated: 76 dates = sorted([ entry.updated for entry in self.entries ]) 77 self.updated = dates and dates[-1] or datetime.utcnow() 78 yield u'<?xml version="1.0" encoding="utf-8"?>\n' 79 yield u'<feed xmlns="http://www.w3.org/2005/Atom">\n' 80 yield ' ' + _make_text_block('title', self.title, self.title_type) 81 yield u' <id>%s</id>\n' % escape(self.id) 82 yield u' <updated>%s</updated>\n' % format_iso8601(self.updated) 83 if self.url: 84 yield u' <link href="%s" />\n' % escape(self.url, True) 85 if self.feed_url: 86 yield u' <link href="%s" rel="self" />\n' % escape(self.feed_url, True) 87 for link in self.links: 88 yield u' <link %s/>\n' % ''.join(('%s="%s" ' % (k, escape(link[k], True)) for k in link)) 89 90 for author in self.author: 91 yield u' <author>\n' 92 yield u' <name>%s</name>\n' % escape(author['name']) 93 if 'uri' in author: 94 yield u' <uri>%s</uri>\n' % escape(author['uri']) 95 if 'email' in author: 96 yield ' <email>%s</email>\n' % escape(author['email']) 97 yield ' </author>\n' 98 99 if self.subtitle: 100 yield ' ' + _make_text_block('subtitle', self.subtitle, self.subtitle_type) 101 if self.icon: 102 yield u' <icon>%s</icon>\n' % escape(self.icon) 103 if self.logo: 104 yield u' <logo>%s</logo>\n' % escape(self.logo) 105 if self.rights: 106 yield ' ' + _make_text_block('rights', self.rights, self.rights_type) 107 generator_name, generator_url, generator_version = self.generator 108 if generator_name or generator_url or generator_version: 109 tmp = [u' <generator'] 110 if generator_url: 111 tmp.append(u' uri="%s"' % escape(generator_url, True)) 112 if generator_version: 113 tmp.append(u' version="%s"' % escape(generator_version, True)) 114 tmp.append(u'>%s</generator>\n' % escape(generator_name)) 115 yield u''.join(tmp) 116 for entry in self.entries: 117 for line in entry.generate(): 118 yield u' ' + line 119 120 yield u'</feed>\n' 121 122 def to_string(self): 123 return u''.join(self.generate()) 124 125 def get_response(self): 126 return BaseResponse(self.to_string(), mimetype='application/atom+xml') 127 128 def __call__(self, environ, start_response): 129 return self.get_response()(environ, start_response) 130 131 def __unicode__(self): 132 return self.to_string() 133 134 def __str__(self): 135 return self.to_string().encode('utf-8') 136 137 138 class FeedEntry(object): 139 140 def __init__(self, title = None, content = None, feed_url = None, **kwargs): 141 self.title = title 142 self.title_type = kwargs.get('title_type', 'text') 143 self.content = content 144 self.content_type = kwargs.get('content_type', 'html') 145 self.url = kwargs.get('url') 146 self.id = kwargs.get('id', self.url) 147 self.updated = kwargs.get('updated') 148 self.summary = kwargs.get('summary') 149 self.summary_type = kwargs.get('summary_type', 'html') 150 self.author = kwargs.get('author') 151 self.published = kwargs.get('published') 152 self.rights = kwargs.get('rights') 153 self.links = kwargs.get('links', []) 154 self.xml_base = kwargs.get('xml_base', feed_url) 155 if not hasattr(self.author, '__iter__') or isinstance(self.author, (basestring, dict)): 156 self.author = [self.author] 157 for i, author in enumerate(self.author): 158 if not isinstance(author, dict): 159 self.author[i] = {'name': author} 160 161 if not self.title: 162 raise ValueError('title is required') 163 if not self.id: 164 raise ValueError('id is required') 165 if not self.updated: 166 raise ValueError('updated is required') 167 168 def __repr__(self): 169 return '<%s %r>' % (self.__class__.__name__, self.title) 170 171 def generate(self): 172 base = '' 173 if self.xml_base: 174 base = ' xml:base="%s"' % escape(self.xml_base, True) 175 yield u'<entry%s>\n' % base 176 yield u' ' + _make_text_block('title', self.title, self.title_type) 177 yield u' <id>%s</id>\n' % escape(self.id) 178 yield u' <updated>%s</updated>\n' % format_iso8601(self.updated) 179 if self.published: 180 yield u' <published>%s</published>\n' % format_iso8601(self.published) 181 if self.url: 182 yield u' <link href="%s" />\n' % escape(self.url) 183 for author in self.author: 184 yield u' <author>\n' 185 yield u' <name>%s</name>\n' % escape(author['name']) 186 if 'uri' in author: 187 yield u' <uri>%s</uri>\n' % escape(author['uri']) 188 if 'email' in author: 189 yield u' <email>%s</email>\n' % escape(author['email']) 190 yield u' </author>\n' 191 192 for link in self.links: 193 yield u' <link %s/>\n' % ''.join(('%s="%s" ' % (k, escape(link[k], True)) for k in link)) 194 195 if self.summary: 196 yield u' ' + _make_text_block('summary', self.summary, self.summary_type) 197 if self.content: 198 yield u' ' + _make_text_block('content', self.content, self.content_type) 199 yield u'</entry>\n' 200 201 def to_string(self): 202 return u''.join(self.generate()) 203 204 def __unicode__(self): 205 return self.to_string() 206 207 def __str__(self): 208 return self.to_string().encode('utf-8')