2014-05-26 16:12:21 +02:00
|
|
|
# -*- coding: utf8 -*-
|
|
|
|
# -----------------------------------------------------------------------------
|
|
|
|
# "THE NO-ALCOHOL BEER-WARE LICENSE" (Revision 42):
|
|
|
|
# Phyks (webmaster@phyks.me) wrote this file. As long as you retain this notice
|
|
|
|
# you can do whatever you want with this stuff (and you can also do whatever
|
|
|
|
# you want with this stuff without retaining it, but that's not cool...). If we
|
|
|
|
# meet some day, and you think this stuff is worth it, you can buy me a
|
|
|
|
# <del>beer</del> soda in return.
|
|
|
|
# Phyks
|
|
|
|
# -----------------------------------------------------------------------------
|
|
|
|
|
2014-08-03 12:38:40 +02:00
|
|
|
from __future__ import unicode_literals
|
2014-04-28 23:35:06 +02:00
|
|
|
import os
|
2014-05-01 00:45:31 +02:00
|
|
|
import re
|
2014-08-03 00:17:01 +02:00
|
|
|
import libbmc.tools as tools
|
|
|
|
import libbmc.fetcher as fetcher
|
2014-12-03 12:54:24 +01:00
|
|
|
import bibtexparser
|
2014-08-01 01:33:32 +02:00
|
|
|
from libbmc.config import Config
|
2014-05-09 23:37:17 +02:00
|
|
|
from codecs import open
|
2014-04-28 23:35:06 +02:00
|
|
|
|
|
|
|
|
2014-06-30 23:02:30 +02:00
|
|
|
config = Config()
|
|
|
|
|
|
|
|
|
2014-05-27 12:17:59 +02:00
|
|
|
def getNewName(src, bibtex, tag='', override_format=None):
|
2014-05-01 00:45:31 +02:00
|
|
|
"""
|
2014-06-30 00:19:38 +02:00
|
|
|
Return the formatted name according to config for the given
|
2014-05-01 00:45:31 +02:00
|
|
|
bibtex entry
|
|
|
|
"""
|
|
|
|
authors = re.split(' and ', bibtex['author'])
|
|
|
|
|
|
|
|
if bibtex['type'] == 'article':
|
2014-05-27 12:17:59 +02:00
|
|
|
if override_format is None:
|
2014-06-30 00:19:38 +02:00
|
|
|
new_name = config.get("format_articles")
|
2014-05-27 12:17:59 +02:00
|
|
|
else:
|
|
|
|
new_name = override_format
|
2014-05-01 00:45:31 +02:00
|
|
|
try:
|
|
|
|
new_name = new_name.replace("%j", bibtex['journal'])
|
2014-07-01 20:31:19 +02:00
|
|
|
except KeyError:
|
2014-05-01 00:45:31 +02:00
|
|
|
pass
|
|
|
|
elif bibtex['type'] == 'book':
|
2014-05-27 12:17:59 +02:00
|
|
|
if override_format is None:
|
2014-06-30 00:19:38 +02:00
|
|
|
new_name = config.get("format_books")
|
2014-05-27 12:17:59 +02:00
|
|
|
else:
|
|
|
|
new_name = override_format
|
2014-05-01 00:45:31 +02:00
|
|
|
|
|
|
|
new_name = new_name.replace("%t", bibtex['title'])
|
|
|
|
try:
|
|
|
|
new_name = new_name.replace("%Y", bibtex['year'])
|
2014-07-01 20:31:19 +02:00
|
|
|
except KeyError:
|
2014-05-01 00:45:31 +02:00
|
|
|
pass
|
|
|
|
new_name = new_name.replace("%f", authors[0].split(',')[0].strip())
|
|
|
|
new_name = new_name.replace("%l", authors[-1].split(',')[0].strip())
|
|
|
|
new_name = new_name.replace("%a", ', '.join([i.split(',')[0].strip()
|
|
|
|
for i in authors]))
|
2014-05-14 23:59:12 +02:00
|
|
|
if('archiveprefix' in bibtex and
|
|
|
|
'arXiv' in bibtex['archiveprefix']):
|
2014-05-14 22:45:25 +02:00
|
|
|
new_name = new_name.replace("%v",
|
2014-06-30 00:19:38 +02:00
|
|
|
'-' +
|
|
|
|
bibtex['eprint'][bibtex['eprint'].
|
|
|
|
rfind('v'):])
|
2014-05-14 22:45:25 +02:00
|
|
|
else:
|
|
|
|
new_name = new_name.replace("%v", '')
|
2014-05-01 00:45:31 +02:00
|
|
|
|
2014-06-30 00:19:38 +02:00
|
|
|
for custom in config.get("format_custom"):
|
2014-05-17 22:21:51 +02:00
|
|
|
new_name = custom(new_name)
|
|
|
|
|
2014-05-05 00:19:29 +02:00
|
|
|
if tag == '':
|
2014-06-30 00:19:38 +02:00
|
|
|
new_name = (config.get("folder") + tools.slugify(new_name) +
|
2014-05-05 00:19:29 +02:00
|
|
|
tools.getExtension(src))
|
|
|
|
else:
|
2014-06-30 00:19:38 +02:00
|
|
|
if not os.path.isdir(config.get("folder") + tag):
|
2014-05-05 00:19:29 +02:00
|
|
|
try:
|
2014-06-30 00:19:38 +02:00
|
|
|
os.mkdir(config.get("folder") + tag)
|
2014-07-01 20:31:19 +02:00
|
|
|
except OSError:
|
2014-05-05 00:19:29 +02:00
|
|
|
tools.warning("Unable to create tag dir " +
|
2014-06-30 00:19:38 +02:00
|
|
|
config.get("folder")+tag+".")
|
2014-05-05 00:19:29 +02:00
|
|
|
|
2014-06-30 00:19:38 +02:00
|
|
|
new_name = (config.get("folder") + tools.slugify(tag) + '/' +
|
2014-05-05 00:19:29 +02:00
|
|
|
tools.slugify(new_name) + tools.getExtension(src))
|
|
|
|
|
|
|
|
return new_name
|
2014-05-01 00:45:31 +02:00
|
|
|
|
|
|
|
|
2014-04-28 23:35:06 +02:00
|
|
|
def bibtexAppend(data):
|
|
|
|
"""Append data to the main bibtex file
|
|
|
|
|
|
|
|
data is a dict for one entry in bibtex, as the one from bibtexparser output
|
|
|
|
"""
|
2014-05-02 12:46:37 +02:00
|
|
|
try:
|
2014-06-30 00:19:38 +02:00
|
|
|
with open(config.get("folder")+'index.bib', 'a', encoding='utf-8') \
|
|
|
|
as fh:
|
2014-05-11 19:29:42 +02:00
|
|
|
fh.write(tools.parsed2Bibtex(data)+"\n")
|
2014-07-01 20:31:19 +02:00
|
|
|
except IOError as e:
|
2014-06-30 23:02:30 +02:00
|
|
|
raise e
|
2014-05-02 12:46:37 +02:00
|
|
|
tools.warning("Unable to open index file.")
|
|
|
|
return False
|
2014-04-28 23:35:06 +02:00
|
|
|
|
|
|
|
|
2014-05-01 00:45:31 +02:00
|
|
|
def bibtexEdit(ident, modifs):
|
|
|
|
"""Update ident key in bibtex file, modifications are in modifs dict"""
|
|
|
|
|
2014-05-02 12:46:37 +02:00
|
|
|
try:
|
2014-06-30 00:19:38 +02:00
|
|
|
with open(config.get("folder")+'index.bib', 'r', encoding='utf-8') \
|
|
|
|
as fh:
|
2014-12-03 12:54:24 +01:00
|
|
|
bibtex = bibtexparser.load(fh)
|
|
|
|
bibtex = bibtex.entries_dict
|
2014-07-01 20:31:19 +02:00
|
|
|
except (IOError, TypeError):
|
2014-05-02 12:46:37 +02:00
|
|
|
tools.warning("Unable to open index file.")
|
|
|
|
return False
|
2014-05-01 00:45:31 +02:00
|
|
|
|
|
|
|
for key in modifs.keys():
|
|
|
|
bibtex[ident][key] = modifs[key]
|
|
|
|
bibtexRewrite(bibtex)
|
|
|
|
|
|
|
|
|
2014-04-28 23:35:06 +02:00
|
|
|
def bibtexRewrite(data):
|
|
|
|
"""Rewrite the bibtex index file.
|
|
|
|
|
|
|
|
data is a dict of bibtex entry dict.
|
|
|
|
"""
|
|
|
|
bibtex = ''
|
|
|
|
for entry in data.keys():
|
2014-05-11 19:29:42 +02:00
|
|
|
bibtex += tools.parsed2Bibtex(data[entry])+"\n"
|
2014-05-02 12:46:37 +02:00
|
|
|
try:
|
2014-06-30 00:19:38 +02:00
|
|
|
with open(config.get("folder")+'index.bib', 'w', encoding='utf-8') \
|
|
|
|
as fh:
|
2014-05-02 12:46:37 +02:00
|
|
|
fh.write(bibtex)
|
2014-07-01 20:31:19 +02:00
|
|
|
except (IOError, TypeError):
|
2014-05-02 12:46:37 +02:00
|
|
|
tools.warning("Unable to open index file.")
|
|
|
|
return False
|
2014-04-28 23:35:06 +02:00
|
|
|
|
|
|
|
|
|
|
|
def deleteId(ident):
|
|
|
|
"""Delete a file based on its id in the bibtex file"""
|
2014-05-02 12:46:37 +02:00
|
|
|
try:
|
2014-06-30 00:19:38 +02:00
|
|
|
with open(config.get("folder")+'index.bib', 'r', encoding='utf-8') \
|
|
|
|
as fh:
|
2014-12-03 12:54:24 +01:00
|
|
|
bibtex = bibtexparser.load(fh)
|
|
|
|
bibtex = bibtex.entries_dict
|
2014-07-01 20:31:19 +02:00
|
|
|
except (IOError, TypeError):
|
2014-05-02 12:46:37 +02:00
|
|
|
tools.warning("Unable to open index file.")
|
|
|
|
return False
|
2014-04-28 23:35:06 +02:00
|
|
|
|
|
|
|
if ident not in bibtex.keys():
|
|
|
|
return False
|
|
|
|
|
|
|
|
try:
|
|
|
|
os.remove(bibtex[ident]['file'])
|
2014-07-01 20:31:19 +02:00
|
|
|
except (KeyError, OSError):
|
2014-04-28 23:35:06 +02:00
|
|
|
tools.warning("Unable to delete file associated to id "+ident+" : " +
|
|
|
|
bibtex[ident]['file'])
|
2014-05-05 00:19:29 +02:00
|
|
|
|
|
|
|
try:
|
|
|
|
if not os.listdir(os.path.dirname(bibtex[ident]['file'])):
|
|
|
|
os.rmdir(os.path.dirname(bibtex[ident]['file']))
|
2014-07-01 20:31:19 +02:00
|
|
|
except (KeyError, OSError):
|
2014-05-05 00:19:29 +02:00
|
|
|
tools.warning("Unable to delete empty tag dir " +
|
|
|
|
os.path.dirname(bibtex[ident]['file']))
|
|
|
|
|
2014-05-01 00:45:31 +02:00
|
|
|
try:
|
|
|
|
del(bibtex[ident])
|
|
|
|
bibtexRewrite(bibtex)
|
|
|
|
except KeyError:
|
|
|
|
tools.warning("No associated bibtex entry in index for file " +
|
|
|
|
bibtex[ident]['file'])
|
2014-04-28 23:35:06 +02:00
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
|
|
def deleteFile(filename):
|
|
|
|
"""Delete a file based on its filename"""
|
2014-05-02 12:46:37 +02:00
|
|
|
try:
|
2014-06-30 00:19:38 +02:00
|
|
|
with open(config.get("folder")+'index.bib', 'r', encoding='utf-8') \
|
|
|
|
as fh:
|
2014-12-03 12:54:24 +01:00
|
|
|
bibtex = bibtexparser.load(fh)
|
|
|
|
bibtex = bibtex.entries_dict
|
2014-07-01 20:31:19 +02:00
|
|
|
except (TypeError, IOError):
|
2014-05-02 12:46:37 +02:00
|
|
|
tools.warning("Unable to open index file.")
|
|
|
|
return False
|
2014-04-28 23:35:06 +02:00
|
|
|
|
|
|
|
found = False
|
2014-08-03 19:10:30 +02:00
|
|
|
for key in list(bibtex.keys()):
|
2014-05-11 03:06:18 +02:00
|
|
|
try:
|
|
|
|
if os.path.samefile(bibtex[key]['file'], filename):
|
|
|
|
found = True
|
|
|
|
try:
|
|
|
|
os.remove(bibtex[key]['file'])
|
2014-07-01 20:31:19 +02:00
|
|
|
except (KeyError, OSError):
|
2014-05-11 03:06:18 +02:00
|
|
|
tools.warning("Unable to delete file associated to id " +
|
2014-05-17 17:23:56 +02:00
|
|
|
key+" : "+bibtex[key]['file'])
|
2014-05-11 03:06:18 +02:00
|
|
|
|
|
|
|
try:
|
|
|
|
if not os.listdir(os.path.dirname(filename)):
|
|
|
|
os.rmdir(os.path.dirname(filename))
|
2014-07-01 20:31:19 +02:00
|
|
|
except OSError:
|
2014-05-11 03:06:18 +02:00
|
|
|
tools.warning("Unable to delete empty tag dir " +
|
2014-05-17 17:23:56 +02:00
|
|
|
os.path.dirname(filename))
|
2014-05-11 03:06:18 +02:00
|
|
|
|
|
|
|
try:
|
|
|
|
del(bibtex[key])
|
|
|
|
except KeyError:
|
|
|
|
tools.warning("No associated bibtex entry in index for " +
|
2014-05-17 17:23:56 +02:00
|
|
|
"file " + bibtex[key]['file'])
|
2014-07-01 20:31:19 +02:00
|
|
|
except (KeyError, OSError):
|
2014-05-11 03:06:18 +02:00
|
|
|
pass
|
2014-04-28 23:35:06 +02:00
|
|
|
if found:
|
|
|
|
bibtexRewrite(bibtex)
|
2014-05-14 17:07:57 +02:00
|
|
|
elif os.path.isfile(filename):
|
|
|
|
os.remove(filename)
|
2014-04-28 23:35:06 +02:00
|
|
|
return found
|
2014-05-01 00:45:31 +02:00
|
|
|
|
|
|
|
|
|
|
|
def diffFilesIndex():
|
|
|
|
"""Compute differences between Bibtex index and PDF files
|
|
|
|
|
|
|
|
Returns a dict with bibtex entry:
|
|
|
|
* full bibtex entry with file='' if file is not found
|
|
|
|
* only file entry if file with missing bibtex entry
|
|
|
|
"""
|
2014-06-30 00:19:38 +02:00
|
|
|
files = tools.listDir(config.get("folder"))
|
2014-05-17 17:23:56 +02:00
|
|
|
files = [i for i in files if tools.getExtension(i) in ['.pdf', '.djvu']]
|
2014-05-02 12:46:37 +02:00
|
|
|
try:
|
2014-06-30 00:19:38 +02:00
|
|
|
with open(config.get("folder")+'index.bib', 'r', encoding='utf-8') \
|
|
|
|
as fh:
|
2014-12-03 12:54:24 +01:00
|
|
|
index = bibtexparser.load(fh)
|
|
|
|
index_diff = index.entries_dict
|
2014-07-01 20:31:19 +02:00
|
|
|
except (TypeError, IOError):
|
2014-05-02 12:46:37 +02:00
|
|
|
tools.warning("Unable to open index file.")
|
|
|
|
return False
|
2014-05-01 00:45:31 +02:00
|
|
|
|
|
|
|
for key in index_diff.keys():
|
|
|
|
if index_diff[key]['file'] not in files:
|
|
|
|
index_diff[key]['file'] = ''
|
|
|
|
else:
|
|
|
|
files.remove(index_diff[key]['file'])
|
|
|
|
|
|
|
|
for filename in files:
|
|
|
|
index_diff[filename] = {'file': filename}
|
|
|
|
|
2014-12-03 12:54:24 +01:00
|
|
|
return index.entries_dict
|
2014-05-04 01:50:41 +02:00
|
|
|
|
|
|
|
|
2014-05-27 12:17:59 +02:00
|
|
|
def getBibtex(entry, file_id='both', clean=False):
|
2014-05-04 01:50:41 +02:00
|
|
|
"""Returns the bibtex entry corresponding to entry, as a dict
|
|
|
|
|
|
|
|
entry is either a filename or a bibtex ident
|
|
|
|
file_id is file or id or both to search for a file / id / both
|
2014-06-30 00:19:38 +02:00
|
|
|
clean is to clean the ignored fields specified in config
|
2014-05-04 01:50:41 +02:00
|
|
|
"""
|
|
|
|
try:
|
2014-06-30 00:19:38 +02:00
|
|
|
with open(config.get("folder")+'index.bib', 'r', encoding='utf-8') \
|
|
|
|
as fh:
|
2014-12-03 12:54:24 +01:00
|
|
|
bibtex = bibtexparser.load(fh)
|
|
|
|
bibtex = bibtex.entries_dict
|
2014-07-01 20:31:19 +02:00
|
|
|
except (TypeError, IOError):
|
2014-05-04 01:50:41 +02:00
|
|
|
tools.warning("Unable to open index file.")
|
|
|
|
return False
|
2014-05-05 00:19:29 +02:00
|
|
|
|
2014-05-04 01:50:41 +02:00
|
|
|
bibtex_entry = False
|
|
|
|
if file_id == 'both' or file_id == 'id':
|
|
|
|
try:
|
|
|
|
bibtex_entry = bibtex[entry]
|
|
|
|
except KeyError:
|
|
|
|
pass
|
2014-05-14 14:53:56 +02:00
|
|
|
if file_id == 'both' or file_id == 'file':
|
|
|
|
if os.path.isfile(entry):
|
|
|
|
for key in bibtex.keys():
|
|
|
|
if os.path.samefile(bibtex[key]['file'], entry):
|
|
|
|
bibtex_entry = bibtex[key]
|
|
|
|
break
|
2014-05-27 12:17:59 +02:00
|
|
|
if clean:
|
2014-06-30 00:19:38 +02:00
|
|
|
for field in config.get("ignore_fields"):
|
2014-05-27 12:17:59 +02:00
|
|
|
try:
|
|
|
|
del(bibtex_entry[field])
|
|
|
|
except KeyError:
|
|
|
|
pass
|
2014-05-04 01:50:41 +02:00
|
|
|
return bibtex_entry
|
2014-05-07 22:04:46 +02:00
|
|
|
|
|
|
|
|
2015-06-09 12:02:54 +02:00
|
|
|
def getEntries(full=False):
|
2014-05-07 22:04:46 +02:00
|
|
|
"""Returns the list of all entries in the bibtex index"""
|
|
|
|
try:
|
2014-06-30 00:19:38 +02:00
|
|
|
with open(config.get("folder")+'index.bib', 'r', encoding='utf-8') \
|
|
|
|
as fh:
|
2014-12-03 12:54:24 +01:00
|
|
|
bibtex = bibtexparser.load(fh)
|
|
|
|
bibtex = bibtex.entries_dict
|
2014-07-01 20:31:19 +02:00
|
|
|
except (TypeError, IOError):
|
2014-05-07 22:04:46 +02:00
|
|
|
tools.warning("Unable to open index file.")
|
|
|
|
return False
|
|
|
|
|
2015-06-09 12:02:54 +02:00
|
|
|
if full:
|
|
|
|
return bibtex
|
|
|
|
else:
|
|
|
|
return list(bibtex.keys())
|
2014-05-07 22:04:46 +02:00
|
|
|
|
|
|
|
|
|
|
|
def updateArXiv(entry):
|
2014-05-08 22:07:52 +02:00
|
|
|
"""Look for new versions of arXiv entry `entry`
|
|
|
|
|
|
|
|
Returns False if no new versions or not an arXiv entry,
|
2014-05-14 22:45:25 +02:00
|
|
|
Returns the new bibtex otherwise.
|
2014-05-08 22:07:52 +02:00
|
|
|
"""
|
2014-05-07 22:04:46 +02:00
|
|
|
bibtex = getBibtex(entry)
|
|
|
|
# Check arXiv
|
2014-05-17 17:23:56 +02:00
|
|
|
if('archiveprefix' not in bibtex or
|
2014-05-14 22:45:25 +02:00
|
|
|
'arXiv' not in bibtex['archiveprefix']):
|
2014-05-07 22:04:46 +02:00
|
|
|
return False
|
|
|
|
|
2014-05-14 22:45:25 +02:00
|
|
|
arxiv_id = bibtex['eprint']
|
2014-05-18 21:22:39 +02:00
|
|
|
arxiv_id_no_v = re.sub(r'v\d+\Z', '', arxiv_id)
|
|
|
|
ids = set(arxiv_id)
|
|
|
|
|
|
|
|
for entry in getEntries():
|
|
|
|
if('archiveprefix' not in bibtex or
|
|
|
|
'arXiv' not in bibtex['archiveprefix']):
|
|
|
|
continue
|
|
|
|
ids.add(bibtex['eprint'])
|
|
|
|
|
2014-12-03 12:54:24 +01:00
|
|
|
last_bibtex = bibtexparser.loads(fetcher.arXiv2Bib(arxiv_id_no_v))
|
|
|
|
last_bibtex = last_bibtex.entries_dict
|
2014-08-03 12:38:40 +02:00
|
|
|
last_bibtex = last_bibtex[list(last_bibtex.keys())[0]]
|
2014-05-07 22:04:46 +02:00
|
|
|
|
2014-05-18 21:22:39 +02:00
|
|
|
if last_bibtex['eprint'] not in ids:
|
2014-05-07 22:04:46 +02:00
|
|
|
return last_bibtex
|
|
|
|
else:
|
|
|
|
return False
|
2014-05-08 22:07:52 +02:00
|
|
|
|
|
|
|
|
|
|
|
def search(query):
|
|
|
|
"""Performs a search in the bibtex index.
|
|
|
|
|
|
|
|
Param: query is a dict of keys and the query for these keys
|
|
|
|
"""
|
|
|
|
raise Exception('TODO')
|