def lookup(cls, edition_or_identifier, data_source, operation=None,
               collection=None):
        from datasource import DataSource
        from edition import Edition
        from identifier import Identifier

        _db = Session.object_session(edition_or_identifier)
        if isinstance(edition_or_identifier, Identifier):
            identifier = edition_or_identifier
        elif isinstance(edition_or_identifier, Edition):
            identifier = edition_or_identifier.primary_identifier
        else:
            raise ValueError(
                "Cannot look up a coverage record for %r." % edition)

        if isinstance(data_source, basestring):
            data_source = DataSource.lookup(_db, data_source)

        return get_one(
            _db, CoverageRecord,
            identifier=identifier,
            data_source=data_source,
            operation=operation,
            collection=collection,
            on_multiple='interchangeable',
        )
    def data_source(self):
        """Find the data source associated with this Collection.

        Bibliographic metadata obtained through the collection
        protocol is recorded as coming from this data source. A
        LicensePool inserted into this collection will be associated
        with this data source, unless its bibliographic metadata
        indicates some other data source.

        For most Collections, the integration protocol sets the data
        source.  For collections that use the OPDS import protocol,
        the data source is a Collection-specific setting.
        """
        data_source = None
        name = ExternalIntegration.DATA_SOURCE_FOR_LICENSE_PROTOCOL.get(
            self.protocol
        )
        if not name:
            name = self.external_integration.setting(
                Collection.DATA_SOURCE_NAME_SETTING
            ).value
        _db = Session.object_session(self)
        if name:
            data_source = DataSource.lookup(_db, name, autocreate=True)
        return data_source
 def all_from_data_sources(cls, _db, data_sources):
     """All custom lists from the given data sources."""
     if not isinstance(data_sources, list):
         data_sources = [data_sources]
     ids = []
     for ds in data_sources:
         if isinstance(ds, basestring):
             ds = DataSource.lookup(_db, ds)
         ids.append(ds.id)
     return _db.query(CustomList).filter(CustomList.data_source_id.in_(ids))
 def lookup(self, _db, data_source, type, patron, refresher_method,
            allow_persistent_token=False, allow_empty_token=False):
     from datasource import DataSource
     if isinstance(data_source, basestring):
         data_source = DataSource.lookup(_db, data_source)
     credential, is_new = get_one_or_create(
         _db, Credential, data_source=data_source, type=type, patron=patron)
     if (is_new
         or (not credential.expires and not allow_persistent_token)
         or (not credential.credential and not allow_empty_token)
         or (credential.expires
             and credential.expires <= datetime.datetime.utcnow())):
         if refresher_method:
             refresher_method(credential)
     return credential
Exemple #5
0
    def unresolved_catalog(self, _db, data_source_name, operation):
        """Returns a query with all identifiers in a Collection's catalog that
        have unsuccessfully attempted resolution. This method is used on the
        metadata wrangler.

        :return: a sqlalchemy.Query
        """
        coverage_source = DataSource.lookup(_db, data_source_name)
        is_not_resolved = and_(
            CoverageRecord.operation == operation,
            CoverageRecord.data_source_id == coverage_source.id,
            CoverageRecord.status != CoverageRecord.SUCCESS,
        )

        query = _db.query(Identifier)\
            .outerjoin(Identifier.licensed_through)\
            .outerjoin(Identifier.coverage_records)\
            .outerjoin(LicensePool.work).outerjoin(Identifier.collections)\
            .filter(
                Collection.id==self.id, is_not_resolved, Work.id==None
            ).order_by(Identifier.id)

        return query
Exemple #6
0
    def data_source(self):
        """Find the data source associated with this Collection.

        Bibliographic metadata obtained through the collection
        protocol is recorded as coming from this data source. A
        LicensePool inserted into this collection will be associated
        with this data source, unless its bibliographic metadata
        indicates some other data source.

        For most Collections, the integration protocol sets the data
        source.  For collections that use the OPDS import protocol,
        the data source is a Collection-specific setting.
        """
        data_source = None
        name = ExternalIntegration.DATA_SOURCE_FOR_LICENSE_PROTOCOL.get(
            self.protocol)
        if not name:
            name = self.external_integration.setting(
                Collection.DATA_SOURCE_NAME_SETTING).value
        _db = Session.object_session(self)
        if name:
            data_source = DataSource.lookup(_db, name, autocreate=True)
        return data_source
    def unresolved_catalog(self, _db, data_source_name, operation):
        """Returns a query with all identifiers in a Collection's catalog that
        have unsuccessfully attempted resolution. This method is used on the
        metadata wrangler.

        :return: a sqlalchemy.Query
        """
        coverage_source = DataSource.lookup(_db, data_source_name)
        is_not_resolved = and_(
            CoverageRecord.operation==operation,
            CoverageRecord.data_source_id==coverage_source.id,
            CoverageRecord.status!=CoverageRecord.SUCCESS,
        )

        query = _db.query(Identifier)\
            .outerjoin(Identifier.licensed_through)\
            .outerjoin(Identifier.coverage_records)\
            .outerjoin(LicensePool.work).outerjoin(Identifier.collections)\
            .filter(
                Collection.id==self.id, is_not_resolved, Work.id==None
            ).order_by(Identifier.id)

        return query
