bmc/main.py

347 lines
13 KiB
Python
Raw Normal View History

2014-04-25 14:13:37 +02:00
#!/usr/bin/env python2
# -*- coding: utf8 -*-
import argparse
import os
2014-04-24 00:18:49 +02:00
import shutil
import subprocess
import sys
import tempfile
import backend
import fetcher
import tearpages
import tools
import params
2014-04-24 00:18:49 +02:00
from bibtexparser.bparser import BibTexParser
from bibtexparser.customization import homogeneize_latex_encoding
2014-04-24 00:18:49 +02:00
EDITOR = os.environ.get('EDITOR') if os.environ.get('EDITOR') else 'vim'
2014-04-24 00:18:49 +02:00
def checkBibtex(filename, bibtex):
2014-05-02 00:07:49 +02:00
print("The bibtex entry found for "+filename+" is:")
bibtex = BibTexParser(bibtex, customization=homogeneize_latex_encoding)
2014-04-25 14:13:37 +02:00
bibtex = bibtex.get_entry_dict()
if len(bibtex) > 0:
bibtex_name = bibtex.keys()[0]
bibtex = bibtex[bibtex_name]
bibtex_string = backend.parsed2Bibtex(bibtex)
else:
bibtex_string = ''
print(bibtex_string)
2014-05-02 00:07:49 +02:00
check = tools.rawInput("Is it correct? [Y/n] ")
2014-04-25 14:13:37 +02:00
while check.lower() == 'n':
with tempfile.NamedTemporaryFile(suffix=".tmp") as tmpfile:
tmpfile.write(bibtex_string)
tmpfile.flush()
subprocess.call([EDITOR, tmpfile.name])
bibtex = BibTexParser(tmpfile.read()+"\n",
customization=homogeneize_latex_encoding)
bibtex = bibtex.get_entry_dict()
if len(bibtex) > 0:
bibtex_name = bibtex.keys()[0]
bibtex = bibtex[bibtex_name]
bibtex_string = backend.parsed2Bibtex(bibtex)
else:
bibtex_string = ''
2014-05-02 00:07:49 +02:00
print("\nThe bibtex entry for "+filename+" is:")
print(bibtex_string)
2014-05-02 00:07:49 +02:00
check = tools.rawInput("Is it correct? [Y/n] ")
return bibtex
def addFile(src, filetype):
2014-04-24 00:18:49 +02:00
"""
Add a file to the library
"""
if filetype == 'article' or filetype is None:
doi = fetcher.findDOI(src)
2014-05-02 00:07:49 +02:00
if (filetype == 'article' or filetype is None) and doi is False:
arxiv = fetcher.findArXivId(src)
2014-05-02 00:07:49 +02:00
if filetype == 'book' or (filetype is None and doi is False and arxiv is
False):
isbn = fetcher.findISBN(src)
2014-05-02 00:07:49 +02:00
if doi is False and isbn is False and arxiv is False:
if filetype is None:
2014-05-02 00:07:49 +02:00
tools.warning("Could not determine the DOI nor the arXiv id nor " +
"the ISBN for "+src+"."+"Switching to manual entry.")
doi_arxiv_isbn = ''
while doi_arxiv_isbn not in ['doi', 'arxiv', 'isbn']:
doi_arxiv_isbn = tools.rawInput("DOI / arXiv / ISBN? ").lower()
if doi_arxiv_isbn == 'doi':
doi = tools.rawInput('DOI? ')
elif doi_arxiv_isbn == 'arxiv':
arxiv = tools.rawInput('arXiv id? ')
else:
2014-05-02 00:07:49 +02:00
isbn = tools.rawInput('ISBN? ')
elif filetype == 'article':
2014-05-02 00:07:49 +02:00
tools.warning("Could not determine the DOI nor the arXiv id for " +
src+", switching to manual entry.")
doi_arxiv = ''
while doi_arxiv not in ['doi', 'arxiv']:
doi_arxiv = tools.rawInput("DOI / arXiv? ").lower()
if doi_arxiv == 'doi':
doi = tools.rawInput('DOI? ')
else:
arxiv = tools.rawInput('arXiv id? ')
elif filetype == 'book':
2014-04-28 22:23:05 +02:00
tools.warning("Could not determine the ISBN for "+src +
", switching to manual entry.")
2014-05-02 00:07:49 +02:00
isbn = tools.rawInput('ISBN? ')
elif doi is not False:
print("DOI for "+src+" is "+doi+".")
2014-05-02 00:07:49 +02:00
elif arxiv is not False:
print("ArXiv id for "+src+" is "+arxiv+".")
elif isbn is not False:
print("ISBN for "+src+" is "+isbn+".")
if doi is not False and doi != '':
2014-04-25 14:13:37 +02:00
# Add extra \n for bibtexparser
bibtex = fetcher.doi2Bib(doi).strip().replace(',', ",\n")+"\n"
2014-05-02 00:07:49 +02:00
elif arxiv is not False and arxiv != '':
bibtex = fetcher.arXiv2Bib(arxiv).strip().replace(',', ",\n")+"\n"
elif isbn is not False and isbn != '':
2014-04-25 14:13:37 +02:00
# Idem
bibtex = fetcher.isbn2Bib(isbn).strip()+"\n"
else:
bibtex = ''
bibtex = checkBibtex(src, bibtex)
2014-05-01 00:45:31 +02:00
new_name = backend.getNewName(src, bibtex)
2014-04-24 00:18:49 +02:00
while os.path.exists(new_name):
2014-04-28 22:23:05 +02:00
tools.warning("file "+new_name+" already exists.")
default_rename = new_name.replace(tools.getExtension(new_name),
" (2)"+tools.getExtension(new_name))
2014-05-02 00:07:49 +02:00
rename = tools.rawInput("New name ["+default_rename+"]? ")
if rename == '':
new_name = default_rename
else:
new_name = rename
2014-04-25 15:36:54 +02:00
bibtex['file'] = new_name
2014-04-24 00:18:49 +02:00
try:
shutil.copy2(src, new_name)
except IOError:
new_name = False
sys.exit("Unable to move file to library dir " + params.folder+".")
2014-04-24 00:18:49 +02:00
# Remove first page of IOP papers
if 'IOP' in bibtex['publisher'] and bibtex['type'] == 'article':
tearpages.tearpage(new_name)
backend.bibtexAppend(bibtex)
return new_name
2014-04-24 00:18:49 +02:00
def downloadFile(url, filetype):
2014-04-28 22:23:05 +02:00
dl, contenttype = fetcher.download(url)
2014-04-26 18:40:32 +02:00
if dl is not False:
tmp = tempfile.NamedTemporaryFile(suffix='.'+contenttype)
with open(tmp.name, 'w+') as fh:
2014-04-26 18:40:32 +02:00
fh.write(dl)
new_name = addFile(tmp.name, filetype)
tmp.close()
return new_name
else:
2014-04-28 22:23:05 +02:00
tools.warning("Could not fetch "+url)
return False
def openFile(ident):
try:
with open(params.folder+'index.bib', 'r') as fh:
bibtex = BibTexParser(fh.read(),
customization=homogeneize_latex_encoding)
bibtex = bibtex.get_entry_dict()
except:
tools.warning("Unable to open index file.")
return False
if ident not in bibtex.keys():
return False
else:
subprocess.Popen(['xdg-open', bibtex[ident]['file']])
return True
2014-05-01 00:45:31 +02:00
def resync():
diff = backend.diffFilesIndex()
for entry in diff:
if entry['file'] == '':
print("Found entry in index without associated file.")
confirm = False
while not confirm:
filename = tools.rawInput("File to import for this entry " +
"(leave empty to delete the " +
2014-05-02 00:07:49 +02:00
"entry)? ")
2014-05-01 00:45:31 +02:00
if filename == '':
break
else:
confirm = True
if 'doi' in entry.keys():
doi = fetcher.findDOI(filename)
if doi is not False and doi != entry['doi']:
confirm = tools.rawInput("Found DOI does not " +
"match bibtex entry " +
"DOI, continue anyway " +
"? [y/N]")
confirm = (confirm.lower() == 'y')
2014-05-02 00:07:49 +02:00
if 'Eprint' in entry.keys():
arxiv = fetcher.findArXivId(filename)
if arxiv is not False and arxiv != entry['Eprint']:
confirm = tools.rawInput("Found arXiv id does " +
"not match bibtex " +
"entry arxiv id, " +
"continue anyway ? [y/N]")
confirm = (confirm.lower() == 'y')
2014-05-01 00:45:31 +02:00
elif 'isbn' in entry.keys():
isbn = fetcher.findISBN(filename)
if isbn is not False and isbn != entry['isbn']:
confirm = tools.rawInput("Found ISBN does not " +
"match bibtex entry " +
"ISBN, continue anyway " +
"? [y/N]")
confirm = (confirm.lower() == 'y')
continue
if filename == '':
backend.deleteId(entry['id'])
else:
new_name = backend.getNewName(filename, entry)
try:
shutil.copy2(filename, new_name)
except IOError:
new_name = False
sys.exit("Unable to move file to library dir " +
params.folder+".")
backend.bibtexEdit(entry['id'], {'file': filename})
else:
print("Found file without any associated entry in index.")
action = ''
while action.lower() not in ['import', 'delete']:
2014-05-02 00:07:49 +02:00
action = tools.rawInput("What to do? [import / delete] ")
2014-05-01 00:45:31 +02:00
action = action.lower()
if action == 'import':
tmp = tempfile.NamedTemporaryFile()
shutil.copy(entry['file'], tmp.name)
filetype = tools.getExtension(entry['file'])
try:
os.remove(entry['file'])
except:
tools.warning("Unable to delete file "+entry['file'])
if not addFile(tmp.name, filetype):
tools.warning("Unable to reimport file "+entry['file'])
tmp.close()
else:
backend.deleteFile(entry['file'])
print(entry['file'] + " removed from disk and " +
"index.")
2014-04-24 00:18:49 +02:00
if __name__ == '__main__':
parser = argparse.ArgumentParser(description="A bibliography " +
"management tool.")
subparsers = parser.add_subparsers(help="sub-command help")
parser_download = subparsers.add_parser('download', help="download help")
parser_download.add_argument('-t', '--type', default=None,
choices=['article', 'book'],
help="Type of the file to download")
parser_download.add_argument('url', nargs='+',
help="url of the file to import")
parser_download.set_defaults(func='download')
parser_import = subparsers.add_parser('import', help="import help")
parser_import.add_argument('-t', '--type', default=None,
choices=['article', 'book'],
help="Type of the file to import")
parser_import.add_argument('file', nargs='+',
help="path to the file to import")
parser_import.set_defaults(func='import')
parser_delete = subparsers.add_parser('delete', help="delete help")
parser_delete.add_argument('files', metavar='entry', nargs='+',
help="a filename or an identifier")
parser_delete.set_defaults(func='delete')
parser_list = subparsers.add_parser('list', help="list help")
parser_list.set_defaults(func='list')
# TODO
parser_search = subparsers.add_parser('search', help="search help")
parser_search.set_defaults(func='search')
# TODO
parser_open = subparsers.add_parser('open', help="open help")
parser_open.add_argument('ids', metavar='id', nargs='+',
help="an identifier")
parser_open.set_defaults(func='open')
parser_resync = subparsers.add_parser('resync', help="resync help")
parser_resync.set_defaults(func='resync')
args = parser.parse_args()
try:
if args.func == 'download':
for url in args.url:
new_name = downloadFile(url, args.t)
if new_name is not False:
print(url+" successfully imported as "+new_name)
else:
tools.warning("An error occurred while downloading "+url)
sys.exit()
2014-04-24 00:18:49 +02:00
if args.func == 'import':
for filename in args.file:
new_name = addFile(filename, args.t)
if new_name is not False:
print(sys.argv[2]+" successfully imported as " +
new_name+".")
else:
tools.warning("An error occurred while importing " +
filename)
sys.exit()
2014-04-24 00:18:49 +02:00
elif args.func == 'delete':
for filename in args.file:
confirm = tools.rawInput("Are you sure you want to delete " +
filename+"? [y/N] ")
2014-04-25 15:36:54 +02:00
if confirm.lower() == 'y':
if not backend.deleteId(filename):
if not backend.deleteFile(filename):
tools.warning("Unable to delete "+filename)
sys.exit(1)
2014-04-25 15:36:54 +02:00
print(filename+" successfully deleted.")
2014-04-25 15:36:54 +02:00
sys.exit()
2014-04-25 14:22:34 +02:00
elif args.func == 'list':
raise Exception('TODO')
2014-04-24 00:18:49 +02:00
elif args.func == 'search':
raise Exception('TODO')
2014-04-25 15:36:54 +02:00
elif args.func == 'open':
for filename in args.ids:
2014-05-02 22:08:24 +02:00
if not openFile(filename):
sys.exit("Unable to open file associated " +
"to ident "+filename)
elif args.func == 'resync':
2014-05-02 00:07:49 +02:00
confirm = tools.rawInput("Resync files and bibtex index? [y/N] ")
2014-05-01 00:45:31 +02:00
if confirm.lower() == 'y':
resync()
except KeyboardInterrupt:
sys.exit()