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
try: for result in instance._run_self_tests(_db): results.append(result) except Exception, e: # This should only happen when there's a bug in the # self-test method itself. failure = instance.test_failure( "Uncaught exception in the self-test method itself.", e) results.append(failure) end = datetime.datetime.utcnow() # Format the results in a useful way. value = dict(start=AtomFeed._strftime(start), end=AtomFeed._strftime(end), duration=(end - start).total_seconds(), results=[x.to_dict for x in results]) # Store the formatted results in the database, if we can find # a place to store them. if instance and isinstance(instance, ExternalSearchIndex): integration = instance.search_integration(_db) for idx, result in enumerate(value.get("results")): if isinstance(results[idx].result, (list, )): result["result"] = results[idx].result elif instance: integration = instance.external_integration(_db)
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
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
except Exception, e: # This should only happen when there's a bug in the # self-test method itself. failure = instance.test_failure( "Uncaught exception in the self-test method itself.", e ) results.append(failure) end = datetime.datetime.utcnow() # Format the results in a useful way. value = dict( start=AtomFeed._strftime(start), end=AtomFeed._strftime(end), duration = (end-start).total_seconds(), results = [x.to_dict for x in results] ) # Store the formatted results in the database, if we can find # a place to store them. if instance and isinstance(instance, ExternalSearchIndex): integration = instance.search_integration(_db) for idx, result in enumerate(value.get("results")): if isinstance(results[idx].result, (list,)): result["result"] = results[idx].result elif instance: integration = instance.external_integration(_db)
try: for result in instance._run_self_tests(_db): results.append(result) except Exception, e: # This should only happen when there's a bug in the # self-test method itself. failure = instance.test_failure( "Uncaught exception in the self-test method itself.", e ) results.append(failure) integration = instance.external_integration(_db) end = datetime.datetime.utcnow() # Format the results in a useful way. value = dict( start=AtomFeed._strftime(start), end=AtomFeed._strftime(end), duration = (end-start).total_seconds(), results = [x.to_dict for x in results] ) # Store the formatted results in the database, if we can find # a place to store them. if integration: integration.setting( cls.SELF_TEST_RESULTS_SETTING ).value = json.dumps(value) return value, results @classmethod def prior_test_results(cls, _db, constructor_method=None, *args, **kwargs):