def feed_from_annotations( annotations, atom_url, annotation_url, annotation_api_url=None, html_url=None, title=None, subtitle=None): """Return an Atom feed for the given list of annotations. :returns: A logical representation of an Atom feed as a Python dict containing all of the data that a template would need to render the feed to XML (including a list of dicts for the feed's entries). :rtype: dict """ annotations = [presenters.AnnotationHTMLPresenter(a) for a in annotations] links = [{"rel": "self", "type": "application/atom+xml", "href": atom_url}] if html_url: links.append( {"rel": "alternate", "type": "text/html", "href": html_url}) entries = [ _feed_entry_from_annotation(a, annotation_url, annotation_api_url) for a in annotations] feed = { "id": atom_url, "title": title or _("Hypothesis Stream"), "subtitle": subtitle or _("The Web. Annotated"), "entries": entries, "links": links } if annotations: feed["updated"] = annotations[0]["updated"] return feed
def feed_from_annotations( # pylint: disable=too-many-arguments annotations, annotation_url, rss_url, html_url, title, description ): """ Return an RSS feed for the given list of annotations. :returns: A logical representation of an RSS feed as a Python dict containing all of the data that a template would need to render the feed to XML (including a list of dicts for the feed's items). :rtype: dict """ annotations = [presenters.AnnotationHTMLPresenter(a) for a in annotations] feed = { "title": title, "rss_url": rss_url, "html_url": html_url, "description": description, # This is called entries not items so as not to clash with the dict's # standard .items() method. "entries": [ _feed_item_from_annotation(annotation, annotation_url) for annotation in annotations ], } if annotations: feed["pubDate"] = _pubdate_string(annotations[0].updated) return feed
def feed_from_annotations(annotations, annotation_url, rss_url, html_url, title, description): """Return an RSS feed for the given list of annotations. :returns: A logical representation of an RSS feed as a Python dict containing all of the data that a template would need to render the feed to XML (including a list of dicts for the feed's items). :rtype: dict """ annotations = [presenters.AnnotationHTMLPresenter(a) for a in annotations] feed = { 'title': title, 'rss_url': rss_url, 'html_url': html_url, 'description': description, # This is called entries not items so as not to clash with the dict's # standard .items() method. 'entries': [ _feed_item_from_annotation(annotation, annotation_url) for annotation in annotations] } if annotations: feed['pubDate'] = parser.parse(annotations[0]['updated']).strftime( '%a, %d %b %Y %H:%M:%S %Z') return feed
def execute(request, query, page_size): search_result = _execute_search(request, query, page_size) result = ActivityResults(total=search_result.total, aggregations=search_result.aggregations, timeframes=[]) if result.total == 0: return result # Load all referenced annotations from the database, bucket them, and add # the buckets to result.timeframes. anns = _fetch_annotations(request.db, search_result.annotation_ids) result.timeframes.extend(bucketing.bucket(anns.all())) # Fetch all groups group_pubids = set([a.groupid for t in result.timeframes for b in t.document_buckets.values() for a in b.annotations]) groups = {g.pubid: g for g in _fetch_groups(request.db, group_pubids)} # Add group information to buckets and present annotations for timeframe in result.timeframes: for bucket in timeframe.document_buckets.values(): for index, annotation in enumerate(bucket.annotations): bucket.annotations[index] = { 'annotation': presenters.AnnotationHTMLPresenter(annotation), 'group': groups.get(annotation.groupid) } return result
def _annotation(self, annotation=None, **kwargs): """Return an AnnotationHTMLPresenter for the given annotation. If no annotation is given a mock will be used, and any keyword arguments will be forwarded to the mock.Mock() constructor. """ return presenters.AnnotationHTMLPresenter(annotation or mock.Mock(**kwargs))
def test_it_does_not_crash_when_annotation_has_no_document(self): annotation = mock.Mock(document=None) presenter = presenters.AnnotationHTMLPresenter(annotation) # Some AnnotationHTMLPresenter properties rely on the annotation's # document. Call them all to make sure that none of them crash when # the document is None. # pylint: disable=pointless-statement presenter.document_link presenter.hostname_or_filename presenter.href presenter.link_text presenter.title
def _read_group(request, group): """Return the rendered "Share this group" page. This is the page that's shown when a user who is already a member of a group visits the group's URL. """ url = request.route_url('group_read', pubid=group.pubid, slug=group.slug) result = search.search(request, private=False, params={ "group": group.pubid, "limit": 1000 }) annotations = [ presenters.AnnotationHTMLPresenter(storage.annotation_from_dict(a)) for a in result['rows'] ] # Group the annotations by URI. # Create a dict mapping the (normalized) URIs of the annotated documents # to the most recent annotation of each document. annotations_by_uri = collections.OrderedDict() for annotation in annotations: normalized_uri = uri.normalize(annotation.uri) if normalized_uri not in annotations_by_uri: annotations_by_uri[normalized_uri] = annotation if len(annotations_by_uri) >= 25: break document_links = [ annotation.document_link for annotation in annotations_by_uri.values() ] template_data = { 'group': group, 'group_url': url, 'document_links': document_links } return renderers.render_to_response( renderer_name='h:templates/groups/share.html.jinja2', value=template_data, request=request)
def execute(request, query, page_size): search_result = _execute_search(request, query, page_size) result = ActivityResults( total=search_result.total, aggregations=search_result.aggregations, timeframes=[], ) if result.total == 0: return result # Load all referenced annotations from the database, bucket them, and add # the buckets to result.timeframes. anns = fetch_annotations(request.db, search_result.annotation_ids) result.timeframes.extend(bucketing.bucket(anns)) # Fetch all groups group_pubids = { a.groupid for t in result.timeframes for b in t.document_buckets.values() for a in b.annotations } groups = {g.pubid: g for g in _fetch_groups(request.db, group_pubids)} # Add group information to buckets and present annotations for timeframe in result.timeframes: for bucket in timeframe.document_buckets.values(): bucket.presented_annotations = [] for annotation in bucket.annotations: bucket.presented_annotations.append({ "annotation": presenters.AnnotationHTMLPresenter(annotation), "group": groups.get(annotation.groupid), "html_link": links.html_link(request, annotation), "incontext_link": links.incontext_link(request, annotation), }) return result
def test_it_does_not_init_DocumentHTMLPresenter_if_no_document( self, DocumentHTMLPresenter): """ It shouldn't init DocumentHTMLPresenter if document is None. We don't want DocumentHTMLPresenter to be initialized with None for a document, so make sure that AnnotationHTMLPresenter doesn't do so. """ annotation = mock.Mock(document=None) presenter = presenters.AnnotationHTMLPresenter(annotation) # Call all these as well to make sure that none of them cause a # DocumentHTMLPresenter to be initialized. # pylint: disable=pointless-statement presenter.document_link presenter.hostname_or_filename presenter.href presenter.link_text presenter.title assert not DocumentHTMLPresenter.called
def execute(request, query, page_size): search_result = _execute_search(request, query, page_size) result = ActivityResults(total=search_result.total, aggregations=search_result.aggregations, timeframes=[]) if result.total == 0: return result # Load all referenced annotations from the database, bucket them, and add # the buckets to result.timeframes. anns = fetch_annotations(request.db, search_result.annotation_ids) result.timeframes.extend(bucketing.bucket(anns)) # Fetch all groups group_pubids = set([a.groupid for t in result.timeframes for b in t.document_buckets.values() for a in b.annotations]) groups = {g.pubid: g for g in _fetch_groups(request.db, group_pubids)} # Add group information to buckets and present annotations result.docs = dict() for timeframe in result.timeframes: for bucket in timeframe.document_buckets.values(): bucket.presented_annotations = [] for annotation in bucket.annotations: bucket.presented_annotations.append({ 'annotation': presenters.AnnotationHTMLPresenter(annotation), 'group': groups.get(annotation.groupid), 'html_link': links.html_link(request, annotation), 'incontext_link': links.incontext_link(request, annotation) }) # XXX: redo the bucketing, fake a bucket if annotation.document.title not in result.docs: result.docs[annotation.document.title] = doc = lambda: None doc.title = annotation.document.title doc.annotations = [] doc.tags = set() doc.users = set() doc.annotations_count = 0 doc.incontext_link = types.MethodType(_incontext_link, doc) presented_document = presenters.DocumentHTMLPresenter(annotation.document) if presented_document.web_uri: parsed = urlparse.urlparse(presented_document.web_uri) doc.uri = parsed.geturl() doc.domain = parsed.netloc else: doc.domain = _('Local file') doc = result.docs[annotation.document.title] doc.annotations.append(annotation) doc.tags.update(set(annotation.tags)) doc.users.add(annotation.userid) doc.annotations_count += 1 for key in result.docs: doc = result.docs[key] doc.annotations = sorted(doc.annotations, cmp=_sort_by_position) doc.presented_annotations = [] for annotation in doc.annotations: doc.presented_annotations.append({ 'annotation': presenters.AnnotationHTMLPresenter(annotation), 'group': groups.get(annotation.groupid), 'html_link': links.html_link(request, annotation), 'incontext_link': links.incontext_link(request, annotation) }) return result
def read_group(request, group, language=None, search_url=None, user=None, render=True): """ Return the rendered "Share this group" page. This is the page that's shown when a user who is already a member of a group visits the group's URL. :param request: a request object :param group: a group object :param language: a language object to search or None :param search_url: the URL to search or None :param user: the user object to search or None :param render: whether or not to return a context object :return: if render, a context object for a template. If render is false, a list of annotations """ if group is None: public_group_id = "__world__" slug = "Public" else: public_group_id = group.pubid slug = group.slug url = request.route_url('group_read', pubid=public_group_id, slug=slug) parameters = {"group": public_group_id, "limit": 1000} if language: parameters['language'] = language.pubid if search_url: parameters['uri'] = search_url if user: parameters['user'] = user result = search.search(request, private=False, params=parameters) annotations = [presenters.AnnotationHTMLPresenter(h.models.Annotation(a)) for a in result['rows']] if render: # Group the annotations by URI. # Create a dict mapping the (normalized) URIs of the annotated documents # to the most recent annotation of each document. annotations_by_uri = collections.OrderedDict() for annotation in annotations: normalized_uri = uri.normalize(annotation.uri) if normalized_uri not in annotations_by_uri: annotations_by_uri[normalized_uri] = annotation if len(annotations_by_uri) >= 25: break document_links = [annotation.document_link for annotation in annotations_by_uri.values()] template_data = { 'group': group, 'group_url': url, 'document_links': document_links} return renderers.render_to_response( renderer_name='h:templates/groups/share.html.jinja2', value=template_data, request=request) else: return annotations