def test_latest_post_date(self): """ Test that both the published and updated dates are considered when determining the latest post date. """ # this feed has a `published` element with the latest date response = self.client.get('/syndication/atom/') feed = minidom.parseString(response.content).firstChild updated = feed.getElementsByTagName('updated')[0].firstChild.wholeText d = Entry.objects.latest('published').published ltz = tzinfo.LocalTimezone(d) latest_published = rfc3339_date(d.replace(tzinfo=ltz)) self.assertEqual(updated, latest_published) # this feed has an `updated` element with the latest date response = self.client.get('/syndication/latest/') feed = minidom.parseString(response.content).firstChild updated = feed.getElementsByTagName('updated')[0].firstChild.wholeText d = Entry.objects.exclude(pk=5).latest('updated').updated ltz = tzinfo.LocalTimezone(d) latest_updated = rfc3339_date(d.replace(tzinfo=ltz)) self.assertEqual(updated, latest_updated)
def add_item_elements(self, handler, item): if item['pubdate'] is not None: handler.addQuickElement(u"published", rfc3339_date(item['pubdate']).decode('utf-8')) item['pubdate'] = None if item['updated'] is not None: handler.addQuickElement(u"updated", rfc3339_date(item['updated']).decode('utf-8')) return super(RightAtom1Feed, self).add_item_elements(handler, item)
def atom_feed(request, encoding='utf-8', mimetype='application/atom+xml'): feed_attrs = {u"xmlns": u"http://www.w3.org/2005/Atom", u"xmlns:fh": u"http://purl.org/syndication/history/1.0"} collections = Collection.objects.filter(is_public=True) site = Site.objects.get(id=1) updated = collections.order_by('-updated')[0].updated feed_id = get_site_url(site, reverse('atom_feed')) output = StringIO.StringIO() handler = SimplerXMLGenerator(output, encoding) handler.startDocument() handler.startElement(u"feed", feed_attrs) # Required Attributes handler.addQuickElement(u"id", feed_id) handler.addQuickElement(u"title", u"UQ Anthropology Museum Sub-collections") handler.addQuickElement(u"updated", rfc3339_date(updated).decode('utf-8')) # A complete feed, so remote client will monitor for deletes/updates handler.addQuickElement(u"fh:complete") # Optional handler.addQuickElement(u"link", attrs={ u'rel': u'alternate', u'href': get_site_url(site, reverse('collections_home')), u'type': u'html' }) for collection in collections: entry_id = get_site_url(site, collection.get_absolute_url()) entry_updated = rfc3339_date(collection.updated).decode('utf-8') handler.startElement(u"entry", {}) handler.addQuickElement(u"id", entry_id) handler.addQuickElement(u"title", collection.title) handler.addQuickElement(u'updated', entry_updated) handler.addQuickElement(u'link', attrs={ u'rel': u'alternate', u'href': get_site_url(site, collection.get_atom_url()), u'type': u'application/atom+xml' }) handler.endElement(u'entry') handler.endElement(u'feed') atom = output.getvalue() response = HttpResponse(atom, mimetype=mimetype) return response
def add_root_elements(self, handler): handler._short_empty_elements = True #super(opdsFeed, self).add_root_elements(handler) handler.characters("\n") handler.addQuickElement("id", self.feed['id']) handler.addQuickElement('icon', settings.ICON) handler.characters("\n") if self.feed.get('link') is not None: handler.addQuickElement('link', None, {"href":self.feed["link"],"rel":"self","type":"application/atom+xml;profile=opds-catalog;kind=navigation"}) handler.characters("\n") if self.feed.get('start_url') is not None: handler.addQuickElement('link', None, {"href":self.feed["start_url"],"rel":"start","type":"application/atom+xml;profile=opds-catalog;kind=navigation"}) handler.characters("\n") handler.addQuickElement("title", self.feed['title']) handler.characters("\n") if self.feed.get('subtitle') is not None: handler.addQuickElement("subtitle", self.feed['subtitle']) handler.characters("\n") handler.addQuickElement("updated", rfc3339_date(self.latest_post_date())) handler.characters("\n") if self.feed.get('prev_url') is not None: handler.addQuickElement('link', None, {"href":self.feed["prev_url"],"rel":"prev","title":"Previous Page","type":"application/atom+xml;profile=opds-catalog"}) handler.characters("\n") if self.feed.get('next_url') is not None: handler.addQuickElement('link', None, {"href":self.feed["next_url"],"rel":"next","title":"Next Page","type":"application/atom+xml;profile=opds-catalog"}) handler.characters("\n") if self.feed.get('search_url') is not None: handler.addQuickElement('link', None, {"href":self.feed["search_url"],"rel":"search","type":"application/atom+xml;profile=opds-catalog;kind=navigation"}) handler.characters("\n") if self.feed.get('searchTerm_url') is not None: handler.addQuickElement('link', None, {"href":self.feed["searchTerm_url"],"rel":"search","type":"application/atom+xml"}) handler.characters("\n")
def test_all_basic_feed_with_one_item(self): response = self.app.get('/results/all-basic.atom') root = etree.XML(response.content) xml_pretty = etree.tostring(root, pretty_print=True) result_event = ResultEvent.objects.first() expected = '''<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en-gb"> <title>Election results from example.com</title> <link href="http://example.com/" rel="alternate"/> <link href="http://example.com/results/all-basic.atom" rel="self"/> <id>http://example.com/</id> <updated>{updated}</updated> <entry> <title>Tessa Jowell (Labour Party) won in Member of Parliament for Dulwich and West Norwood</title> <link href="http://example.com/#{item_id}" rel="alternate"/> <published>{updated}</published> <updated>{updated}</updated> <author> <name>john</name> </author> <id>http://example.com/#{item_id}</id> <summary type="html">A example.com volunteer recorded at {space_separated} that Tessa Jowell (Labour Party) won the ballot in Member of Parliament for Dulwich and West Norwood, quoting the source 'Seen on the BBC news').</summary> </entry> </feed> '''.format( updated=rfc3339_date(result_event.created), space_separated=result_event.created.strftime("%Y-%m-%d %H:%M:%S"), item_id=result_event.id, ) self.assertEqual(expected, xml_pretty)
def add_item_elements(self, handler, item): """Example: """ """<itunes:duration>00:48:26</itunes:duration> <itunes:author>CCNMTL</itunes:author> <itunes:explicit>no</itunes:explicit> <itunes:keywords /> <dc:title>Kenneth Jackson discusses the Colored Orphan Asylum</dc:title> <dc:description>Columbia University History Professor Kenneth Jackson describes the infamous Draft Riots and the burning of the Colored Orphan Asylum.</dc:description> <dc:creator>CCNMTL</dc:creator> <dc:contributor>Kenneth Jackson</dc:contributor> <dc:relation>http://maap.columbia.edu/welcome</dc:relation> <dc:date>2008-01-24T00:01:00Z</dc:date> <dc:identifier>ccnmtl:302.001</dc:identifier> <dc:language>English</dc:language> """ super(CCNMTLRssFeed, self).add_item_elements(handler, item) handler.addQuickElement('itunes:author', item['author_name']) handler.addQuickElement('itunes:explicit', 'no') handler.addQuickElement('itunes:subtitle', '') handler.addQuickElement('itunes:keywords', '') handler.addQuickElement('itunes:summary', item['description']) handler.addQuickElement('dc:language', item['item'].language) handler.addQuickElement('dc:title', item['title']) handler.addQuickElement('dc:description', item['description']) handler.addQuickElement('dc:date', rfc3339_date(item['item'].created))
def add_item_elements(self, handler, item): super(ActivityStreamsFeed, self).add_item_elements(handler, item) handler.addQuickElement("activity: verb", item["verb"]) if "actor" in item: handler.startElement("author", {}) handler.addQuickElement("name", item["actor"].display_name) handler.addQuickElement("uri", get_tag_uri(item["actor"].get_absolute_url(), None)) handler.addQuickElement("id", item["actor"].get_absolute_url()) handler.addQuickElement("activity: object-type", "person") handler.addQuickElement("link", get_tag_uri(item["actor"].get_absolute_url(), None), {"type": "text/html"}) handler.endElement("author") if "object" in item: handler.startElement("activity: object", {}) handler.addQuickElement("id", item["object_id"]) handler.addQuickElement("title", item["object_title"]) handler.addQuickElement("published", rfc3339_date(item["object_timestamp"]).decode("utf-8")) handler.addQuickElement("link", item["object"].get_absolute_url(), {"type": "text/html"}) handler.addQuickElement("activity: object-type", item["object_object_type"]) handler.endElement("activity: object") if "target" in item: handler.startElement("activity: target", {}) handler.addQuickElement("id", item["target_id"]) handler.addQuickElement("title", item["target_title"]) handler.addQuickElement("activity: object-type", str(item["target_object_type"])) handler.endElement("activity: target")
def add_item_elements(self, handler, item): super(ActivityStreamsFeed, self).add_item_elements(handler, item) handler.addQuickElement("activity: verb", item['verb']) if 'actor' in item: handler.startElement('author', {}) handler.addQuickElement('name', item['actor'].display_name) handler.addQuickElement('uri', get_tag_uri( item['actor'].get_absolute_url(), None)) handler.addQuickElement('id', item['actor'].get_absolute_url()) handler.addQuickElement('activity: object-type', 'person') handler.addQuickElement('link', get_tag_uri( item['actor'].get_absolute_url(), None), {'type': 'text/html'}) handler.endElement('author') if 'object' in item: handler.startElement('activity: object', {}) handler.addQuickElement('id', item['object_id']) handler.addQuickElement('title', item['object_title']) handler.addQuickElement('published', rfc3339_date(item['object_timestamp']).decode('utf-8')) handler.addQuickElement('link', item['object'].get_absolute_url(), {'type': 'text/html'}) handler.addQuickElement('activity: object-type', item['object_object_type']) handler.endElement('activity: object') if 'target' in item: handler.startElement('activity: target', {}) handler.addQuickElement('id', item['target_id']) handler.addQuickElement('title', item['target_title']) handler.addQuickElement('activity: object-type', str(item['target_object_type'])) handler.endElement('activity: target')
def atom_base(self): return ['<?xml version="1.0" encoding="utf-8"?>\n', 'xmlns="http://www.w3.org/2005/Atom"', 'xml:lang="%s"' % settings.LANGUAGE_CODE, '<updated>%s' % rfc3339_date(datetime.now())[:-3], '<uri>http://example.com/detail/', '<id>tag:example.com,2000-01-01:/detail/']
def test_rfc3339_date(self): """ Test rfc3339_date() correctly formats datetime objects. """ self.assertEqual( feedgenerator.rfc3339_date( datetime.datetime(2008, 11, 14, 13, 37, 0)), "2008-11-14T13:37:00Z")
def test_rfc3339_date_without_time(self): """ Test rfc3339_date() correctly formats date objects. """ self.assertEqual( feedgenerator.rfc3339_date(datetime.date(2008, 11, 14)), "2008-11-14T00:00:00Z" )
def test_rfc3339_date(self): """ Test rfc3339_date() correctly formats datetime objects. """ self.assertEqual( feedgenerator.rfc3339_date(datetime.datetime(2008, 11, 14, 13, 37, 0)), "2008-11-14T13:37:00Z" )
def test_rfc3339_date_with_timezone(self): """ rfc3339_date() correctly formats datetime objects with tzinfo. """ self.assertEqual( feedgenerator.rfc3339_date(datetime.datetime(2008, 11, 14, 13, 37, 0, tzinfo=get_fixed_timezone(120))), "2008-11-14T13:37:00+02:00" )
def test_rfc3339_date_with_timezone(self): """ Test rfc3339_date() correctly formats datetime objects with tzinfo. """ self.assertEqual( feedgenerator.rfc3339_date(datetime.datetime(2008, 11, 14, 13, 37, 0, tzinfo=tzinfo.FixedOffset(datetime.timedelta(minutes=120)))), "2008-11-14T13:37:00+02:00" )
def test_rfc3339_date_with_timezone(self): """ Test rfc3339_date() correctly formats datetime objects with tzinfo. """ self.assertEqual( feedgenerator.rfc3339_date(datetime.datetime(2008, 11, 14, 13, 37, 0, tzinfo=get_fixed_timezone(120))), "2008-11-14T13:37:00+02:00" )
def _room2dict(request, room): return {'name': room.name, 'description': room.description, 'user_count': room.nusers(), 'host_count': room.nhosts(), 'updated': rfc3339_date(room.lastupdated), 'self_cleaning': room.self_cleaning, 'url': base_url(request, room.go_url())}
def atom_base(self): return [ '<?xml version="1.0" encoding="utf-8"?>\n', 'xmlns="http://www.w3.org/2005/Atom"', 'xml:lang="%s"' % settings.LANGUAGE_CODE, '<updated>%s' % rfc3339_date(datetime.now())[:-3], '<uri>http://example.com/detail/', '<id>tag:example.com,2000-01-01:/detail/' ]
def test_all_basic_feed_with_a_correction(self): response = self.app.get('/results/all-basic.atom') root = etree.XML(response.content) xml_pretty = etree.tounicode(root, pretty_print=True) expected = '''<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en-gb"> <title>Election results from example.com</title> <link href="http://example.com/" rel="alternate"/> <link href="http://example.com/results/all-basic.atom" rel="self"/> <id>http://example.com/</id> <updated>{updated[0]}</updated> <entry> <title>Tessa Jowell (Labour Party) won in Dulwich and West Norwood</title> <link href="http://example.com/#{item_id[0]}" rel="alternate"/> <published>{updated[0]}</published> <updated>{updated[0]}</updated> <author> <name>john</name> </author> <id>http://example.com/#{item_id[0]}</id> <summary type="html">A example.com volunteer recorded at {space_separated[0]} that Tessa Jowell (Labour Party) won the ballot in Dulwich and West Norwood, quoting the source 'Seen on the BBC news'.</summary> </entry> <entry> <title>Correction: retracting the statement that Tessa Jowell (Labour Party) won in Dulwich and West Norwood</title> <link href="http://example.com/#{item_id[1]}" rel="alternate"/> <published>{updated[1]}</published> <updated>{updated[1]}</updated> <author> <name>john</name> </author> <id>http://example.com/#{item_id[1]}</id> <summary type="html">At {space_separated[1]}, a example.com volunteer retracted the previous assertion that Tessa Jowell (Labour Party) won the ballot in Dulwich and West Norwood, quoting the source 'Result recorded in error, retracting'.</summary> </entry> <entry> <title>James Barber (Liberal Democrats) won in Dulwich and West Norwood</title> <link href="http://example.com/#{item_id[2]}" rel="alternate"/> <published>{updated[2]}</published> <updated>{updated[2]}</updated> <author> <name>john</name> </author> <id>http://example.com/#{item_id[2]}</id> <summary type="html">A example.com volunteer recorded at {space_separated[2]} that James Barber (Liberal Democrats) won the ballot in Dulwich and West Norwood, quoting the source 'Seen on Sky News'.</summary> </entry> </feed> '''.format( updated=[ rfc3339_date(result_event.created) for result_event in self.events ], space_separated=[ result_event.created.strftime("%Y-%m-%d %H:%M:%S") for result_event in self.events ], item_id=[result_event.id for result_event in self.events], ) self.compare_xml(expected, xml_pretty)
def add_item_elements(self, handler, item): disable_item_links = item.get('disable_item_links') handler.characters("\n") handler.addQuickElement("id", item['unique_id']) handler.characters("\n") handler.addQuickElement("title", item['title']) handler.characters("\n") if not disable_item_links: handler.addQuickElement("link", "", {"href": item['link'], "rel": "alternate"}) handler.characters("\n") # Enclosures. if not disable_item_links: if item.get('enclosures') is not None: for enclosure in item['enclosures']: handler.addQuickElement('link', '', { 'rel': enclosure.rel, 'href': enclosure.url, 'type': enclosure.mime_type, }) handler.characters("\n") if item.get('updateddate') is not None: handler.addQuickElement('updated', rfc3339_date(item['updateddate'])) handler.characters("\n") if self.feed.get("description_mime_type") is not None: content_type = self.feed["description_mime_type"] else: content_type = "text/html" if item.get("description") is not None: handler.addQuickElement("content", item["description"], {"type": content_type}) handler.characters("\n") if item.get("authors") is not None: for a in item["authors"]: handler.startElement("author", {}) handler.addQuickElement("name", a['full_name']) #handler.addQuickElement("uri", item['author_link']) handler.endElement("author") handler.addQuickElement("link", "", {"href": reverse("opds_catalog:searchbooks", kwargs={"searchtype":'a', "searchterms":a['id']}), "rel": "related", "type":"application/atom+xml;profile=opds-catalog", "title":_("All books by %(author)s")%{'author':a['full_name']}}) handler.characters("\n") if item.get("genres") is not None: for g in item["genres"]: handler.addQuickElement("category", "", {"term": g['subsection'], "label": g['subsection']}) handler.characters("\n") if item.get("doubles") is not None: handler.addQuickElement("link", "", {"href": reverse("opds_catalog:searchbooks", kwargs={"searchtype":'d', "searchterms":item['doubles']}), "rel": "related", "type":"application/atom+xml;profile=opds-catalog", "title":_("Book doublicates")}) handler.characters("\n")
def read(self, request, location_slug=None): """Return information on the current usage of the location. This information is represented as a list of the location's workstations, along with information on whether or not a session is currently in progress at each workstation. If one is, the datetime at which the session began is provided. This information is available in the JSON response via the following keys: workstations - a list of each workstation at the location name - the display name of the workstation mac_addresses - a list of any MAC addresses for the workstation type - a string of the type of MAC address address - the actual MAC address, in the form AA:BB:CC:DD:EE:FF session_start - an ISO 8601 string of the session start time with timezone If the location slug provided does not map to a valid location, an HTTP 400 bad request response is returned. :param location_slug: a slug identifying a location :type location_slug: str """ try: location = Location.objects.get(slug=location_slug) except Location.DoesNotExist: return rc.BAD_REQUEST # Build a map of the workstations and their current usage workstations = [] for workstation in Workstation.objects.all_for_location(location): # Get the MAC information for the workstation macs = [] for mac in workstation.mac_addresses.all(): macs.append({ 'type': mac.get_nic_display(), 'address': mac.address_with_separators(":") }) # Provide a properly formatted session start time if one is in progress start = Session.objects.active_session_for_workstation(workstation) if start: start = rfc3339_date(location.timezone.localize(start.start)) workstations.append({ 'name': workstation.name, 'mac_addresses': macs, 'session_start': start }) return { 'workstations': workstations }
def add_item_elements(self, handler, item): super(RealAtomFeed, self).add_item_elements(handler, item) for datefield in (u"published", u"updated"): datevalue = item.get(datefield) if datevalue is not None: handler.addQuickElement(datefield, feedgenerator.rfc3339_date(datevalue).decode("utf-8")) content_html = item.get("content_html") if content_html is not None: handler.addQuickElement(u"content", content_html, {u"type": u"html"})
def add_item_elements(self, handler, item): super(StreamAtom1Feed, self).add_item_elements(handler, item) if 'begin' in item and item['begin']: handler.addQuickElement('xsn:begin', rfc3339_date(item['begin'])) if 'end' in item and item['end']: handler.addQuickElement('xsn:end', rfc3339_date(item['end'])) if 'icon' in item and item['icon']: handler.addQuickElement('xsn:icon', item['icon']) if 'channel' in item: handler.startElement("xsn:channel", {'id': item['channel']}) if 'listener' in item: handler.addQuickElement('xsn:listener', item['listener']) if 'current_song' in item: handler.addQuickElement('xsn:current_song', item['current_song']) if 'streams' in item: for stream in item['streams']: handler.addQuickElement('xsn:stream', stream) handler.endElement("xsn:channel") if 'website' in item: handler.addQuickElement('xsn:website', item['website'])
def to_entryxml(self): """XML representation of entry according to Atom standard. Uses template in templates/foreskrift_entry.xml """ if not self.content_object: # Can happen with old databases that may have stale # AtomEntry-objects with the delete property set. return "" template = loader.get_template('foreskrift_entry.xml') context = { 'entry_id': self.entry_id, 'updated': rfc3339_date(self.updated), 'published': rfc3339_date(self.published), 'deleted': rfc3339_date(self.deleted) if self.deleted else None, 'doc': self.content_object, 'rdf_post': self.rdf_post, 'rdf_url': None if self.deleted else self.content_object.get_absolute_url() + "rdf", 'fst_instance_url': settings.FST_INSTANCE_URL } return template.render(context)
def read(self, request, location_slug=None): """Return information on the current usage of the location. This information is represented as a list of the location's workstations, along with information on whether or not a session is currently in progress at each workstation. If one is, the datetime at which the session began is provided. This information is available in the JSON response via the following keys: workstations - a list of each workstation at the location name - the display name of the workstation mac_addresses - a list of any MAC addresses for the workstation type - a string of the type of MAC address address - the actual MAC address, in the form AA:BB:CC:DD:EE:FF session_start - an ISO 8601 string of the session start time with timezone If the location slug provided does not map to a valid location, an HTTP 400 bad request response is returned. :param location_slug: a slug identifying a location :type location_slug: str """ try: location = Location.objects.get(slug=location_slug) except Location.DoesNotExist: return rc.BAD_REQUEST # Build a map of the workstations and their current usage workstations = [] for workstation in Workstation.objects.all_for_location(location): # Get the MAC information for the workstation macs = [] for mac in workstation.mac_addresses.all(): macs.append({ 'type': mac.get_nic_display(), 'address': mac.address_with_separators(":") }) # Provide a properly formatted session start time if one is in progress start = Session.objects.active_session_for_workstation(workstation) if start: start = rfc3339_date(location.timezone.localize(start.start)) workstations.append({ 'name': workstation.name, 'mac_addresses': macs, 'session_start': start }) return {'workstations': workstations}
def test_get_package_as_xml(self): response = self.c.get("/api/package/%s" % self.p.id) expected = """<?xml version='1.0' encoding='utf-8'?> <feed xmlns="http://www.w3.org/2005/Atom"> <title>Test Package</title> <id>http://findcontext.org/api/package/{package_id}</id> <updated>{package_updated}</updated> <subtitle>This is a test.</subtitle> <link href="http://findcontext.org/api/package/{package_id}" rel="self"/> <entry> <title>Monasticon Hibernicum</title> <id>http://findcontext.org/api/resource/1</id> <updated>2010-01-19T00:18:34Z</updated> <summary>Early Christian ecclesiastical settlement in Ireland, 5th to 12th centuries.</summary> <author> <name>Ryan Shaw</name> </author> <content type="application/opensearchdescription+xml"> <OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/"> <ShortName>Monasticon Hibernicum</ShortName> <Description>Early Christian ecclesiastical settlement in Ireland, 5th to 12th centuries.</Description> <Url method="get" template="http://www.google.com/search?q=site:monasticon.celt.dias.ie+{{searchTerms}}" type="text/html"/> <Developer>Ryan Shaw</Developer> <InputEncoding>UTF-8</InputEncoding> </OpenSearchDescription> </content> </entry> <entry> <title>Celtic Art & Cultures</title> <id>http://findcontext.org/api/resource/12</id> <updated>2010-01-19T00:18:35Z</updated> <summary>Images of Celtic art, artifacts, and architecture.</summary> <author> <name>Ryan Shaw</name> </author> <content type="application/opensearchdescription+xml"> <OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/"> <ShortName>Celtic Art & Cultures</ShortName> <Description>Images of Celtic art, artifacts, and architecture.</Description> <Url method="get" template="http://www.google.com/search?q=site:www.unc.edu/celtic+{{searchTerms}}" type="text/html"/> <Developer>Ryan Shaw</Developer> <InputEncoding>UTF-8</InputEncoding> </OpenSearchDescription> </content> </entry> </feed> """.format( package_id=self.p.id, package_updated=feedgenerator.rfc3339_date(self.p.last_updated) ) self.assertEqual("application/atom+xml; charset=utf-8", response["Content-Type"]) self.assertEqual(200, response.status_code) self.assert_equal_show_diff(expected, response.content)
def add_root_elements(self, handler): handler.addQuickElement("title", self.feed['title']) if self.feed['subtitle'] is not None: handler.addQuickElement("subtitle", self.feed['subtitle']) handler.addQuickElement("id", self.feed['id']) handler.addQuickElement("updated", rfc3339_date(self.latest_post_date())) if self.feed['feed_url'] is not None: self.__add_link_element(handler, self.feed['feed_url'], 'self', self.__get_link_type(self.kind)) if 'root_url' in self.feed and self.feed['root_url'] is not None: self.__add_link_element(handler, self.feed['root_url'], 'start', self.__get_link_type('navigation')) if 'search_url' in self.feed and self.feed['search_url'] is not None: self.__add_link_element(handler, self.feed['search_url'], 'search', 'application/atom+xml', _('Search')) if self.page is not None: if 'up_url' in self.feed and self.feed['up_url']: self.__add_link_element(handler, self.feed['up_url'], 'up', self.__get_link_type(self.kind), _('Up')) self.__add_link_element(handler, self.feed['feed_url'], 'first', self.__get_link_type(self.kind), _('First Page')) if self.page.has_previous(): self.__add_link_element( handler, self.feed['feed_url'] + '?page=' + str(self.page.previous_page_number()), 'previous', self.__get_link_type(self.kind), _('Previous Page')) if self.page.has_next(): self.__add_link_element( handler, self.feed['feed_url'] + '?page=' + str(self.page.paginator.num_pages), 'last', self.__get_link_type(self.kind), _('Last Page')) self.__add_link_element( handler, self.feed['feed_url'] + '?page=' + str(self.page.next_page_number()), 'next', self.__get_link_type(self.kind), _('Next Page')) if self.feed['author_name'] is not None: handler.startElement("author", {}) handler.addQuickElement("name", self.feed['author_name']) if self.feed['author_email'] is not None: handler.addQuickElement("email", self.feed['author_email']) if self.feed['author_link'] is not None: handler.addQuickElement("uri", self.feed['author_link']) handler.endElement("author") for cat in self.feed['categories']: handler.addQuickElement("category", "", {"term": cat}) if self.feed['feed_rights'] is not None: handler.addQuickElement("rights", self.feed['feed_copyright']) if self.feed['feed_icon'] is not None: handler.addQuickElement("icon", self.feed['feed_icon'])
def add_item_elements(self, handler, item): handler.addQuickElement(u"updated", rfc3339_date(item["updated"])) if item["author_name"] is not None: self._add_author_info(handler, item["author_name"], item["author_link"]) item["author_name"] = None handler.addQuickElement(u"activity:verb", item["activity"]["verb"]) obj = item["activity"]["object"] handler.startElement(u"activity:object", {}) handler.addQuickElement(u"activity:object-type", obj["object-type"]) handler.addQuickElement(u"link", u"", {"href": obj["link"], "rel": "alternate", "type": "text/html"}) handler.addQuickElement(u"content", obj["content"], {"type": "text/html"}) handler.endElement(u"activity:object") super(ActivityStreamAtomFeed, self).add_item_elements(handler, item)
def add_item_elements(self, handler, item): super(ActivityStreamsFeed, self).add_item_elements(handler, item) # <activity:verb>post</activity:verb> handler.addQuickElement(u"activity:verb", item['verb']) if 'actor' in item: # <author> handler.startElement('author', {}) # <name>Geraldine</name> handler.addQuickElement('name', item['actor'].display_name) # <uri>http://example.com/geraldine</uri> handler.addQuickElement('uri', get_tag_uri(item['actor'].get_absolute_url(), None)) # <id>tag:photopanic.example.com,2009:person/4859</id> handler.addQuickElement('id', item['actor'].get_absolute_url()) # <activity:object-type>person</activity:object-type> handler.addQuickElement('activity:object-type', 'person') # <link rel="alternate" type="text/html" href="http://example.com/geraldine" /> handler.addQuickElement('link', get_tag_uri(item['actor'].get_absolute_url(), None), {'type':'text/html'}) handler.endElement('author') # </author> if 'object' in item: # <activity:object> handler.startElement('activity:object', {}) # <id>tag:photopanic.example.com,2009:photo/4352</id> handler.addQuickElement('id', item['object_id']) # <title>My Cat</title> handler.addQuickElement('title', item['object_title']) # <published>2009-11-02T15:29:00Z</published> handler.addQuickElement( u"published", rfc3339_date(item['object_timestamp']).decode('utf-8')) # <link rel="alternate" type="text/html" href="http://example.com/geraldine/photos/4352" /> handler.addQuickElement('link', item['object'].get_absolute_url(), {'type':'text/html'}) # <activity:object-type>photo</activity:object-type> handler.addQuickElement('activity:object-type', item['object_object_type']) # </activity:object> handler.endElement('activity:object') if 'target' in item: # <activity:target> handler.startElement('activity:target', {}) # <id>tag:photopanic.example.com,2009:photo-album/2519</id> handler.addQuickElement('id', item['target_id']) # <title>My Pets</title> handler.addQuickElement('title', item['target_title']) # <link rel="alternate" type="text/html" href="/geraldine/albums/pets" /> # <activity:object-type>photo-album</activity:object-type> handler.addQuickElement('activity:object-type', str(item['target_object_type'])) # </activity:target> handler.endElement('activity:target')
def test_naive_datetime_conversion(self): """ Test that datetimes are correctly converted to the local time zone. """ # Naive date times passed in get converted to the local time zone, so # check the received zone offset against the local offset. response = self.client.get('/syndication/naive-dates/') doc = minidom.parseString(response.content) updated = doc.getElementsByTagName('updated')[0].firstChild.wholeText d = Entry.objects.latest('published').published latest = rfc3339_date(timezone.make_aware(d, TZ)) self.assertEqual(updated, latest)
def format(self, action): item = { 'id': self.get_uri(action), 'url': self.get_url(action), 'verb': action.verb, 'published': rfc3339_date(action.timestamp), 'actor': self.format_actor(action) } if action.description: item['content'] = action.description if action.target: item['target'] = self.format_target(action) if action.action_object: item['object'] = self.format_action_object(action) return item
def test_latest_post_date(self): """ Test that both the published and updated dates are considered when determining the latest post date. """ # this feed has a `published` element with the latest date response = self.client.get('/syndication/atom/') feed = minidom.parseString(response.content).firstChild updated = feed.getElementsByTagName('updated')[0].firstChild.wholeText d = Entry.objects.latest('published').published latest_published = rfc3339_date(timezone.make_aware(d, TZ)) self.assertEqual(updated, latest_published) # this feed has an `updated` element with the latest date response = self.client.get('/syndication/latest/') feed = minidom.parseString(response.content).firstChild updated = feed.getElementsByTagName('updated')[0].firstChild.wholeText d = Entry.objects.exclude(pk=5).latest('updated').updated latest_updated = rfc3339_date(timezone.make_aware(d, TZ)) self.assertEqual(updated, latest_updated)
def resources_to_atom(cls, resources, name='All resources', description='All available resources.', updated=datetime.now(), package_uri=None): if not package_uri: package_uri = 'http://%s/api/resource/' % Site.objects.get_current().domain feed = a.feed( a.title(name), a.id(package_uri), a.updated(feedgenerator.rfc3339_date(updated)), a.subtitle(description), a.link(rel='self', href=package_uri)) for resource in resources: feed.append(a.entry( a.title(resource.short_name), a.id(resource.uri), a.updated(feedgenerator.rfc3339_date(resource.last_updated)), a.summary(resource.description), a.author(a.name(resource.developer)), a.content( resource.open_search_description, type='application/opensearchdescription+xml'))) return feed
def test_latest_post_date(self): """ Test that both the published and updated dates are considered when determining the latest post date. """ # this feed has a `published` element with the latest date response = self.client.get("/syndication/atom/") feed = minidom.parseString(response.content).firstChild updated = feed.getElementsByTagName("updated")[0].firstChild.wholeText d = Entry.objects.latest("published").published latest_published = rfc3339_date(timezone.make_aware(d, TZ)) self.assertEqual(updated, latest_published) # this feed has an `updated` element with the latest date response = self.client.get("/syndication/latest/") feed = minidom.parseString(response.content).firstChild updated = feed.getElementsByTagName("updated")[0].firstChild.wholeText d = Entry.objects.exclude(pk=5).latest("updated").updated latest_updated = rfc3339_date(timezone.make_aware(d, TZ)) self.assertEqual(updated, latest_updated)
def test_all_feed_with_one_item(self): response = self.app.get('/results/all.atom') root = etree.XML(response.content) xml_pretty = etree.tounicode(root, pretty_print=True) result_event = ResultEvent.objects.first() expected = '''<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en-gb"> <title>Election results from example.com (with extra data)</title> <link href="http://example.com/" rel="alternate"/> <link href="http://example.com/results/all.atom" rel="self"/> <id>http://example.com/</id> <updated>{updated}</updated> <entry> <title>Tessa Jowell (Labour Party) won in Dulwich and West Norwood</title> <link href="http://example.com/#{item_id}" rel="alternate"/> <published>{updated}</published> <updated>{updated}</updated> <author> <name>john</name> </author> <id>http://example.com/#{item_id}</id> <summary type="html">A example.com volunteer recorded at {space_separated} that Tessa Jowell (Labour Party) won the ballot in Dulwich and West Norwood, quoting the source 'Seen on the BBC news'.</summary> <retraction>0</retraction> <election_slug>2015</election_slug> <election_name>2015 General Election</election_name> <election_date>{election_date}</election_date> <post_id>65808</post_id> <winner_person_id>4322</winner_person_id> <winner_person_name>Tessa Jowell</winner_person_name> <winner_party_id>party:53</winner_party_id> <winner_party_name>Labour Party</winner_party_name> <user_id>{user_id}</user_id> <post_name>Dulwich and West Norwood</post_name> <information_source>Seen on the BBC news</information_source> <image_url>https://example.com{image_url_path}</image_url> <parlparse_id>uk.org.publicwhip/person/123456</parlparse_id> </entry> </feed> '''.format( updated=rfc3339_date(result_event.created), space_separated=result_event.created.strftime("%Y-%m-%d %H:%M:%S"), item_id=result_event.id, user_id=self.user.id, election_date=self.election.election_date, image_url_path=self.example_image.image.url, ) self.compare_xml(expected, xml_pretty)
def format(self, action): """ Returns a formatted dictionary for the given action. """ item = { 'verb': action.verb, 'published': rfc3339_date(action.timestamp), 'actor': self.format_actor(action), } if action.description: item['description'] = action.description if action.action_object: objectInfo = self.format_action_object(action) item['object_type'] = objectInfo['objectType'] item['object_name'] = objectInfo['objectName'] return item
def atomfeed(request): """ Display Atom Feed representing activities in document collection """ entries = AtomEntry.objects.order_by("-updated") context = { 'entries': AtomEntry.objects.order_by("-updated"), 'last_updated': rfc3339_date(entries[0].updated) if entries else "", 'feed_id': settings.FST_DATASET_URI, 'feed_title': settings.FST_DATASET_TITLE, 'feed_contact_name': settings.FST_ORG_CONTACT_NAME, 'feed_contact_url': settings.FST_ORG_CONTACT_URL, 'feed_contact_email': settings.FST_ORG_CONTACT_EMAIL, 'fst_instance_url': settings.FST_INSTANCE_URL, } return HttpResponse( _response(request, 'atomfeed.xml', context), content_type="application/atom+xml; charset=utf-8")
def format(self, action): """ Returns a formatted dictionary for the given action. """ item = { '@context': 'https://www.w3.org/ns/activitystreams', 'summary': str(action), 'type': str(action.description), 'id': self.get_uri(action), 'url': self.get_url(action), 'verb': action.verb, 'published': rfc3339_date(action.timestamp), 'actor': self.format_actor(action), } if action.target: item['target'] = self.format_target(action) if action.action_object: item['object'] = self.format_action_object(action) return item
def format(self, action): """ Returns a formatted dictionary for the given action. """ item = { 'id': self.get_uri(action), 'url': self.get_url(action), 'verb': action.verb, 'published': rfc3339_date(action.timestamp), 'actor': self.format_actor(action), 'title': text_type(action), } if action.description: item['content'] = action.description if action.target: item['target'] = self.format_target(action) if action.action_object: item['object'] = self.format_action_object(action) return item
def add_item_elements(self, handler, item): handler.addQuickElement(u'updated', rfc3339_date(item['updated'])) if item['author_name'] is not None: self._add_author_info( handler, item['author_name'], item['author_link']) item['author_name'] = None handler.addQuickElement(u'activity:verb', item['activity']['verb']) obj = item['activity']['object'] handler.startElement(u'activity:object', {}) handler.addQuickElement(u'activity:object-type', obj['object-type']) handler.addQuickElement(u'link', u'', { 'href': obj['link'], 'rel': 'alternate', 'type': 'text/html', }) handler.addQuickElement( u'content', obj['content'], {'type': 'text/html'}) handler.endElement(u'activity:object') super(ActivityStreamAtomFeed, self).add_item_elements(handler, item)
def add_item_elements(self, handler, item): handler.addQuickElement(u'updated', rfc3339_date(item['updated'])) if item['author_name'] is not None: self._add_author_info(handler, item['author_name'], item['author_link']) item['author_name'] = None handler.addQuickElement(u'activity:verb', item['activity']['verb']) obj = item['activity']['object'] handler.startElement(u'activity:object', {}) handler.addQuickElement(u'activity:object-type', obj['object-type']) handler.addQuickElement(u'link', u'', { 'href': obj['link'], 'rel': 'alternate', 'type': 'text/html', }) handler.addQuickElement(u'content', obj['content'], {'type': 'text/html'}) handler.endElement(u'activity:object') super(ActivityStreamAtomFeed, self).add_item_elements(handler, item)
def add_item_elements(self, item): item_elements = OrderedDict() item_elements['id'] = item['link'] item_elements['url'] = item['link'] item_elements['title'] = item['title'] if item['description'] is not None: item_elements['summary'] = item['description'] content = '' if 'image' in item: if use_feed_image and item['image'] != "": content += '<img src="%s"><hr>' % (item['image']) if 'content' in item: content += item['content'] item_elements['content_html'] = content if item['pubdate'] is not None: item_elements['date_published'] = rfc3339_date(item['pubdate']) return item_elements
def add_item_elements(self, handler, item): super(ActivityStreamsFeed, self).add_item_elements(handler, item) handler.addQuickElement("activity: verb", item['verb']) if 'actor' in item: handler.startElement('author', {}) handler.addQuickElement('name', item['actor'].display_name) handler.addQuickElement( 'uri', get_tag_uri(item['actor'].get_absolute_url(), None)) handler.addQuickElement('id', item['actor'].get_absolute_url()) handler.addQuickElement('activity: object-type', 'person') handler.addQuickElement( 'link', get_tag_uri(item['actor'].get_absolute_url(), None), {'type': 'text/html'}) handler.endElement('author') if 'object' in item: handler.startElement('activity: object', {}) handler.addQuickElement('id', item['object_id']) handler.addQuickElement('title', item['object_title']) handler.addQuickElement( 'published', rfc3339_date(item['object_timestamp']).decode('utf-8')) handler.addQuickElement('link', item['object'].get_absolute_url(), {'type': 'text/html'}) handler.addQuickElement('activity: object-type', item['object_object_type']) handler.endElement('activity: object') if 'target' in item: handler.startElement('activity: target', {}) handler.addQuickElement('id', item['target_id']) handler.addQuickElement('title', item['target_title']) handler.addQuickElement('activity: object-type', str(item['target_object_type'])) handler.endElement('activity: target')
def editlog_to_collection_item(self, editlog_object, perm_level="full"): def add_actor(editlog_object, perm_level=perm_level): actor = { "type": "Person", "id": "{0}/{1}".format( self.base_uri_for_arches + reverse("user_profile_manager"), editlog_object.userid) } if perm_level == "full": actor["name"] = "{0}, {1}".format( editlog_object.user_lastname, editlog_object.user_firstname) if actor["name"] == ", ": del actor["name"] actor["tag"] = editlog_object.user_username if actor["tag"] == "null": del actor["tag"] return actor def add_resource(editlog_object, perm_level=perm_level): obj = {"type": "Object"} try: r = Resource.objects.get(pk=editlog_object.resourceinstanceid) rclass = r.get_root_ontology() if rclass: obj = {"type": rclass} except ObjectDoesNotExist: pass if editlog_object.edittype == 'delete': # Tombstone instead. obj["formerType"] = obj["type"] obj["type"] = "Tombstone" obj["url"] = self.base_uri_for_arches + reverse( "resources", args=(editlog_object.resourceinstanceid, )) return obj def add_tile(editlog_object, perm_level=perm_level): obj = {"type": "Object"} # Tile? obj['url'] = "{0}node/{1}/tile/{2}".format( settings.ARCHES_NAMESPACE_FOR_DATA_EXPORT, editlog_object.nodegroupid, editlog_object.tileinstanceid) return obj item = { "type": self.type_mapping.get(editlog_object.edittype, "Activity") } # what's the correct attr here? item["endTime"] = rfc3339_date(editlog_object.timestamp) if item['type'] in ("Create", "Delete"): # activity affects main resource item["actor"] = add_actor(editlog_object) item["object"] = add_resource(editlog_object) if item['type'] in ("Update"): # activity affects a Tile associated with a resource # If a Tile associated with a resource is altered, bubble that # change up to be about the Resource, and mark it as an 'Update' item["actor"] = add_actor(editlog_object) # item["object"] = add_tile(editlog_object) item["object"] = add_resource(editlog_object) return item
def test_all_feed_with_a_correction(self): response = self.app.get('/results/all.atom') root = etree.XML(response.content) xml_pretty = etree.tounicode(root, pretty_print=True) expected = '''<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en-gb"> <title>Election results from example.com (with extra data)</title> <link href="http://example.com/" rel="alternate"/> <link href="http://example.com/results/all.atom" rel="self"/> <id>http://example.com/</id> <updated>{updated[0]}</updated> <entry> <title>Tessa Jowell (Labour Party) won in Dulwich and West Norwood</title> <link href="http://example.com/#{item_id[0]}" rel="alternate"/> <published>{updated[0]}</published> <updated>{updated[0]}</updated> <author> <name>john</name> </author> <id>http://example.com/#{item_id[0]}</id> <summary type="html">A example.com volunteer recorded at {space_separated[0]} that Tessa Jowell (Labour Party) won the ballot in Dulwich and West Norwood, quoting the source 'Seen on the BBC news'.</summary> <retraction>0</retraction> <election_slug>2015</election_slug> <election_name>2015 General Election</election_name> <election_date>{election_date}</election_date> <post_id>65808</post_id> <winner_person_id>4322</winner_person_id> <winner_person_name>Tessa Jowell</winner_person_name> <winner_party_id>party:53</winner_party_id> <winner_party_name>Labour Party</winner_party_name> <user_id>{user_id}</user_id> <post_name>Dulwich and West Norwood</post_name> <information_source>Seen on the BBC news</information_source> <parlparse_id>uk.org.publicwhip/person/123456</parlparse_id> </entry> <entry> <title>Correction: retracting the statement that Tessa Jowell (Labour Party) won in Dulwich and West Norwood</title> <link href="http://example.com/#{item_id[1]}" rel="alternate"/> <published>{updated[1]}</published> <updated>{updated[1]}</updated> <author> <name>john</name> </author> <id>http://example.com/#{item_id[1]}</id> <summary type="html">At {space_separated[1]}, a example.com volunteer retracted the previous assertion that Tessa Jowell (Labour Party) won the ballot in Dulwich and West Norwood, quoting the source 'Result recorded in error, retracting'.</summary> <retraction>1</retraction> <election_slug>2015</election_slug> <election_name>2015 General Election</election_name> <election_date>{election_date}</election_date> <post_id>65808</post_id> <winner_person_id>4322</winner_person_id> <winner_person_name>Tessa Jowell</winner_person_name> <winner_party_id>party:53</winner_party_id> <winner_party_name>Labour Party</winner_party_name> <user_id>{user_id}</user_id> <post_name>Dulwich and West Norwood</post_name> <information_source>Result recorded in error, retracting</information_source> <parlparse_id>uk.org.publicwhip/person/123456</parlparse_id> </entry> <entry> <title>James Barber (Liberal Democrats) won in Dulwich and West Norwood</title> <link href="http://example.com/#{item_id[2]}" rel="alternate"/> <published>{updated[2]}</published> <updated>{updated[2]}</updated> <author> <name>john</name> </author> <id>http://example.com/#{item_id[2]}</id> <summary type="html">A example.com volunteer recorded at {space_separated[2]} that James Barber (Liberal Democrats) won the ballot in Dulwich and West Norwood, quoting the source 'Seen on Sky News'.</summary> <retraction>0</retraction> <election_slug>2015</election_slug> <election_name>2015 General Election</election_name> <election_date>{election_date}</election_date> <post_id>65808</post_id> <winner_person_id>4493</winner_person_id> <winner_person_name>James Barber</winner_person_name> <winner_party_id>party:90</winner_party_id> <winner_party_name>Liberal Democrats</winner_party_name> <user_id>{user_id}</user_id> <post_name>Dulwich and West Norwood</post_name> <information_source>Seen on Sky News</information_source> </entry> </feed> '''.format( updated=[ rfc3339_date(result_event.created) for result_event in self.events ], space_separated=[ result_event.created.strftime("%Y-%m-%d %H:%M:%S") for result_event in self.events ], item_id=[result_event.id for result_event in self.events], user_id=self.user.id, election_date=self.election.election_date, ) self.compare_xml(expected, xml_pretty)
def rfc3339_localized(self, date_instance): """Return the date instance as a localized, RFC3339 formatted string.""" return rfc3339_date( self.location.timezone.localize( datetime.datetime.combine(date_instance, datetime.time())))
def add_item_elements(self, handler, item): handler.addQuickElement("title", item['title']) if 'summary' in item and item['summary'] is not None: handler.addQuickElement('summary', item['summary'], {"type": "text"}) self.__add_link_element(handler, item['link'], '', self.__get_link_type(item['link_type'])) if item['pubdate'] is not None: handler.addQuickElement('published', rfc3339_date(item['pubdate'])) if item['updateddate'] is not None: handler.addQuickElement('updated', rfc3339_date(item['updateddate'])) # Author information. if item['author_name'] is not None: handler.startElement("author", {}) handler.addQuickElement("name", item['author_name']) if item['author_email'] is not None: handler.addQuickElement("email", item['author_email']) if item['author_link'] is not None: handler.addQuickElement("uri", item['author_link']) handler.endElement("author") # Unique ID. if item['unique_id'] is not None: unique_id = item['unique_id'] else: unique_id = get_tag_uri(item['link'], item['pubdate']) handler.addQuickElement("id", unique_id) # Summary. if item['description'] is not None: handler.addQuickElement("content", item['description'], {"type": "text"}) # Categories. for cat in item['categories']: handler.addQuickElement("category", "", {"term": cat}) # Rights. if item['item_copyright'] is not None: handler.addQuickElement("rights", item['item_copyright']) if 'download_links' in item and item['download_links'] is not None: for link in item['download_links']: self.__add_link_element(handler, link['href'], 'http://opds-spec.org/acquisition', link['type']) if 'authors' in item and item['authors'] is not None: for author in item['authors']: handler.startElement("author", {}) handler.addQuickElement("name", author['name']) if author['url'] is not None: handler.addQuickElement("uri", author['url']) handler.endElement("author") if 'image' in item and item[ 'image'] is not None and 'image_type' in item and item[ 'image_type'] is not None: self.__add_link_element(handler, item['image'], 'http://opds-spec.org/image', item['image_type']) if 'isbn' in item and item['isbn'] is not None: handler.addQuickElement('dc:identifier', 'urn:isbn:' + item['isbn']) if 'year' in item and item['year'] is not None: handler.addQuickElement('dc:issued', item['year']) if 'language' in item and item['language'] is not None: handler.addQuickElement('dc:language', item['language'])