Skip to content

Commit

Permalink
Merge branch 'release/0.2.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
mfcovington committed Jan 22, 2016
2 parents b0be098 + 4608022 commit fe68c76
Show file tree
Hide file tree
Showing 7 changed files with 223 additions and 54 deletions.
2 changes: 1 addition & 1 deletion .bumpversion.cfg
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[bumpversion]
current_version = 0.1.5
current_version = 0.2.0
parse = (?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)(\-dev(?P<dev>\d+))?
serialize =
{major}.{minor}.{patch}-dev{dev}
Expand Down
8 changes: 8 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
Revision History
================

0.2.0 2016-01-22

- Create command-line tool (``pubmed-citation``) to quickly retrieve citations for PubMed IDs/URLS
- Create command-line tool (``pubmed-url``) to quickly retrieve article and DOI URLs for PubMed IDs/URLS
- Add option to save time by not resolving DOI URL (``Publication(pubmed_record, resolve_doi=False)``)
- Clean up documentation


0.1.5 2016-01-08

- Add exception for publications that do not have month information (Thanks to Sasha Cuerda!)
Expand Down
122 changes: 83 additions & 39 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -47,56 +47,56 @@ Usage

- Retrieve a PubMed record:

.. code-block:: python
.. code-block:: python
from pubmed_lookup import PubMedLookup
from pubmed_lookup import PubMedLookup
# NCBI will contact user by email if excessive queries are detected
email = ''
url = 'http://www.ncbi.nlm.nih.gov/pubmed/22331878'
lookup = PubMedLookup(url, email)
# NCBI will contact user by email if excessive queries are detected
email = ''
url = 'http://www.ncbi.nlm.nih.gov/pubmed/22331878'
lookup = PubMedLookup(url, email)
- Create a Publication object:

.. code-block:: python
.. code-block:: python
from pubmed_lookup import Publication
from pubmed_lookup import Publication
publication = Publication(lookup)
publication = Publication(lookup) # Use 'resolve_doi=False' to keep DOI URL
- Access the Publication object's attributes:

.. code-block:: python
print(
"""
TITLE:\n{title}\n
AUTHORS:\n{authors}\n
JOURNAL:\n{journal}\n
YEAR:\n{year}\n
MONTH:\n{month}\n
DAY:\n{day}\n
URL:\n{url}\n
PUBMED:\n{pubmed}\n
CITATION:\n{citation}\n
MINICITATION:\n{mini_citation}\n
ABSTRACT:\n{abstract}\n
"""
.format(**{
'title': publication.title,
'authors': publication.authors,
'journal': publication.journal,
'year': publication.year,
'month': publication.month,
'day': publication.day,
'url': publication.url,
'pubmed': publication.pubmed_url,
'citation': publication.cite(),
'mini_citation': publication.cite_mini(),
'abstract': repr(publication.abstract),
}))
.. code-block:: python
print(
"""
TITLE:\n{title}\n
AUTHORS:\n{authors}\n
JOURNAL:\n{journal}\n
YEAR:\n{year}\n
MONTH:\n{month}\n
DAY:\n{day}\n
URL:\n{url}\n
PUBMED:\n{pubmed}\n
CITATION:\n{citation}\n
MINICITATION:\n{mini_citation}\n
ABSTRACT:\n{abstract}\n
"""
.format(**{
'title': publication.title,
'authors': publication.authors,
'journal': publication.journal,
'year': publication.year,
'month': publication.month,
'day': publication.day,
'url': publication.url,
'pubmed': publication.pubmed_url,
'citation': publication.cite(),
'mini_citation': publication.cite_mini(),
'abstract': repr(publication.abstract),
}))
- Output of example:
Expand Down Expand Up @@ -134,4 +134,48 @@ Usage
ABSTRACT:
Diverse life forms have evolved internal clocks enabling them to monitor time and thereby anticipate the daily environmental changes caused by Earth's rotation. The plant circadian clock regulates expression of about one-third of the Arabidopsis genome, yet the physiological relevance of this regulation is not fully understood. Here we show that the circadian clock, acting with hormone signals, provides selective advantage to plants through anticipation of and enhanced defense against herbivory. We found that cabbage loopers (Trichoplusia ni) display rhythmic feeding behavior that is sustained under constant conditions, and plants entrained in light/dark cycles coincident with the entrainment of the T. ni suffer only moderate tissue loss due to herbivory. In contrast, plants entrained out-of-phase relative to the insects are significantly more susceptible to attack. The in-phase entrainment advantage is lost in plants with arrhythmic clocks or deficient in jasmonate hormone; thus, both the circadian clock and jasmonates are required. Circadian jasmonate accumulation occurs in a phase pattern consistent with preparation for the onset of peak circadian insect feeding behavior, providing evidence for the underlying mechanism of clock-enhanced herbivory resistance. Furthermore, we find that salicylate, a hormone involved in biotrophic defense that often acts antagonistically to jasmonates, accumulates in opposite phase to jasmonates. Our results demonstrate that the plant circadian clock provides a strong physiological advantage by performing a critical role in Arabidopsis defense."

