def test_has_next_page(self): query = self._db.query(Work) pagination = Pagination(size=2) # When the query is empty, pagination doesn't have a next page. pagination.apply(query) eq_(False, pagination.has_next_page) # When there are more results in the query, it does. for num in range(3): # Create three works. self._work() pagination.apply(query) eq_(True, pagination.has_next_page) # When we reach the end of results, there's no next page. pagination.offset = 1 eq_(False, pagination.has_next_page) # When the database is updated, pagination knows. for num in range(3): self._work() pagination.apply(query) eq_(True, pagination.has_next_page) # Even when the query ends at the same size as a page, all is well. pagination.offset = 4 eq_(False, pagination.has_next_page)
def test_refusal_to_create_expensive_feed(self): facets = Facets.default() pagination = Pagination.default() lane = Lane(self._db, "My Lane", languages=['eng', 'chi']) args = (self._db, lane, CachedFeed.PAGE_TYPE, facets, pagination, None) # If we ask for a group feed that will be cached forever, and it's # not around, we'll get a page feed instead. feed, fresh = CachedFeed.fetch(*args, max_age=Configuration.CACHE_FOREVER) eq_(CachedFeed.PAGE_TYPE, feed.type) # If we ask for the same feed, but we don't say it must be cached # forever, it'll be created. feed, fresh = CachedFeed.fetch(*args, max_age=0) # Or if we explicitly demand that the feed be created, it will # be created. feed, fresh = CachedFeed.fetch(*args, force_refresh=True, max_age=Configuration.CACHE_FOREVER) feed.update("Cache this forever!") # Once the feed has content associated with it, we can ask for # it in cached-forever mode and no longer get the exception. feed, fresh = CachedFeed.fetch(*args, max_age=Configuration.CACHE_FOREVER) eq_("Cache this forever!", feed.content)
def test_lifecycle(self): facets = Facets.default() pagination = Pagination.default() lane = Lane(self._db, "My Lane", languages=['eng', 'chi']) # Fetch a cached feed from the database--it's empty. args = (self._db, lane, CachedFeed.PAGE_TYPE, facets, pagination, None) feed, fresh = CachedFeed.fetch(*args, max_age=0) eq_(False, fresh) eq_(None, feed.content) eq_(pagination.query_string, feed.pagination) eq_(facets.query_string, feed.facets) eq_(lane.name, feed.lane_name) eq_('eng,chi', feed.languages) # Update the content feed.update("The content") self._db.commit() # Fetch it again. feed, fresh = CachedFeed.fetch(*args, max_age=0) # Now it's cached! But not fresh, because max_age is zero eq_("The content", feed.content) eq_(False, fresh) # Lower our standards, and it's fresh! feed, fresh = CachedFeed.fetch(*args, max_age=1000) eq_("The content", feed.content) eq_(True, fresh)
def test_fetch_ignores_feeds_without_content(self): facets = Facets.default(self._default_library) pagination = Pagination.default() lane = self._lane(u"My Lane", languages=['eng', 'chi']) # Create a feed without content (i.e. don't update it) contentless_feed = get_one_or_create( self._db, CachedFeed, lane_id=lane.id, type=CachedFeed.PAGE_TYPE, facets=unicode(facets.query_string), pagination=unicode(pagination.query_string))[0] # It's not returned because it hasn't been updated. args = (self._db, lane, CachedFeed.PAGE_TYPE, facets, pagination, None) feed, fresh = CachedFeed.fetch(*args) eq_(True, feed != contentless_feed) eq_(False, fresh) # But if the feed is updated, we get it back. feed.update(self._db, u"Just feedy things") result, fresh = CachedFeed.fetch(*args) eq_(True, fresh) eq_(feed, result)
def test_lifecycle_with_worklist(self): facets = Facets.default(self._default_library) pagination = Pagination.default() lane = WorkList() lane.initialize(self._default_library) # Fetch a cached feed from the database--it's empty. args = (self._db, lane, CachedFeed.PAGE_TYPE, facets, pagination, None) feed, fresh = CachedFeed.fetch(*args, max_age=0) eq_(False, fresh) eq_(None, feed.content) eq_(pagination.query_string, feed.pagination) eq_(facets.query_string, feed.facets) eq_(None, feed.lane_id) # Update the content feed.update(self._db, u"The content") self._db.commit() # Fetch it again. feed, fresh = CachedFeed.fetch(*args, max_age=0) # Now it's cached! But not fresh, because max_age is zero eq_("The content", feed.content) eq_(False, fresh) # Lower our standards, and it's fresh! feed, fresh = CachedFeed.fetch(*args, max_age=1000) eq_("The content", feed.content) eq_(True, fresh)
def load_pagination(size, offset): """Turn user input into a Pagination object.""" try: size = int(size) except ValueError: return INVALID_INPUT.detailed( _("Invalid page size: %(size)s", size=size)) size = min(size, 100) if offset: try: offset = int(offset) except ValueError: return INVALID_INPUT.detailed( _("Invalid offset: %(offset)s", offset=offset)) return Pagination(offset, size)
def page(cls, _db, title, url, lane, annotator=None, facets=None, pagination=None, cache_type=None, force_refresh=False, use_materialized_works=True ): """Create a feed representing one page of works from a given lane.""" facets = facets or Facets.default() pagination = pagination or Pagination.default() cache_type = cache_type or CachedFeed.PAGE_TYPE # Find or create a CachedFeed. cached, usable = CachedFeed.fetch( _db, lane=lane, type=cache_type, facets=facets, pagination=pagination, annotator=annotator, force_refresh=force_refresh ) if usable: return cached if use_materialized_works: works_q = lane.materialized_works(facets, pagination) else: works_q = lane.works(facets, pagination) if not works_q: works = [] else: works = works_q.all() feed = cls(_db, title, url, works, annotator) # Add URLs to change faceted views of the collection. for args in cls.facet_links(annotator, facets): OPDSFeed.add_link_to_feed(feed=feed.feed, **args) if len(works) > 0: # There are works in this list. Add a 'next' link. OPDSFeed.add_link_to_feed(feed=feed.feed, rel="next", href=annotator.feed_url(lane, facets, pagination.next_page)) if pagination.offset > 0: OPDSFeed.add_link_to_feed(feed=feed.feed, rel="first", href=annotator.feed_url(lane, facets, pagination.first_page)) previous_page = pagination.previous_page if previous_page: OPDSFeed.add_link_to_feed(feed=feed.feed, rel="previous", href=annotator.feed_url(lane, facets, previous_page)) # Add "up" link and breadcrumbs top_level_title = annotator.top_level_title() or "Collection Home" visible_parent = lane.visible_parent() if isinstance(visible_parent, Lane): title = visible_parent.display_name else: title = top_level_title if visible_parent: up_uri = annotator.lane_url(visible_parent) OPDSFeed.add_link_to_feed(feed=feed.feed, href=up_uri, rel="up", title=title) feed.add_breadcrumbs(lane, annotator) OPDSFeed.add_link_to_feed(feed=feed.feed, rel='start', href=annotator.default_lane_url(), title=top_level_title) annotator.annotate_feed(feed, lane) content = unicode(feed) cached.update(content) return cached