Update doc to rst format for generation with Sphinx

This commit is contained in:
Lucas Verney 2015-12-25 01:43:49 +01:00
parent 6fc337095d
commit ec97c0a320
10 changed files with 154 additions and 133 deletions

1
.gitignore vendored
View File

@ -1 +1,2 @@
__pycache__ __pycache__
docs/

View File

@ -1,12 +1,23 @@
""" """
This file contains the database schema in SQLAlchemy format. This file contains the database schema in SQLAlchemy format.
""" """
from sqlalchemy import Column, Integer, String from sqlalchemy import event, Column, Integer, String
from sqlalchemy.engine import Engine
from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base() Base = declarative_base()
@event.listens_for(Engine, "connect")
def set_sqlite_pragma(dbapi_connection, connection_record):
"""
Auto enable foreign keys for SQLite.
"""
cursor = dbapi_connection.cursor()
cursor.execute("PRAGMA foreign_keys=ON")
cursor.close()
class Paper(Base): class Paper(Base):
__tablename__ = 'papers' __tablename__ = 'papers'
id = Column(Integer, primary_key=True) id = Column(Integer, primary_key=True)

11
main.py
View File

@ -1,8 +1,7 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
import bottle import bottle
from bottle.ext import sqlalchemy from bottle.ext import sqlalchemy
from sqlalchemy import create_engine, event from sqlalchemy import create_engine
from sqlalchemy.engine import Engine
import database import database
import routes import routes
@ -32,14 +31,6 @@ plugin = sqlalchemy.Plugin(
app.install(plugin) app.install(plugin)
# Auto enable foreign keys for SQLite
@event.listens_for(Engine, "connect")
def set_sqlite_pragma(dbapi_connection, connection_record):
cursor = dbapi_connection.cursor()
cursor.execute("PRAGMA foreign_keys=ON")
cursor.close()
# Routes # Routes
app.get("/papers", callback=routes.get.fetch_papers) app.get("/papers", callback=routes.get.fetch_papers)
app.get("/papers/<id:int>", callback=routes.get.fetch_by_id) app.get("/papers/<id:int>", callback=routes.get.fetch_by_id)

View File

@ -13,10 +13,8 @@ def sources_from_arxiv(eprint):
""" """
Download sources on arXiv for a given preprint. Download sources on arXiv for a given preprint.
Params: :param eprint: The arXiv id (e.g. ``1401.2910`` or ``1401.2910v1``).
- eprint is the arXiv id (e.g. 1401.2910 or 1401.2910v1). :returns: A ``TarFile`` object of the sources of the arXiv preprint.
Returns a TarFile object of the sources of the arXiv preprint.
""" """
r = requests.get("http://arxiv.org/e-print/%s" % (eprint,)) r = requests.get("http://arxiv.org/e-print/%s" % (eprint,))
file_object = io.BytesIO(r.content) file_object = io.BytesIO(r.content)
@ -27,10 +25,8 @@ def bbl_from_arxiv(eprint):
""" """
Get the .bbl files (if any) of a given preprint. Get the .bbl files (if any) of a given preprint.
Params: :param eprint: The arXiv id (e.g. ``1401.2910`` or ``1401.2910v1``).
- eprint is the arXiv id (e.g. 1401.2910 or 1401.2910v1). :returns: A list of the ``.bbl`` files as text (if any) or ``None``.
Returns a list of the .bbl files as text (if any) or None.
""" """
tf = sources_from_arxiv(eprint) tf = sources_from_arxiv(eprint)
bbl_files = [i for i in tf.getmembers() if i.name.endswith(".bbl")] bbl_files = [i for i in tf.getmembers() if i.name.endswith(".bbl")]
@ -43,10 +39,8 @@ def get_cited_dois(eprint):
""" """
Get the .bbl files (if any) of a given preprint. Get the .bbl files (if any) of a given preprint.
Params: :param eprint: The arXiv id (e.g. ``1401.2910`` or ``1401.2910v1``).
- eprint is the arXiv id (e.g. 1401.2910 or 1401.2910v1). :returns: A dict of cleaned plaintext citations and their associated doi.
Returns a dict of cleaned plaintext citations and their associated doi.
""" """
bbl_files = bbl_from_arxiv(eprint) bbl_files = bbl_from_arxiv(eprint)
dois = {} dois = {}
@ -59,10 +53,8 @@ def get_arxiv_eprint_from_doi(doi):
""" """
Get the arXiv eprint id for a given DOI. Get the arXiv eprint id for a given DOI.
Params: :param doi: The DOI of the resource to look for.
- doi is the DOI of the resource to look for. :returns: The arXiv eprint id, or ``None`` if not found.
Returns the arXiv eprint id, or None if not found.
""" """
r = requests.get("http://export.arxiv.org/api/query", r = requests.get("http://export.arxiv.org/api/query",
params={ params={
@ -80,10 +72,8 @@ def get_doi(eprint):
""" """
Get the associated DOI for a given arXiv eprint. Get the associated DOI for a given arXiv eprint.
Params: :param eprint: The arXiv eprint id.
- eprint is the arXiv eprint id. :returns: The DOI if any, or ``None``.
Returns the DOI if any, or None.
""" """
r = requests.get("http://export.arxiv.org/api/query", r = requests.get("http://export.arxiv.org/api/query",
params={ params={

View File

@ -13,12 +13,10 @@ from . import tools
def clean_bibitem(bibitem): def clean_bibitem(bibitem):
""" """
Return a plaintext representation of the bibitem from the bbl file. Return a plaintext representation of the bibitem from the ``.bbl`` file.
Params: :param bibitem: The text content of the bibitem.
- bibitem is the text content of the bibitem. :returns: A cleaned plaintext citation from the bibitem.
Returns a cleaned plaintext citation from the bibitem.
""" """
script_dir = os.path.dirname(os.path.abspath(__file__)) script_dir = os.path.dirname(os.path.abspath(__file__))
output = subprocess.check_output(["%s/opendetex/delatex" % (script_dir,), output = subprocess.check_output(["%s/opendetex/delatex" % (script_dir,),
@ -31,12 +29,11 @@ def clean_bibitem(bibitem):
def parse(bbl): def parse(bbl):
""" """
Parse a *.bbl file to get a clean list of plaintext citations. Parse a ``*.bbl`` file to get a clean list of plaintext citations.
Params: :param bbl: Either the path to the .bbl file or the content of a ``.bbl`` \
- bbl is either the path to the .bbl file or the content of a bbl file. file.
:returns: A list of cleaned plaintext citations.
Returns a list of cleaned plaintext citations.
""" """
# Handle path or content # Handle path or content
if os.path.isfile(bbl): if os.path.isfile(bbl):
@ -59,11 +56,10 @@ def get_dois(bbl_input):
""" """
Get the papers cited by the paper identified by the given DOI. Get the papers cited by the paper identified by the given DOI.
Params: :param bbl_input: Either the path to the .bbl file or the content of a \
- bbl_input is either the path to the .bbl file or the content of a bbl bbl file.
file.
Returns a dict of cleaned plaintext citations and their associated doi. :returns: A dict of cleaned plaintext citations and their associated doi.
""" """
cleaned_citations_with_URLs = parse(bbl_input) cleaned_citations_with_URLs = parse(bbl_input)
dois = {} dois = {}

View File

@ -10,6 +10,9 @@ from . import tools
def extract_doi_links(urls): def extract_doi_links(urls):
""" """
Try to find a DOI from a given list of URLs. Try to find a DOI from a given list of URLs.
:param urls: A list of URLs.
:returns: First matching DOI URL, or ``None``.
""" """
doi_urls = [url for url in urls if "/doi/" in url] doi_urls = [url for url in urls if "/doi/" in url]
if len(doi_urls) > 0: if len(doi_urls) > 0:
@ -22,6 +25,9 @@ def extract_doi_links(urls):
def extract_arxiv_links(urls): def extract_arxiv_links(urls):
""" """
Try to find an arXiv link from a given list of URLs. Try to find an arXiv link from a given list of URLs.
:param urls: A list of URLs.
:returns: First matching arXiv URL, or ``None``.
""" """
arxiv_urls = [url for url in urls if "://arxiv.org" in url] arxiv_urls = [url for url in urls if "://arxiv.org" in url]
if len(arxiv_urls) > 0: if len(arxiv_urls) > 0:
@ -35,9 +41,14 @@ def match_doi_or_arxiv(text, only=["DOI", "arXiv"]):
Search for a valid article ID (DOI or ArXiv) in the given text Search for a valid article ID (DOI or ArXiv) in the given text
(regex-based). (regex-based).
Returns a tuple (type, first matching ID) or None if not found. From \
From : http://en.dogeno.us/2010/02/release-a-python-script-for-organizing-scientific-papers-pyrenamepdf-py/ http://en.dogeno.us/2010/02/release-a-python-script-for-organizing-scientific-papers-pyrenamepdf-py/ \
and https://github.com/minad/bibsync/blob/3fdf121016f6187a2fffc66a73cd33b45a20e55d/lib/bibsync/utils.rb and \
https://github.com/minad/bibsync/blob/3fdf121016f6187a2fffc66a73cd33b45a20e55d/lib/bibsync/utils.rb.
:param text: Input text on which matching is to be done.
:param only: List of matches to look for (DOI/arXiv).
:returns: a tuple ``(type, first matching ID)`` or ``None`` if not found.
""" """
text = text.lower() text = text.lower()
# Try to extract DOI # Try to extract DOI
@ -86,10 +97,8 @@ def get_oa_version(doi):
""" """
Get an OA version for a given DOI. Get an OA version for a given DOI.
Params: :param doi: A DOI or a dx.doi.org link.
- doi is a DOI or a dx.doi.org link. :returns: The URL of the OA version of the given DOI, or ``None``.
Returns the URL of the OA version of the given DOI, or None.
""" """
# If DOI is a link, truncate it # If DOI is a link, truncate it
if "dx.doi.org" in doi: if "dx.doi.org" in doi:

View File

@ -3,15 +3,17 @@ This file contains various utility functions.
""" """
def replaceAll(text, dic): def replaceAll(text, replace_dict):
"""Replace all the dic keys by the associated item in text""" """
for i, j in dic.items(): Replace all the ``replace_dict`` keys by their associated item in ``text``.
"""
for i, j in replace_dict.items():
text = text.replace(i, j) text = text.replace(i, j)
return text return text
def clean_whitespaces(text): def clean_whitespaces(text):
""" """
Remove double whitespaces and trailing . and , from text. Remove double whitespaces and trailing "." and "," from text.
""" """
return ' '.join(text.strip().rstrip(".,").split()) return ' '.join(text.strip().rstrip(".,").split())

View File

@ -11,34 +11,39 @@ def fetch_papers(db):
""" """
Fetch all matching papers. Fetch all matching papers.
``` .. code-block:: bash
GET /papers
Accept: application/vnd.api+json
```
Filtering is possible using `id=ID`, `doi=DOI`, `arxiv_id=ARXIV_ID` or any GET /papers
combination of these GET parameters. Other parameters are ignored. Accept: application/vnd.api+json
```
{ Filtering is possible using ``id=ID``, ``doi=DOI``, ``arxiv_id=ARXIV_ID`` \
"data": [ or any combination of these GET parameters. Other parameters are ignored.
{
"type": "papers",
"id": 1, .. code-block:: json
"attributes": {
"doi": "10.1126/science.1252319", {
"arxiv_id": "1401.2910" "data": [
}, {
"links": { "type": "papers",
"self": "/papers/1" "id": 1,
}, "attributes": {
"relationships": { "doi": "10.1126/science.1252319",
TODO "arxiv_id": "1401.2910"
},
"links": {
"self": "/papers/1"
},
"relationships": {
TODO
}
} }
} ]
] }
}
``` :param db: A database session, injected by the ``Bottle`` plugin.
:returns: An ``HTTPResponse``.
""" """
filters = {k: bottle.request.params[k] filters = {k: bottle.request.params[k]
for k in bottle.request.params for k in bottle.request.params
@ -55,31 +60,36 @@ def fetch_by_id(id, db):
""" """
Fetch a resource identified by its internal id. Fetch a resource identified by its internal id.
``` .. code-block:: bash
GET /id/<id>
Accept: application/vnd.api+json
```
``` GET /id/<id>
{ Accept: application/vnd.api+json
"data": {
{
"type": "papers", .. code-block:: json
"id": 1,
"attributes": { {
"doi": "10.1126/science.1252319", "data": {
"arxiv_id": "1401.2910" {
}, "type": "papers",
"links": { "id": 1,
"self": "/papers/1" "attributes": {
}, "doi": "10.1126/science.1252319",
"relationships": { "arxiv_id": "1401.2910"
TODO },
"links": {
"self": "/papers/1"
},
"relationships": {
TODO
}
} }
} }
} }
}
``` :param id: The id of the requested article.
:param db: A database session, injected by the ``Bottle`` plugin.
:returns: An ``HTTPResponse``.
""" """
resource = db.query(database.Paper).filter_by(id=id).first() resource = db.query(database.Paper).filter_by(id=id).first()
if resource: if resource:

View File

@ -14,40 +14,44 @@ def create_paper(db):
""" """
Create a new resource identified by its DOI or arXiv eprint id. Create a new resource identified by its DOI or arXiv eprint id.
``` .. code-block:: bash
POST /papers
Content-Type: application/vnd.api+json
Accept: application/vnd.api+json
{ POST /papers
"data": { Content-Type: application/vnd.api+json
"doi": "10.1126/science.1252319", Accept: application/vnd.api+json
// OR
"arxiv_id": "1401.2910" {
"data": {
"doi": "10.1126/science.1252319",
// OR
"arxiv_id": "1401.2910"
}
} }
}
```
```
{ .. code-block:: json
"data": {
{ {
"type": "papers", "data": {
"id": 1, {
"attributes": { "type": "papers",
"doi": "10.1126/science.1252319", "id": 1,
"arxiv_id": "1401.2910" "attributes": {
}, "doi": "10.1126/science.1252319",
"links": { "arxiv_id": "1401.2910"
"self": "/papers/1" },
}, "links": {
"relationships": { "self": "/papers/1"
TODO },
"relationships": {
TODO
}
} }
} }
} }
}
``` :param db: A database session, injected by the ``Bottle`` plugin.
:returns: An ``HTTPResponse``.
""" """
data = json.loads(bottle.request.body.read().decode("utf-8")) data = json.loads(bottle.request.body.read().decode("utf-8"))
# Validate the request # Validate the request
@ -83,7 +87,9 @@ def create_by_doi(doi, db):
""" """
Create a new resource identified by its DOI, if it does not exist. Create a new resource identified by its DOI, if it does not exist.
Return None if insertion failed, the Paper object otherwise. :param doi: The DOI of the paper.
:param db: A database session.
:returns: ``None`` if insertion failed, the ``Paper`` object otherwise.
""" """
paper = database.Paper(doi=doi) paper = database.Paper(doi=doi)
@ -110,7 +116,9 @@ def create_by_arxiv(arxiv, db):
Create a new resource identified by its arXiv eprint ID, if it does not Create a new resource identified by its arXiv eprint ID, if it does not
exist. exist.
Return None if insertion failed, the Paper object otherwise. :param arxiv: The arXiv eprint ID.
:param db: A database session.
:returns: ``None`` if insertion failed, the ``Paper`` object otherwise.
""" """
paper = database.Paper(arxiv_id=arxiv) paper = database.Paper(arxiv_id=arxiv)

View File

@ -7,7 +7,10 @@ import json
def pretty_json(data): def pretty_json(data):
""" """
Return pretty printed JSON-formatted string. Return pretty-printed JSON-formatted string.
:param data: A string to be converted.
:returns: A pretty-printed JSON-formatted string.
""" """
return json.dumps(data, return json.dumps(data,
sort_keys=True, sort_keys=True,