*Version 0.1.5*

Command-Line Tools
==================

pubmed-citation
---------------

- Get a PubMed record's citation (both give same result):

.. code-block:: sh
pubmed-citation 22331878
pubmed-citation http://www.ncbi.nlm.nih.gov/pubmed/22331878
- Output of example:

Goodspeed D, Chehab EW, Min-Venditti A, Braam J, Covington MF (2012). Arabidopsis synchronizes jasmonate-mediated defense with insect circadian behavior. Proc Natl Acad Sci U S A 109(12): 4674-7.

- Output of example (using ``--mini`` option):

Goodspeed D - Covington MF - 2012 - Proc Natl Acad Sci U S A


pubmed-url
----------

- Get a PubMed record's url (both give same result):

.. code-block:: sh
pubmed-url 22331878
pubmed-url http://www.ncbi.nlm.nih.gov/pubmed/22331878
- Output of example:

http://www.pnas.org/content/109/12/4674

- Output of example (using ``--doi`` option):

http://dx.doi.org/10.1073/pnas.1116368109


*Version 0.2.0*
47 changes: 47 additions & 0 deletions pubmed_lookup/command_line.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import argparse
import sys

from pubmed_lookup import PubMedLookup, Publication


def pubmed_citation(args=sys.argv[1:], out=sys.stdout):
"""Get a citation via the command line using a PubMed ID or PubMed URL"""

parser = argparse.ArgumentParser(
description='Get a citation using a PubMed ID or PubMed URL')
parser.add_argument('query', help='PubMed ID or PubMed URL')
parser.add_argument(
'-m', '--mini', action='store_true', help='get mini citation')
parser.add_argument(
'-e', '--email', action='store', help='set user email', default='')

args = parser.parse_args(args=args)

lookup = PubMedLookup(args.query, args.email)
publication = Publication(lookup, resolve_doi=False)

if args.mini:
out.write(publication.cite_mini() + '\n')
else:
out.write(publication.cite() + '\n')


def pubmed_url(args=sys.argv[1:], resolve_doi=True, out=sys.stdout):
"""
Get a publication URL via the command line using a PubMed ID or PubMed URL
"""

parser = argparse.ArgumentParser(
description='Get a publication URL using a PubMed ID or PubMed URL')
parser.add_argument('query', help='PubMed ID or PubMed URL')
parser.add_argument(
'-d', '--doi', action='store_false', help='get DOI URL')
parser.add_argument(
'-e', '--email', action='store', help='set user email', default='')

args = parser.parse_args(args=args)

lookup = PubMedLookup(args.query, args.email)
publication = Publication(lookup, resolve_doi=args.doi)

