Warning
This document is for an in-development version of Galaxy. You can alternatively view this page in the latest release if it exists or view the top of the latest release's documentation.
Source code for galaxy.managers.citations
import functools
import logging
import os
import requests
from beaker.cache import CacheManager
from beaker.util import parse_cache_config_options
log = logging.getLogger(__name__)
[docs]class CitationsManager(object):
[docs] def citations_for_tool_ids(self, tool_ids):
citation_collection = CitationCollection()
for tool_id in tool_ids:
tool = self._get_tool(tool_id)
for citation in self.citations_for_tool(tool):
citation_collection.add(citation)
return citation_collection.citations
[docs] def parse_citation(self, citation_elem, tool_directory):
return parse_citation(citation_elem, tool_directory, self)
def _get_tool(self, tool_id):
tool = self.app.toolbox.get_tool(tool_id)
return tool
[docs]class DoiCache(object):
[docs] def __init__(self, config):
cache_opts = {
'cache.type': getattr(config, 'citation_cache_type', 'file'),
'cache.data_dir': getattr(config, 'citation_cache_data_dir', None),
'cache.lock_dir': getattr(config, 'citation_cache_lock_dir', None),
}
self._cache = CacheManager(**parse_cache_config_options(cache_opts)).get_cache('doi')
def _raw_get_bibtex(self, doi):
doi_url = "https://doi.org/" + doi
headers = {'Accept': 'text/bibliography; style=bibtex, application/x-bibtex'}
req = requests.get(doi_url, headers=headers)
return req.text
[docs] def get_bibtex(self, doi):
createfunc = functools.partial(self._raw_get_bibtex, doi)
return self._cache.get(key=doi, createfunc=createfunc)
[docs]def parse_citation(elem, directory, citation_manager):
""" Parse an abstract citation entry from the specified XML element.
The directory parameter should be used to find external files for this
citation.
"""
citation_type = elem.attrib.get('type', None)
citation_class = CITATION_CLASSES.get(citation_type, None)
if not citation_class:
log.warning("Unknown or unspecified citation type: %s" % citation_type)
return None
return citation_class(elem, directory, citation_manager)
[docs]class CitationCollection(object):
def __iter__(self):
return self.citations.__iter__()
def __len__(self):
return len(self.citations)
[docs] def add(self, new_citation):
for citation in self.citations:
if citation.equals(new_citation):
# TODO: We have two equivalent citations, pick the more
# informative/complete/correct.
return False
self.citations.append(new_citation)
return True
[docs]class BaseCitation(object):
[docs] def to_dict(self, citation_format):
if citation_format == "bibtex":
return dict(
format="bibtex",
content=self.to_bibtex(),
)
else:
raise Exception("Unknown citation format %s" % citation_format)
[docs] def equals(self, other_citation):
if self.has_doi() and other_citation.has_doi():
return self.doi() == other_citation.doi()
else:
# TODO: Do a better job figuring out if this is the same citation.
return self.to_bibtex() == other_citation.to_bibtex()
[docs]class BibtexCitation(BaseCitation):
[docs] def __init__(self, elem, directory, citation_manager):
bibtex_file = elem.attrib.get("file", None)
if bibtex_file:
raw_bibtex = open(os.path.join(directory, bibtex_file), "r").read()
else:
raw_bibtex = elem.text.strip()
self._set_raw_bibtex(raw_bibtex)
def _set_raw_bibtex(self, raw_bibtex):
self.raw_bibtex = raw_bibtex
[docs]class DoiCitation(BaseCitation):
BIBTEX_UNSET = object()
[docs] def __init__(self, elem, directory, citation_manager):
self.__doi = elem.text.strip()
self.doi_cache = citation_manager.doi_cache
self.raw_bibtex = DoiCitation.BIBTEX_UNSET
[docs] def to_bibtex(self):
if self.raw_bibtex is DoiCitation.BIBTEX_UNSET:
try:
self.raw_bibtex = self.doi_cache.get_bibtex(self.__doi)
except Exception:
log.exception("Failed to fetch bibtex for DOI %s", self.__doi)
if self.raw_bibtex is DoiCitation.BIBTEX_UNSET:
return """@MISC{%s,
DOI = {%s},
note = {Failed to fetch BibTeX for DOI.}
}""" % (self.__doi, self.__doi)
else:
return self.raw_bibtex
CITATION_CLASSES = dict(
bibtex=BibtexCitation,
doi=DoiCitation,
)