예제 #1
0
    def test_fulfill(self):
        other_client, ignore = IntegrationClient.register(
            self._db, "http://other_library.org")
        loan, ignore = create(self._db,
                              Loan,
                              integration_client=other_client,
                              license_pool=self.pool)
        assert_raises(CannotFulfill, self.shared_collection.fulfill,
                      self.collection, self.client, loan,
                      self.delivery_mechanism)

        loan.integration_client = self.client

        # If the API does not return content or a content link, the loan can't be fulfilled.
        assert_raises(CannotFulfill, self.shared_collection.fulfill,
                      self.collection, self.client, loan,
                      self.delivery_mechanism)
        eq_([(self.client, loan, self.delivery_mechanism)], self.api.fulfills)

        self.api.fulfillment = FulfillmentInfo(
            self.collection,
            self.pool.data_source.name,
            self.pool.identifier.type,
            self.pool.identifier.identifier,
            "http://content",
            "text/html",
            None,
            None,
        )
        fulfillment = self.shared_collection.fulfill(self.collection,
                                                     self.client, loan,
                                                     self.delivery_mechanism)
        eq_([(self.client, loan, self.delivery_mechanism)],
            self.api.fulfills[1:])
        eq_(self.delivery_mechanism, loan.fulfillment)
예제 #2
0
    def test_fulfill_feed(self):
        patron = self._patron()

        work = self._work(with_license_pool=True,
                          with_open_access_download=False)
        pool = work.license_pools[0]
        pool.open_access = False
        streaming_mech = pool.set_delivery_mechanism(
            DeliveryMechanism.STREAMING_TEXT_CONTENT_TYPE,
            DeliveryMechanism.OVERDRIVE_DRM, RightsStatus.IN_COPYRIGHT, None)

        now = datetime.datetime.utcnow()
        loan, ignore = pool.loan_to(patron, start=now)
        fulfillment = FulfillmentInfo(
            pool.collection, pool.data_source.name, pool.identifier.type,
            pool.identifier.identifier, "http://streaming_link",
            Representation.TEXT_HTML_MEDIA_TYPE +
            DeliveryMechanism.STREAMING_PROFILE, None, None)

        feed_obj = CirculationManagerLoanAndHoldAnnotator.single_fulfillment_feed(
            None, loan, fulfillment, test_mode=True)
        raw = etree.tostring(feed_obj)

        entries = feedparser.parse(raw)['entries']
        eq_(1, len(entries))

        links = entries[0]['links']

        # The feed for a single fulfillment only includes one fulfill link.
        fulfill_links = [
            link for link in links
            if link['rel'] == "http://opds-spec.org/acquisition"
        ]
        eq_(1, len(fulfill_links))

        eq_(
            Representation.TEXT_HTML_MEDIA_TYPE +
            DeliveryMechanism.STREAMING_PROFILE, fulfill_links[0]['type'])
        eq_("http://streaming_link", fulfill_links[0]['href'])
예제 #3
0
    def fulfill(
        self,
        patron,
        pin,
        licensepool,
        internal_format=None,
        part=None,
        fulfill_part_url=None,
    ):
        """Fulfill the loan.

        NOTE: This method requires the patron to have either:
        - an active ProQuest JWT bearer token
        - or a SAML affiliation ID which will be used to create a new ProQuest JWT bearer token.
        """
        self._logger.info("Started fulfilling '{0}' for patron {1}".format(
            internal_format, patron))

        try:
            with self._get_configuration(self._db) as configuration:
                token = self._get_or_create_proquest_token(
                    patron, configuration)
                book = self._get_book(patron, configuration,
                                      licensepool.identifier.identifier)

                if book.content is not None:
                    fulfillment_info = FulfillmentInfo(
                        licensepool.collection,
                        licensepool.data_source.name,
                        licensepool.identifier.type,
                        licensepool.identifier.identifier,
                        content_link=None,
                        content_type=book.content_type if book.content_type
                        else internal_format.delivery_mechanism.content_type,
                        content=book.content,
                        content_expires=None,
                    )
                else:
                    now = utc_now()
                    expires_in = (token.expires - now).total_seconds()
                    token_document = dict(
                        token_type="Bearer",
                        access_token=token.credential,
                        expires_in=expires_in,
                        location=book.link,
                    )

                    return FulfillmentInfo(
                        licensepool.collection,
                        licensepool.data_source.name,
                        licensepool.identifier.type,
                        licensepool.identifier.identifier,
                        content_link=None,
                        content_type=DeliveryMechanism.BEARER_TOKEN,
                        content=json.dumps(token_document),
                        content_expires=token.expires,
                    )

                self._logger.info(
                    "Finished fulfilling {0} for patron {1}: {2}".format(
                        internal_format, patron, fulfillment_info))

                return fulfillment_info
        except BaseError as exception:
            self._logger.exception("Failed to fulfill out {0} for patron {1}")

            raise CannotFulfill(str(exception))