api.proquest package¶
Submodules¶
api.proquest.client module¶
- class api.proquest.client.ProQuestAPIClient(configuration_storage, configuration_factory)[source]¶
Bases:
object
ProQuest API client.
- DOWNLOAD_LINK_FIELD = 'downloadLink'¶
- DRM_FREE_DOWNLOAD_LINK_KEYWORD = 'getDrmFreeFile'¶
- MAX_PAGE_INDEX = 32766¶
- MAX_PAGE_SIZE = 32766¶
- RESPONSE_OPDS_FEED_FIELD = 'opdsFeed'¶
- RESPONSE_STATUS_CODE_FIELD = 'statusCode'¶
- SUCCESS_STATUS_CODE = 200¶
- TOKEN_FIELD = 'token'¶
- create_token(db, affiliation_id)[source]¶
Create a new JWT bearer token.
- Parameters:
db (sqlalchemy.orm.session.Session) – Database session
affiliation_id (str) – SAML affiliation ID used as a patron’s unique identifier by ProQuest
- Returns:
New JWT bearer token
- Return type:
str
- download_all_feed_pages(db)[source]¶
Download all available feed pages.
- Parameters:
db (sqlalchemy.orm.session.Session) – Database session
- Returns:
Iterable list of feed pages in a form of Python dictionaries
- Return type:
Iterable[dict]
- download_feed_page(db, page, hits_per_page)[source]¶
Download a single page of a paginated OPDS 2.0 feed.
- Parameters:
db (sqlalchemy.orm.session.Session) – Database session
page (int) – Page index (max = 32,766)
hits_per_page (int) – Number of publications on a single page (max = 32,766)
- Returns:
Python dictionary object containing the feed’s page
- Return type:
dict
- get_book(db, token, document_id)[source]¶
Get a book by it’s ProQuest Doc ID.
NOTE: There are two different cases to consider: - Open-access books: in this case ProQuest API returns the book content. - Adobe DRM copy protected books: in this case ProQuest API returns an ACSM file containing information about downloading a digital publication.
- Parameters:
db (sqlalchemy.orm.session.Session) – Database session
token (str) – JWT bearer token created using ProQuestAPIClient.create_token method
document_id (str) – ProQuest Doc ID
- Returns:
Book instance containing either an ACS link to the book or the book content
- Return type:
- class api.proquest.client.ProQuestAPIClientConfiguration(configuration_storage, db)[source]¶
Bases:
ConfigurationGrouping
Contains configuration settings of ProQuest API client.
- DEFAULT_PAGE_SIZE = 5000¶
- books_catalog_service_url¶
Contains configuration metadata
- download_link_service_url¶
Contains configuration metadata
- http_proxy_url¶
Contains configuration metadata
- https_proxy_url¶
Contains configuration metadata
- page_size¶
Contains configuration metadata
- partner_auth_token_service_url¶
Contains configuration metadata
- class api.proquest.client.ProQuestAPIClientFactory[source]¶
Bases:
object
Factory used for creating ProQuestAPIClient instances.
- create(integration_association)[source]¶
Create a new instance of ProQuestAPIClientFactory.
- Parameters:
integration_association (core.model.configuration.HasExternalIntegration) – Association with an external integration
- Returns:
New instance of ProQuestAPIClient
- Return type:
- exception api.proquest.client.ProQuestAPIInvalidJSONResponseError(response)[source]¶
Bases:
BaseError
Raised when the client receives from ProQuest API a response with incorrect JSON document.
- property response¶
Return the response associated with this error.
- Returns:
Response associated with this error
- Return type:
requests.models.Response
- exception api.proquest.client.ProQuestAPIMissingJSONPropertyError(response, missing_property)[source]¶
Bases:
ProQuestAPIInvalidJSONResponseError
Raised when the client receives from ProQuest API a response with incorrect JSON document.
- property missing_property¶
Return the name of the missing property.
- Returns:
Name of the missing property
- Return type:
str
- class api.proquest.client.ProQuestBook(link=None, content=None, content_type=None)[source]¶
Bases:
object
POCO class containing information about a ProQuest book.
- property content¶
Return the book’s content.
- Returns:
Book’s content
- Return type:
Optional[Union[str, bytes]]
- property content_type¶
Return the content type.
- Returns:
Content type
- Return type:
Optional[str]
- property link¶
Return the book’s link.
- Returns:
Book’s link
- Return type:
Optional[str]
api.proquest.credential module¶
- class api.proquest.credential.ProQuestCredentialManager[source]¶
Bases:
object
Manages ProQuest credentials.
- lookup_patron_affiliation_id(db, patron, affiliation_attributes=('eduPersonPrincipalName', 'eduPersonScopedAffiliation'))[source]¶
Look up for patron’s SAML affiliation ID.
- Parameters:
db (sqlalchemy.orm.session.Session) – Database session
patron (core.model.patron.Patron) – Patron object
affiliation_attributes (Tuple) – SAML attributes containing an affiliation ID
- Returns:
Patron’s SAML affiliation ID (if any)
- Return type:
Optional[str]
- lookup_proquest_token(db, patron)[source]¶
Look up for a JWT bearer token used required to use ProQuest API.
- Parameters:
db (sqlalchemy.orm.session.Session) – Database session
patron (core.model.patron.Patron) – Patron object
- Returns:
Credential object containing the existing ProQuest JWT bearer token (if any)
- Return type:
Optional[core.model.credential.Credential]
- save_proquest_token(db, patron, duration, token)[source]¶
Save a ProQuest JWT bearer token for later use.
- Parameters:
db (sqlalchemy.orm.session.Session) – Database session
patron (core.model.patron.Patron) – Patron object
duration (datetime.timedelta) – How long this token can be valid
token (str) – ProQuest JWT bearer token
- Returns:
Credential object containing a new ProQuest JWT bearer token
- Return type:
Optional[core.model.credential.Credential]
api.proquest.identifier module¶
- class api.proquest.identifier.ProQuestIdentifierParser[source]¶
Bases:
IdentifierParser
Parser for ProQuest Doc IDs.
- PROQUEST_ID_REGEX = re.compile('urn:proquest.com/document-id/(\\d+)')¶
- parse(identifier_string)[source]¶
Parse a string containing an identifier, extract it and determine its type.
- Parameters:
identifier_string (str) – String containing an identifier
- Returns:
2-tuple containing the identifier’s type and identifier itself or None if the string contains an incorrect identifier
- Return type:
Optional[Tuple[str, str]]
api.proquest.importer module¶
- exception api.proquest.importer.CannotCreateProQuestTokenError(inner_exception)[source]¶
Bases:
BaseError
- class api.proquest.importer.ProQuestOPDS2ImportMonitor(client_factory, db, collection, import_class, force_reimport=False, process_removals=False, **import_class_kwargs)[source]¶
Bases:
OPDS2ImportMonitor
,HasExternalIntegration
- PROTOCOL = 'ProQuest'¶
- run_once(progress_ignore)[source]¶
Do the actual work of the Monitor.
- Parameters:
progress – A TimestampData representing the work done by the Monitor up to this point.
- Returns:
A TimestampData representing how you want the Monitor’s entry in the timestamps table to look like from this point on. NOTE: Modifying the incoming progress and returning it is generally a bad idea, because the incoming progress is full of old data. Instead, return a new TimestampData containing data for only the fields you want to set.
- class api.proquest.importer.ProQuestOPDS2Importer(db, collection, data_source_name=None, identifier_mapping=None, http_get=None, metadata_client=None, content_modifier=None, map_from_collection=None, mirrors=None)[source]¶
Bases:
OPDS2Importer
,BaseCirculationAPI
,HasExternalIntegration
Allows to import ProQuest OPDS 2.0 feeds into Circulation Manager.
- DESCRIPTION = l'Import books from a ProQuest OPDS 2.0 feed.'¶
- LIBRARY_SETTINGS = [{'key': 'ebook_loan_duration', 'label': l'Default Loan Period (in Days)', 'default': 21, 'type': 'number', 'description': l'Until it hears otherwise from the distributor, this server will assume that any given loan for this library from this collection will last this number of days. This number is usually a negotiated value between the library and the distributor. This only affects estimates—it cannot affect the actual length of loans.'}]¶
- NAME = 'ProQuest'¶
- SETTINGS = [{'key': 'data_source', 'label': l'Data source name', 'description': l'Name of the data source associated with this collection.', 'type': None, 'required': True, 'default': 'ProQuest', 'options': None, 'category': None}, {'key': 'token_expiration_timeout', 'label': l'ProQuest JWT token's expiration timeout', 'description': l'Determines how long in seconds can a ProQuest JWT token be valid.', 'type': 'number', 'required': False, 'default': 3600, 'options': None, 'category': None}, {'key': 'affiliation_attributes', 'label': l'List of SAML attributes containing an affiliation ID', 'description': l'ProQuest integration assumes that the SAML provider is used for authentication. ProQuest JWT bearer tokens required by the most ProQuest API services are created based on the affiliation ID - SAML attribute uniquely identifying the patron.This setting determines what attributes the ProQuest integration will use to look for affiliation IDs. The ProQuest integration will investigate the specified attributes sequentially and will take the first non-empty value.', 'type': 'menu', 'required': False, 'default': ['eduPersonPrincipalName', 'eduPersonScopedAffiliation'], 'options': [{'key': 'uid', 'label': 'uid'}, {'key': 'givenName', 'label': 'givenName'}, {'key': 'surname', 'label': 'surname'}, {'key': 'mail', 'label': 'mail'}, {'key': 'displayName', 'label': 'displayName'}, {'key': 'eduPerson', 'label': 'eduPerson'}, {'key': 'eduPersonAffiliation', 'label': 'eduPersonAffiliation'}, {'key': 'eduPersonNickname', 'label': 'eduPersonNickname'}, {'key': 'eduPersonOrgDN', 'label': 'eduPersonOrgDN'}, {'key': 'eduPersonOrgUnitDN', 'label': 'eduPersonOrgUnitDN'}, {'key': 'eduPersonPrimaryAffiliation', 'label': 'eduPersonPrimaryAffiliation'}, {'key': 'eduPersonPrincipalName', 'label': 'eduPersonPrincipalName'}, {'key': 'eduPersonEntitlement', 'label': 'eduPersonEntitlement'}, {'key': 'eduPersonPrimaryOrgUnitDN', 'label': 'eduPersonPrimaryOrgUnitDN'}, {'key': 'eduPersonScopedAffiliation', 'label': 'eduPersonScopedAffiliation'}, {'key': 'eduPersonTargetedID', 'label': 'eduPersonTargetedID'}, {'key': 'eduPersonAssurance', 'label': 'eduPersonAssurance'}, {'key': 'eduPersonOrcid', 'label': 'eduPersonOrcid'}, {'key': 'eduPersonUniqueId', 'label': 'eduPersonUniqueId'}, {'key': 'eduPersonPrincipalNamePrior', 'label': 'eduPersonPrincipalNamePrior'}, {'key': 'eduOrg', 'label': 'eduOrg'}, {'key': 'eduOrgHomePageURI', 'label': 'eduOrgHomePageURI'}, {'key': 'eduOrgIdentityAuthNPolicyURI', 'label': 'eduOrgIdentityAuthNPolicyURI'}, {'key': 'eduOrgLegalName', 'label': 'eduOrgLegalName'}, {'key': 'eduOrgSuperiorURI', 'label': 'eduOrgSuperiorURI'}, {'key': 'eduOrgWhitePagesURI', 'label': 'eduOrgWhitePagesURI'}], 'category': None}, {'key': 'test_affiliation_id', 'label': l'Test SAML affiliation ID', 'description': l'Test SAML affiliation ID used for testing ProQuest API. Please contact ProQuest before using it.', 'type': None, 'required': False, 'default': None, 'options': None, 'category': None}, {'key': 'default_audience', 'label': l'Default audience', 'description': l'If ProQuest does not specify the target audience for their books, assume the books have this target audience.', 'type': 'select', 'required': False, 'default': '', 'options': [{'key': '', 'label': l'No default audience'}, {'key': 'Adult', 'label': 'Adult'}, {'key': 'Adults Only', 'label': 'Adults Only'}, {'key': 'All Ages', 'label': 'All Ages'}, {'key': 'Children', 'label': 'Children'}, {'key': 'Research', 'label': 'Research'}, {'key': 'Young Adult', 'label': 'Young Adult'}], 'category': None}, {'key': 'books_catalog_service_url', 'label': l'BooksCatalog service's URL', 'description': l'URL of the BooksCatalog service endpoint', 'type': None, 'required': True, 'default': None, 'options': None, 'category': None}, {'key': 'page_size', 'label': l'Feed page's size', 'description': l'This value determines how many publications will be on a single page fetched from the BooksCatalog service.', 'type': 'number', 'required': False, 'default': 5000, 'options': None, 'category': None}, {'key': 'partner_auth_token_service_url', 'label': l'PartnerAuthToken service's URL', 'description': l'URL of the PartnerAuthToken service endpoint.', 'type': None, 'required': True, 'default': None, 'options': None, 'category': None}, {'key': 'download_link_service_url', 'label': l'DownloadLink service's URL', 'description': l'URL of the DownloadLink service endpoint.', 'type': None, 'required': True, 'default': None, 'options': None, 'category': None}, {'key': 'http_proxy_url', 'label': l'HTTP proxy's URL', 'description': l'URL of the proxy handling HTTP traffic.', 'type': None, 'required': False, 'default': None, 'options': None, 'category': None}, {'key': 'https_proxy_url', 'label': l'HTTPS proxy's URL', 'description': l'URL of the proxy handling HTTPS traffic.', 'type': None, 'required': False, 'default': None, 'options': None, 'category': None}]¶
- checkout(patron, pin, licensepool, internal_format)[source]¶
Checkout the book.
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.
- external_integration(db)[source]¶
Return an external integration associated with this object.
- Parameters:
db (sqlalchemy.orm.session.Session) – Database session
- Returns:
External integration associated with this object
- Return type:
- extract_next_links(feed)[source]¶
Extract “next” links from the feed.
- Parameters:
feed (Union[str, opds2_ast.OPDS2Feed]) – OPDS 2.0 feed
- Returns:
List of “next” links
- Return type:
List[str]
- fulfill(patron, pin, licensepool, internal_format=None, part=None, fulfill_part_url=None)[source]¶
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.
- internal_format(delivery_mechanism)[source]¶
Look up the internal format for this delivery mechanism or raise an exception.
- Parameters:
delivery_mechanism (LicensePoolDeliveryMechanism) – A LicensePoolDeliveryMechanism
- patron_activity(patron, pin)[source]¶
Return patron’s loans.
TODO This and code from ODLAPI should be refactored into a generic set of rules for any situation where the CM, not the remote API, is responsible for managing loans and holds.
- place_hold(patron, pin, licensepool, notification_email_address)[source]¶
Place a book on hold.
- Returns:
A HoldInfo object
- release_hold(patron, pin, licensepool)[source]¶
Release a patron’s hold on a book.
- Raises:
CannotReleaseHold – If there is an error communicating with the provider, or the provider refuses to release the hold for any reason.
- class api.proquest.importer.ProQuestOPDS2ImporterConfiguration(configuration_storage, db)[source]¶
Bases:
ConfigurationGrouping
Contains configuration settings of ProQuestOPDS2Importer.
- DEFAULT_AFFILIATION_ATTRIBUTES = ('eduPersonPrincipalName', 'eduPersonScopedAffiliation')¶
- DEFAULT_TOKEN_EXPIRATION_TIMEOUT_SECONDS = 3600¶
- TEST_AFFILIATION_ID = 1¶
- affiliation_attributes¶
Contains configuration metadata
- data_source_name¶
Contains configuration metadata
- default_audience¶
Contains configuration metadata
- test_affiliation_id¶
Contains configuration metadata
- token_expiration_timeout¶
Contains configuration metadata
api.proquest.scripts module¶
- class api.proquest.scripts.ProQuestOPDS2ImportScript(*args, **kwargs)[source]¶
Bases:
OPDSImportScript
Runs a ProQuestOPDS2ImportMonitor.
- run_monitor(collection, force=None)[source]¶
Run the monitor for the specified collection.
- Parameters:
collection (core.model.collection.Collection) – Collection object
force (bool) – Boolean value indicating whether the import process should be run from scratch