o 3Ûøa;ã@sÌdZddlZddlZddlmZddlmZddlmZddl m Z ddl m Z dd „Z d d „Zd d „ZGdd„dƒZGdd„dƒZGdd„deƒZGdd„deƒZGdd„deƒZGdd„deƒZeZdS)aî Syndication feed generation library -- used for generating RSS, etc. Sample usage: >>> from django.utils import feedgenerator >>> feed = feedgenerator.Rss201rev2Feed( ... title="Poynter E-Media Tidbits", ... link="http://www.poynter.org/column.asp?id=31", ... description="A group Weblog by the sharpest minds in online media/journalism/publishing.", ... language="en", ... ) >>> feed.add_item( ... title="Hello", ... link="http://www.holovaty.com/test/", ... description="Testing." ... ) >>> with open('test.rss', 'w') as fp: ... feed.write(fp, 'utf-8') For definitions of the different versions of RSS, see: https://web.archive.org/web/20110718035220/http://diveintomark.org/archives/2004/02/04/incompatible-rss éN)ÚStringIO)Úurlparse)Ú iri_to_uri)Úutc)ÚSimplerXMLGeneratorcCs*t|tjƒstj |t ¡¡}tj |¡S©N)Ú isinstanceÚdatetimeÚcombineÚtimeÚemailÚutilsÚformat_datetime©Údate©rú.to_strcSsg|]}t|ƒ‘qSrr#©Ú.0ÚcrrrÚ Bóz,SyndicationFeed.__init__..r) ÚtitleÚlinkÚ descriptionÚlanguageÚ author_emailÚ author_nameÚ author_linkÚsubtitleÚ categoriesÚfeed_urlÚfeed_copyrightÚidÚttl)rÚfeedÚitems)Úselfr.r/r0r1r2r3r4r5r6r7r8Ú feed_guidr:Úkwargsr'rrrÚ__init__=s&óò zSyndicationFeed.__init__rc s‚dd„‰| o‡fdd„| Dƒ} |j ˆ|ƒt|ƒˆ|ƒˆ|ƒˆ|ƒt|ƒ||ˆ|ƒˆ| ƒ| |p0d| p3dˆ| ƒˆ| ƒdœ|¥¡dS)zí Add an item to the feed. All args are expected to be strings except pubdate and updateddate, which are datetime.datetime objects, and enclosures, which is an iterable of instances of the Enclosure class. cSr"rr#r%rrrr'^r(z(SyndicationFeed.add_item..to_strcsg|]}ˆ|ƒ‘qSrrr)©r'rrr,`r-z,SyndicationFeed.add_item..r)r.r/r0r2r3r4ÚpubdateÚ updateddateÚcommentsÚ unique_idÚunique_id_is_permalinkÚ enclosuresr6Úitem_copyrightr:N)r<Úappendr)r=r.r/r0r2r3r4rBrDrErFr6rHr:rCrGr?rrArÚadd_itemUs* ñ ðzSyndicationFeed.add_itemcCs t|jƒSr)Úlenr<©r=rrrÚ num_itemsts zSyndicationFeed.num_itemscCóiS)zx Return extra attributes to place on the root (i.e. feed/channel) element. Called from write(). rrLrrrÚroot_attributeswózSyndicationFeed.root_attributescCódS)zd Add elements in the root (i.e. feed/channel) element. Called from write(). Nr©r=ÚhandlerrrrÚadd_root_elements~rPz!SyndicationFeed.add_root_elementscCrN)zZ Return extra attributes to place on each item (i.e. item/entry) element. r)r=ÚitemrrrÚitem_attributes…ózSyndicationFeed.item_attributescCrQ)zF Add elements on each item (i.e. item/entry) element. Nr©r=rSrUrrrÚadd_item_elements‹rWz!SyndicationFeed.add_item_elementscCstdƒ‚)z‰ Output the feed in the given encoding to outfile, which is a file-like object. Subclasses should override this. z;subclasses of SyndicationFeed must provide a write() method)ÚNotImplementedError)r=ÚoutfileÚencodingrrrÚwrite‘szSyndicationFeed.writecCstƒ}| ||¡| ¡S)zD Return the feed in the given encoding as a string. )rr]Úgetvalue)r=r\r&rrrÚ writeString˜s zSyndicationFeed.writeStringcCsVd}d}|jD]}|D]}| |¡}|r|dus||kr|}q q|p*tj ¡jtdS)z Return the latest item's pubdate or updateddate. If no items have either of these attributes this return the current UTC date/time. N)rCrB)Útzinfo)r<Úgetr ÚutcnowÚreplacer)r=Ú latest_dateÚ date_keysrUÚdate_keyÚ item_daterrrÚlatest_post_date s  €üz SyndicationFeed.latest_post_date) NNNNNNNNNN) NNNNNNNrNNNN)Ú__name__Ú __module__Ú __qualname__Ú__doc__r@rJrMrOrTrVrYr]r_rhrrrrr!;s& þ ý r!c@óeZdZdZdd„ZdS)Ú EnclosurezAn RSS enclosurecCs|||_|_t|ƒ|_dS)z#All args are expected to be stringsN)ÚlengthÚ mime_typerr)r=rrorprrrr@µszEnclosure.__init__N)rirjrkrlr@rrrrrn³s rnc@s8eZdZdZdd„Zdd„Zdd„Zdd „Zd d „Zd S) ÚRssFeedz"application/rss+xml; charset=utf-8cCs^t||ƒ}| ¡| d| ¡¡| d| ¡¡| |¡| |¡| |¡| d¡dS)NÚrssÚchannel) rÚ startDocumentÚ startElementÚrss_attributesrOrTÚ write_itemsÚendChannelElementÚ endElement©r=r[r\rSrrrr]¾s    z RssFeed.writecCs |jddœS)Núhttp://www.w3.org/2005/Atom)Úversionz xmlns:atom)Ú_versionrLrrrrvÈsþzRssFeed.rss_attributescCó8|jD]}| d| |¡¡| ||¡| d¡qdS)NrU©r<rurVrYryrXrrrrwÎó   ýzRssFeed.write_itemscCsö| d|jd¡| d|jd¡| d|jd¡|jddur/| ddd|jddœ¡|jddur?| d|jd¡|jd D]}| d |¡qD|jd dur]| d |jd ¡| d t| ¡ƒ¡|jddury| d|jd¡dSdS)Nr.r/r0r7z atom:linkr=©ÚrelÚhrefr1r6Úcategoryr8Ú copyrightÚ lastBuildDater:)ÚaddQuickElementr;rrh©r=rSÚcatrrrrTÔsÿzRssFeed.add_root_elementscCs| d¡dS)Nrs)ryrRrrrrxäszRssFeed.endChannelElementN) rirjrkÚ content_typer]rvrwrTrxrrrrrq»s  rqc@rm)ÚRssUserland091Feedz0.91cCsD| d|d¡| d|d¡|ddur | d|d¡dSdS)Nr.r/r0)r‡rXrrrrYës  ÿz$RssUserland091Feed.add_item_elementsN©rirjrkr}rYrrrrr‹ès r‹c@rm)ÚRss201rev2Feedz2.0cCsª| d|d¡| d|d¡|ddur| d|d¡|dr5|dr5| dd|d|df¡n|drB| d|d¡n|drQ| d|dd d i¡|d dura| d t|d ƒ¡|d duro| d |d ¡|ddur’i}t| d¡tƒr‰t|dƒ ¡|d<| d|d|¡|ddur | d|d¡|drÆt|dƒ}t|ƒdkr´t dƒ‚|d}| dd|j |j |j dœ¡|dD]}| d|¡qÊdS)Nr.r/r0r3r2Úauthorz%s (%s)z dc:creatorzxmlns:dcz http://purl.org/dc/elements/1.1/rBÚpubDaterDrErFÚ isPermaLinkÚguidr:rGézrRSS feed items may only have one enclosure, see http://www.rssboard.org/rss-profile#element-channel-item-enclosurerÚ enclosurer)rroÚtyper6r„) r‡rrraÚboolr$ÚlowerÚlistrKÚ ValueErrorrrorp)r=rSrUÚ guid_attrsrGr“r‰rrrrYösL ÿ      ÿý ÿz Rss201rev2Feed.add_item_elementsNrŒrrrrròs rc@s<eZdZdZdZdd„Zdd„Zdd„Zd d „Zd d „Z d S)Ú Atom1Feedz#application/atom+xml; charset=utf-8r{cCsDt||ƒ}| ¡| d| ¡¡| |¡| |¡| d¡dS)Nr;)rrtrurOrTrwryrzrrrr]+s   zAtom1Feed.writecCs*|jddur|j|jddœSd|jiS)Nr1)Úxmlnszxml:langr›)r;ÚnsrLrrrrO3s zAtom1Feed.root_attributescCsZ| d|jd¡| ddd|jddœ¡|jddur*| ddd|jddœ¡| d|jd¡| d t| ¡ƒ¡|jd durx| d i¡| d |jd ¡|jd durc| d|jd ¡|jddurs| d|jd¡| d ¡|jddurˆ| d|jd¡|jdD] }| ddd|i¡q|jddur«| d|jd¡dSdS)Nr.r/rÚ alternaterr7r=r9Úupdatedr3rŽÚnamer2r r4Úurir5r6r„Útermr8Úrights)r‡r;rrhruryrˆrrrrT9s*  ÿzAtom1Feed.add_root_elementscCr~)NÚentryrrXrrrrwOr€zAtom1Feed.write_itemsc Cs˜| d|d¡| dd|dddœ¡|ddur$| dt|dƒ¡|ddur4| d t|dƒ¡|d duri| d i¡| d |d ¡|d durV| d|d ¡|ddurd| d|d¡| d ¡|ddurt|d}n t|d|dƒ}| d|¡|ddur”| d|dddi¡|dD]}| ddd|j|j|jdœ¡q˜|dD] }| ddd|i¡q®|ddurÊ| d|d¡dSdS)Nr.r/rr)rƒr‚rBÚ publishedrCržr3rŽrŸr2r r4r rEr9r0Úsummaryr”ÚhtmlrGr“)r‚rƒror”r6r„r¡rHr¢)r‡rruryr rrorp)r=rSrUrEr“r‰rrrrYUs@             ü  ÿzAtom1Feed.add_item_elementsN) rirjrkrŠrœr]rOrTrwrYrrrrrš&s rš)rlr r ÚiorÚ urllib.parserÚdjango.utils.encodingrÚdjango.utils.timezonerÚdjango.utils.xmlutilsrrrr r!rnrqr‹rršÚ DefaultFeedrrrrÚs$      x- 4b