Exemple #8
0
    def from_metadata_identifier(cls, _db, metadata_identifier, data_source=None):
        """Finds or creates a Collection on the metadata wrangler, based
        on its unique metadata_identifier.
        """

        # Decode the metadata identifier into a protocol and an
        # account ID. If the metadata identifier is invalid, this
        # will raise an exception.
        protocol, account_id = cls._decode_metadata_identifier(metadata_identifier)

        # Now that we know the metadata identifier is valid, try to
        # look up a collection named after it.
        collection = get_one(_db, Collection, name=metadata_identifier)
        is_new = False

        if not collection:
            # Create a collection named after the metadata
            # identifier. Give it an ExternalIntegration with the
            # corresponding protocol, and set its data source and
            # external_account_id.
            collection, is_new = create(
                _db, Collection, name=metadata_identifier
            )
            collection.create_external_integration(protocol)

        if protocol == ExternalIntegration.OPDS_IMPORT:
            # For OPDS Import collections only, we store the URL to
            # the OPDS feed (the "account ID") and the data source.
            collection.external_account_id = account_id
            if data_source and not isinstance(data_source, DataSource):
                data_source = DataSource.lookup(
                    _db, data_source, autocreate=True
                )
            collection.data_source = data_source

        return collection, is_new
Exemple #9
0
    def restrict_to_ready_deliverable_works(
        cls, query, work_model, edition_model=None, collection_ids=None,
        show_suppressed=False, allow_holds=True,
    ):
        """Restrict a query to show only presentation-ready works present in
        an appropriate collection which the default client can
        fulfill.

        Note that this assumes the query has an active join against
        LicensePool.

        :param query: The query to restrict.

        :param work_model: Either Work or MaterializedWorkWithGenre

        :param edition_model: Either Edition or MaterializedWorkWithGenre

        :param show_suppressed: Include titles that have nothing but
        suppressed LicensePools.

        :param collection_ids: Only include titles in the given
        collections.

        :param allow_holds: If false, pools with no available copies
        will be hidden.
        """
        edition_model = edition_model or work_model

        # Only find presentation-ready works.
        #
        # Such works are automatically filtered out of
        # the materialized view, but we need to filter them out of Work.
        if work_model == Work:
            query = query.filter(
                work_model.presentation_ready == True,
            )

        # Only find books that have some kind of DeliveryMechanism.
        LPDM = LicensePoolDeliveryMechanism
        exists_clause = exists().where(
            and_(LicensePool.data_source_id==LPDM.data_source_id,
                LicensePool.identifier_id==LPDM.identifier_id)
        )
        query = query.filter(exists_clause)

        # Some sources of audiobooks may be excluded because the
        # server can't fulfill them or the expected client can't play
        # them.
        _db = query.session
        excluded = ConfigurationSetting.excluded_audio_data_sources(_db)
        if excluded:
            audio_excluded_ids = [
                DataSource.lookup(_db, x).id for x in excluded
            ]
            query = query.filter(
                or_(edition_model.medium != EditionConstants.AUDIO_MEDIUM,
                    ~LicensePool.data_source_id.in_(audio_excluded_ids))
            )

        # Only find books with unsuppressed LicensePools.
        if not show_suppressed:
            query = query.filter(LicensePool.suppressed==False)

        # Only find books with available licenses.
        query = query.filter(
                or_(LicensePool.licenses_owned > 0, LicensePool.open_access)
        )

        # Only find books in an appropriate collection.
        if collection_ids is not None:
            query = query.filter(
                LicensePool.collection_id.in_(collection_ids)
            )

        # If we don't allow holds, hide any books with no available copies.
        if not allow_holds:
            query = query.filter(
                or_(LicensePool.licenses_available > 0, LicensePool.open_access)
            )
        return query
    def restrict_to_ready_deliverable_works(
        cls, query, work_model, edition_model=None, collection_ids=None,
        show_suppressed=False, allow_holds=True,
    ):
        """Restrict a query to show only presentation-ready works present in
        an appropriate collection which the default client can
        fulfill.

        Note that this assumes the query has an active join against
        LicensePool.

        :param query: The query to restrict.

        :param work_model: Either Work or MaterializedWorkWithGenre

        :param edition_model: Either Edition or MaterializedWorkWithGenre

        :param show_suppressed: Include titles that have nothing but
        suppressed LicensePools.

        :param collection_ids: Only include titles in the given
        collections.

        :param allow_holds: If false, pools with no available copies
        will be hidden.
        """
        edition_model = edition_model or work_model

        # Only find presentation-ready works.
        #
        # Such works are automatically filtered out of
        # the materialized view, but we need to filter them out of Work.
        if work_model == Work:
            query = query.filter(
                work_model.presentation_ready == True,
            )

        # Only find books that have some kind of DeliveryMechanism.
        LPDM = LicensePoolDeliveryMechanism
        exists_clause = exists().where(
            and_(LicensePool.data_source_id==LPDM.data_source_id,
                LicensePool.identifier_id==LPDM.identifier_id)
        )
        query = query.filter(exists_clause)

        # Some sources of audiobooks may be excluded because the
        # server can't fulfill them or the expected client can't play
        # them.
        _db = query.session
        excluded = ConfigurationSetting.excluded_audio_data_sources(_db)
        if excluded:
            audio_excluded_ids = [
                DataSource.lookup(_db, x).id for x in excluded
            ]
            query = query.filter(
                or_(edition_model.medium != EditionConstants.AUDIO_MEDIUM,
                    ~LicensePool.data_source_id.in_(audio_excluded_ids))
            )

        # Only find books with unsuppressed LicensePools.
        if not show_suppressed:
            query = query.filter(LicensePool.suppressed==False)

        # Only find books with available licenses.
        query = query.filter(
                or_(LicensePool.licenses_owned > 0, LicensePool.open_access)
        )

        # Only find books in an appropriate collection.
        if collection_ids is not None:
            query = query.filter(
                LicensePool.collection_id.in_(collection_ids)
            )

        # If we don't allow holds, hide any books with no available copies.
        if not allow_holds:
            query = query.filter(
                or_(LicensePool.licenses_available > 0, LicensePool.open_access)
            )
        return query