Exemple #1
0
    def detailed_author(cls, contributor):
        """Turn a Contributor into a detailed <author> tag."""
        children = []
        children.append(AtomFeed.name(contributor.display_name or ""))
        sort_name = AtomFeed.makeelement("{%s}sort_name" % AtomFeed.SIMPLIFIED_NS)
        sort_name.text = contributor.sort_name

        children.append(sort_name)

        if contributor.family_name:
            family_name = AtomFeed.makeelement(AtomFeed.schema_("family_name"))
            family_name.text = contributor.family_name
            children.append(family_name)

        if contributor.wikipedia_name:
            wikipedia_name = AtomFeed.makeelement(
                "{%s}wikipedia_name" % AtomFeed.SIMPLIFIED_NS)
            wikipedia_name.text = contributor.wikipedia_name
            children.append(wikipedia_name)

        if contributor.viaf:
            viaf_tag = AtomFeed.makeelement(AtomFeed.schema_("sameas"))
            viaf_tag.text = "http://viaf.org/viaf/%s" % contributor.viaf
            children.append(viaf_tag)

        if contributor.lc:
            lc_tag = AtomFeed.makeelement(AtomFeed.schema_("sameas"))
            lc_tag.text = "http://id.loc.gov/authorities/names/%s" % contributor.lc
            children.append(lc_tag)


        return AtomFeed.author(*children)
Exemple #2
0
    def minimal_opds_entry(cls, identifier, cover, description, quality):
        elements = []
        representations = []
        most_recent_update = None
        if cover:
            cover_representation = cover.representation
            representations.append(cover.representation)
            cover_link = AtomFeed.makeelement(
                "link", href=cover_representation.mirror_url,
                type=cover_representation.media_type, rel=Hyperlink.IMAGE)
            elements.append(cover_link)
            if cover_representation.thumbnails:
                thumbnail = cover_representation.thumbnails[0]
                representations.append(thumbnail)
                thumbnail_link = AtomFeed.makeelement(
                    "link", href=thumbnail.mirror_url,
                    type=thumbnail.media_type,
                    rel=Hyperlink.THUMBNAIL_IMAGE
                )
                elements.append(thumbnail_link)
        if description:
            content = description.representation.content
            if isinstance(content, str):
                content = content.decode("utf8")
            description_e = AtomFeed.summary(content, type='html')
            elements.append(description_e)
            representations.append(description.representation)

        if quality:
            elements.append(
                Annotator.rating_tag(Measurement.QUALITY, quality))

        # The update date is the most recent date any of these
        # resources were mirrored/fetched.
        potential_update_dates = [
            r.mirrored_at or r.fetched_at for r in representations
            if r.mirrored_at or r.fetched_at
        ]
        
        if potential_update_dates:
            update_date = max(potential_update_dates)
            elements.append(AtomFeed.updated(AtomFeed._strftime(update_date)))
        entry = AtomFeed.entry(
            AtomFeed.id(identifier.urn),
            AtomFeed.title(OPDSFeed.NO_TITLE),
            *elements
        )
        return entry
Exemple #3
0
    def add_breadcrumbs(self, lane, annotator, include_lane=False):
        """Add list of ancestor links in a breadcrumbs element."""
        # Ensure that lane isn't top-level before proceeding
        if annotator.lane_url(lane) != annotator.default_lane_url():
            breadcrumbs = AtomFeed.makeelement("{%s}breadcrumbs" % AtomFeed.SIMPLIFIED_NS)

            # Add root link
            root_url = annotator.default_lane_url()
            breadcrumbs.append(
                AtomFeed.link(title=annotator.top_level_title(), href=root_url)
            )
            
            # Add links for all visible ancestors that aren't root
            for ancestor in reversed(lane.visible_ancestors()):
                lane_url = annotator.lane_url(ancestor)
                if lane_url != root_url:
                    breadcrumbs.append(
                        AtomFeed.link(title=ancestor.display_name, href=lane_url)
                    )

            # Include link to lane
            # For search, breadcrumbs include the searched lane
            if include_lane:
                breadcrumbs.append(
                    AtomFeed.link(title=lane.display_name, href=annotator.lane_url(lane))
                )

            self.feed.append(breadcrumbs)