out.write(publication.url + '\n')
31 changes: 20 additions & 11 deletions pubmed_lookup/pubmed_lookup.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,16 @@ class Publication(object):
a scientific publication.
"""

def __init__(self, pubmed_record):
def __init__(self, pubmed_record, resolve_doi=True):
"""
Upon init: set Publication attributes (record, pmid, pubmed_url,
title, authors, first_author, last_author, journal, volume, issue,
pages, url, abstract, year, month, and day)
pages, url, abstract, year, month, and day).
By default, the DOI gets resolved into the article's actual URL.
To return the DOI URL instead of the article's URL, use:
publication = Publication(pubmed_record, resolve_doi=False)
"""
self.record = pubmed_record.record
self.pmid = self.record.get('Id')
Expand All @@ -34,7 +39,7 @@ def __init__(self, pubmed_record):
self.volume = self.record.get('Volume')
self.issue = self.record.get('Issue')
self.pages = self.record.get('Pages')
self.set_article_url()
self.set_article_url(resolve_doi=resolve_doi)

xml_dict = self.get_pubmed_xml()
self.set_abstract(xml_dict)
Expand Down Expand Up @@ -162,26 +167,30 @@ def get_pubmed_xml(self):

def set_abstract(self, xml_dict):
"""
If record has an abstract, get it extract it from PubMed's XML data
If record has an abstract, extract it from PubMed's XML data
"""
if self.record.get('HasAbstract') == 1 and xml_dict:
self.abstract = self.parse_abstract(xml_dict)
else:
self.abstract = ''

def set_article_url(self):
def set_article_url(self, resolve_doi=True):
"""
If record has a DOI, set article URL based on where the DOI points.
"""
if 'DOI' in self.record:
doi_url = "/".join(['http://dx.doi.org', self.record['DOI']])

try:
response = urlopen(doi_url)
except URLError:
self.url = ''
if resolve_doi:
try:
response = urlopen(doi_url)
except URLError:
self.url = ''
else:
self.url = response.geturl()
else:
self.url = response.geturl()
self.url = doi_url

else:
self.url = ''

Expand All @@ -201,7 +210,7 @@ def set_pub_year_month_day(self, xml_dict):
try:
self.month = datetime.datetime.strptime(
month_short, "%b").month
except (ValueError, TypeError) as e:
except (ValueError, TypeError):
self.month = ''

else:
Expand Down
59 changes: 57 additions & 2 deletions pubmed_lookup/test_pubmed_lookup.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,69 @@
import copy
import os
import unittest
from io import StringIO

import command_line
from pubmed_lookup import Publication, PubMedLookup


class TestConsole(unittest.TestCase):
"""Test command-line tools."""

def setUp(self):
self.out = StringIO()
self.pmid = '22331878'

self.citation = (
'Goodspeed D, Chehab EW, Min-Venditti A, Braam J, Covington MF '
'(2012). Arabidopsis synchronizes jasmonate-mediated defense with '
'insect circadian behavior. Proc Natl Acad Sci U S A 109(12): '
'4674-7.')
self.mini_citation = (
'Goodspeed D - Covington MF - 2012 - Proc Natl Acad Sci U S A')

self.article_url = 'http://www.pnas.org/content/109/12/4674'
self.doi_url = 'http://dx.doi.org/10.1073/pnas.1116368109'

def test_pubmed_citation(self):
command_line.pubmed_citation([self.pmid], out=self.out)
output = self.out.getvalue()
self.assertEqual(output, self.citation + '\n')

def test_pubmed_citation_m(self):
command_line.pubmed_citation(['-m', self.pmid], out=self.out)
output = self.out.getvalue()
self.assertEqual(output, self.mini_citation + '\n')

def test_pubmed_citation_mini(self):
command_line.pubmed_citation(['--mini', self.pmid], out=self.out)
output = self.out.getvalue()
self.assertEqual(output, self.mini_citation + '\n')

def test_pubmed_url(self):
command_line.pubmed_url([self.pmid], out=self.out)
output = self.out.getvalue()
self.assertEqual(output, self.article_url + '\n')

def test_pubmed_url_d(self):
command_line.pubmed_url(['-d', self.pmid], out=self.out)
output = self.out.getvalue()
self.assertEqual(output, self.doi_url + '\n')

def test_pubmed_url_doi(self):
command_line.pubmed_url(['--doi', self.pmid], out=self.out)
output = self.out.getvalue()
self.assertEqual(output, self.doi_url + '\n')


class TestPublication(unittest.TestCase):
@classmethod
def setUpClass(cls):
# Get publication record
email = ''
cls.pmid = '22331878'
lookup = PubMedLookup(cls.pmid, email)
cls.master_record = Publication(lookup)
cls.lookup = PubMedLookup(cls.pmid, email)
cls.master_record = Publication(cls.lookup)

# Set frequently used expected results
cls.authors = 'Goodspeed D, Chehab EW, Min-Venditti A, Braam J, ' \
Expand Down Expand Up @@ -120,6 +171,10 @@ def test_invalid_doi(self):
self.record.set_article_url()
self.assertEqual(self.record.url, '')

def test_dont_resolve_doi(self):
record = Publication(self.lookup, resolve_doi=False)
self.assertEqual(record.url, 'http://dx.doi.org/10.1073/pnas.1116368109')


class TestPubMedLookup(unittest.TestCase):
def setUp(self):
Expand Down
8 changes: 7 additions & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ def read(*paths):

setup(
name='pubmed-lookup',
version='0.1.5',
version='0.2.0',
packages=['pubmed_lookup'],
test_suite='pubmed_lookup.test_pubmed_lookup',
include_package_data=True,
Expand All @@ -47,4 +47,10 @@ def read(*paths):
'Programming Language :: Python :: 3 :: Only',
],
install_requires=install_requires,
entry_points={
'console_scripts': [
'pubmed-citation=pubmed_lookup.command_line:pubmed_citation',
'pubmed-url=pubmed_lookup.command_line:pubmed_url',
],
},
)

0 comments on commit fe68c76

Please sign in to comment.