You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
119 lines
3.9 KiB
119 lines
3.9 KiB
from __future__ import unicode_literals
|
|
|
|
import os
|
|
import datetime
|
|
|
|
from .. import repo
|
|
from .. import endecoder
|
|
from .. import bibstruct
|
|
from .. import color
|
|
from .. import content
|
|
from ..paper import Paper
|
|
from ..uis import get_ui
|
|
from ..content import system_path, read_text_file
|
|
from ..command_utils import add_doc_copy_arguments
|
|
|
|
|
|
_ABORT_USE_IGNORE_MSG = " Aborting import. Use --ignore-malformed to ignore."
|
|
_IGNORING_MSG = " Ignoring it."
|
|
|
|
|
|
def parser(subparsers, conf):
|
|
parser = subparsers.add_parser(
|
|
'import',
|
|
help='import paper(s) to the repository.')
|
|
parser.add_argument(
|
|
'bibpath',
|
|
help=("path to bibtex, bibtexml or bibyaml file, or a directory "
|
|
"containing such files; will not recurse into subdirectories."))
|
|
parser.add_argument(
|
|
'keys', nargs='*',
|
|
help=("one or several keys to import from the file; if not provided,"
|
|
" all entries will be imported."))
|
|
parser.add_argument(
|
|
'-O', '--overwrite', action='store_true', default=False,
|
|
help="overwrite keys already in the database.")
|
|
parser.add_argument(
|
|
'-i', '--ignore-malformed', action='store_true', default=False,
|
|
help="ignore malformed and unreadable files and entries.")
|
|
add_doc_copy_arguments(parser, copy=False)
|
|
return parser
|
|
|
|
|
|
def many_from_path(ui, bibpath, ignore=False):
|
|
"""Extract list of papers found in bibliographic files in path.
|
|
|
|
The behavior is to:
|
|
- ignore wrong entries,
|
|
- overwrite duplicated entries.
|
|
:returns: dictionary of (key, paper | exception)
|
|
if loading of entry failed, the excpetion is returned in the
|
|
dictionary in place of the paper
|
|
"""
|
|
coder = endecoder.EnDecoder()
|
|
|
|
bibpath = system_path(bibpath)
|
|
if os.path.isdir(bibpath):
|
|
all_files = [os.path.join(bibpath, f) for f in os.listdir(bibpath)
|
|
if os.path.splitext(f)[-1][1:] == 'bib']
|
|
else:
|
|
all_files = [bibpath]
|
|
|
|
biblist = []
|
|
for filepath in all_files:
|
|
try:
|
|
biblist.append(coder.decode_bibdata(read_text_file(filepath)))
|
|
except coder.BibDecodingError:
|
|
error = "Could not parse bibtex at {}.".format(filepath)
|
|
if ignore:
|
|
ui.warning(error + _IGNORING_MSG)
|
|
else:
|
|
ui.error(error + _ABORT_USE_IGNORE_MSG)
|
|
ui.exit()
|
|
|
|
papers = {}
|
|
for b in biblist:
|
|
for k, b in b.items():
|
|
if k in papers:
|
|
ui.warning('Duplicated citekey {}. Keeping the last one.'.format(k))
|
|
try:
|
|
papers[k] = Paper(k, b)
|
|
papers[k].added = datetime.datetime.now()
|
|
except ValueError as e:
|
|
error = 'Could not load entry for citekey {} ({}).'.format(k, e)
|
|
if ignore:
|
|
ui.warning(error + _IGNORING_MSG)
|
|
else:
|
|
ui.error(error + _ABORT_USE_IGNORE_MSG)
|
|
ui.exit()
|
|
return papers
|
|
|
|
|
|
def command(conf, args):
|
|
"""
|
|
:param bibpath: path (no url yet) to a bibliography file
|
|
"""
|
|
|
|
ui = get_ui()
|
|
bibpath = args.bibpath
|
|
doc_import = args.doc_copy or 'copy'
|
|
|
|
rp = repo.Repository(conf)
|
|
# Extract papers from bib
|
|
papers = many_from_path(ui, bibpath, ignore=args.ignore_malformed)
|
|
keys = args.keys or papers.keys()
|
|
for k in keys:
|
|
p = papers[k]
|
|
rp.push_paper(p, overwrite=args.overwrite)
|
|
ui.info('{} imported.'.format(color.dye_out(p.citekey, 'citekey')))
|
|
docfile = bibstruct.extract_docfile(p.bibdata)
|
|
if docfile is None:
|
|
ui.warning("No file for {}.".format(p.citekey))
|
|
else:
|
|
rp.push_doc(p.citekey, docfile,
|
|
copy=(doc_import in ('copy', 'move')))
|
|
if doc_import == 'move' and content.content_type(docfile) != 'url':
|
|
content.remove_file(docfile)
|
|
|
|
rp.close()
|