Exemple #4
0
 def rating_tag(cls, type_uri, value):
     """Generate a schema:Rating tag for the given type and value."""
     rating_tag = AtomFeed.makeelement(AtomFeed.schema_("Rating"))
     value_key = AtomFeed.schema_('ratingValue')
     rating_tag.set(value_key, "%.4f" % value)
     if type_uri:
         type_key = AtomFeed.schema_('additionalType')
         rating_tag.set(type_key, type_uri)
     return rating_tag
Exemple #5
0
 def series(cls, series_name, series_position):
     """Generate a schema:Series tag for the given name and position."""
     if not series_name:
         return None
     series_details = dict()
     series_details['name'] = series_name
     if series_position:
         series_details[AtomFeed.schema_('position')] = unicode(series_position)
     series_tag = AtomFeed.makeelement(AtomFeed.schema_("Series"), **series_details)
     return series_tag
Exemple #6
0
 def indirect_acquisition(cls, indirect_types):
     top_level_parent = None
     parent = None
     for t in indirect_types:
         indirect_link = AtomFeed.makeelement(
             "{%s}indirectAcquisition" % AtomFeed.OPDS_NS, type=t)
         if parent is not None:
             parent.extend([indirect_link])
         parent = indirect_link
         if top_level_parent is None:
             top_level_parent = indirect_link
     return top_level_parent
Exemple #7
0
 def link(cls, rel, href, type):
     return AtomFeed.makeelement("link", type=type, rel=rel, href=href)
Exemple #8
0
    def _make_entry_xml(self, work, license_pool, edition, identifier,
                        lane_link):

        # Find the .epub link
        epub_href = None
        p = None

        links = []
        cover_quality = 0
        qualities = []
        if work:
            qualities.append(("Work quality", work.quality))
        full_url = None

        thumbnail_urls, full_urls = self.annotator.cover_links(work)
        for rel, urls in (
                (Hyperlink.IMAGE, full_urls),
                (Hyperlink.THUMBNAIL_IMAGE, thumbnail_urls)):
            for url in urls:
                image_type = "image/png"
                if url.endswith(".jpeg") or url.endswith(".jpg"):
                    image_type = "image/jpeg"
                elif url.endswith(".gif"):
                    image_type = "image/gif"
                links.append(AtomFeed.link(rel=rel, href=url, type=image_type))
           

        permalink = self.annotator.permalink_for(work, license_pool, identifier)
        content = self.annotator.content(work)
        if isinstance(content, str):
            content = content.decode("utf8")

        content_type = 'html'

        kw = {}
        if edition.medium:
            additional_type = Edition.medium_to_additional_type.get(
                edition.medium)
            if not additional_type:
                logging.warn("No additionalType for medium %s",
                             edition.medium)
            additional_type_field = AtomFeed.schema_("additionalType")
            kw[additional_type_field] = additional_type

        entry = AtomFeed.entry(
            AtomFeed.id(permalink),
            AtomFeed.title(edition.title or OPDSFeed.NO_TITLE),
            **kw
        )
        if edition.subtitle:
            subtitle_tag = AtomFeed.makeelement(AtomFeed.schema_("alternativeHeadline"))
            subtitle_tag.text = edition.subtitle
            entry.append(subtitle_tag)

        if license_pool:
            provider_name_attr = "{%s}ProviderName" % AtomFeed.BIBFRAME_NS
            kwargs = {provider_name_attr : license_pool.data_source.name}
            data_source_tag = AtomFeed.makeelement(
                "{%s}distribution" % AtomFeed.BIBFRAME_NS,
                **kwargs
            )
            entry.extend([data_source_tag])

        author_tags = self.annotator.authors(work, license_pool, edition, identifier)
        entry.extend(author_tags)

        if edition.series:
            entry.extend([self.annotator.series(edition.series, edition.series_position)])

        if content:
            entry.extend([AtomFeed.summary(content, type=content_type)])

        entry.extend([
            AtomFeed.updated(AtomFeed._strftime(datetime.datetime.utcnow())),
        ])

        permanent_work_id_tag = AtomFeed.makeelement("{%s}pwid" % AtomFeed.SIMPLIFIED_NS)
        permanent_work_id_tag.text = edition.permanent_work_id
        entry.append(permanent_work_id_tag)

        entry.extend(links)

        categories_by_scheme = self.annotator.categories(work)
        category_tags = []
        for scheme, categories in categories_by_scheme.items():
            for category in categories:
                if isinstance(category, basestring):
                    category = dict(term=category)
                category = dict(map(unicode, (k, v)) for k, v in category.items())
                category_tag = AtomFeed.category(scheme=scheme, **category)
                category_tags.append(category_tag)
        entry.extend(category_tags)

        # print " ID %s TITLE %s AUTHORS %s" % (tag, work.title, work.authors)
        language = edition.language_code
        if language:
            language_tag = AtomFeed.makeelement("{%s}language" % AtomFeed.DCTERMS_NS)
            language_tag.text = language
            entry.append(language_tag)

        if edition.publisher:
            publisher_tag = AtomFeed.makeelement("{%s}publisher" % AtomFeed.DCTERMS_NS)
            publisher_tag.text = edition.publisher
            entry.extend([publisher_tag])

        # We use Atom 'published' for the date the book first became
        # available to people using this application.
        now = datetime.datetime.utcnow()
        today = datetime.date.today()
        if license_pool and license_pool.availability_time:
            avail = license_pool.availability_time
            if isinstance(avail, datetime.datetime):
                avail = avail.date()
            if avail <= today:
                availability_tag = AtomFeed.makeelement("published")
                # TODO: convert to local timezone.
                availability_tag.text = AtomFeed._strftime(license_pool.availability_time)
                entry.extend([availability_tag])

        # Entry.issued is the date the ebook came out, as distinct
        # from Entry.published (which may refer to the print edition
        # or some original edition way back when).
        #
        # For Dublin Core 'created' we use Entry.issued if we have it
        # and Entry.published if not. In general this means we use
        # issued date for Gutenberg and published date for other
        # sources.
        #
        # We use dc:created instead of dc:issued because dc:issued is
        # commonly conflated with atom:published.
        #
        # For the date the book was added to our collection we use
        # atom:published.
        issued = edition.issued or edition.published
        if (isinstance(issued, datetime.datetime) 
            or isinstance(issued, datetime.date)):
            issued_already = False
            if isinstance(issued, datetime.datetime):
                issued_already = (issued <= now)
            elif isinstance(issued, datetime.date):
                issued_already = (issued <= today)
            if issued_already:
                issued_tag = AtomFeed.makeelement("{%s}created" % AtomFeed.DCTERMS_NS)
                # TODO: convert to local timezone, not that it matters much.
                issued_tag.text = issued.strftime("%Y-%m-%d")
                entry.extend([issued_tag])

        return entry
Exemple #9
0
    def license_tags(cls, license_pool, loan, hold):
        # Generate a list of licensing tags. These should be inserted
        # into a <link> tag.
        tags = []
        availability_tag_name = None
        suppress_since = False
        status = None
        since = None
        until = None

        if not license_pool:
            return
        if license_pool.open_access:
            default_loan_period = default_reservation_period = None
        else:
            ds = license_pool.data_source
            default_loan_period = ds.default_loan_period
            default_reservation_period = ds.default_reservation_period
        if loan:
            status = 'available'
            since = loan.start
            until = loan.until(default_loan_period)
        elif hold:
            until = hold.until(default_loan_period, default_reservation_period)
            if hold.position == 0:
                status = 'ready'
                since = None
            else:
                status = 'reserved'
                since = hold.start
        elif (license_pool.open_access or (
                license_pool.licenses_available > 0 and
                license_pool.licenses_owned > 0)
          ):
            status = 'available'
        else:
            status='unavailable'

        kw = dict(status=status)
        if since:
            kw['since'] = AtomFeed._strftime(since)
        if until:
            kw['until'] = AtomFeed._strftime(until)
        tag_name = "{%s}availability" % AtomFeed.OPDS_NS
        availability_tag = AtomFeed.makeelement(tag_name, **kw)
        tags.append(availability_tag)

        # Open-access pools do not need to display <opds:holds> or <opds:copies>.
        if license_pool.open_access:
            return tags


        holds_kw = dict(total=str(license_pool.patrons_in_hold_queue or 0))
        if hold and hold.position:
            holds_kw['position'] = str(hold.position)
        holds = AtomFeed.makeelement("{%s}holds" % AtomFeed.OPDS_NS, **holds_kw)
        tags.append(holds)

        copies_kw = dict(
            total=str(license_pool.licenses_owned or 0),
            available=str(license_pool.licenses_available or 0),
        )
        copies = AtomFeed.makeelement("{%s}copies" % AtomFeed.OPDS_NS, **copies_kw)
        tags.append(copies)

        return tags