diff --git a/pubs/commands/add_cmd.py b/pubs/commands/add_cmd.py index ada5e7c..b56927e 100644 --- a/pubs/commands/add_cmd.py +++ b/pubs/commands/add_cmd.py @@ -116,6 +116,9 @@ def command(conf, args): if bibentry is None: ui.error('invalid bibfile {}.'.format(bibfile)) + # exclude bibtex fields if specified + utils.remove_bibtex_fields(bibentry, conf['main']['exclude_bibtex_fields']) + # citekey citekey = args.citekey diff --git a/pubs/commands/edit_cmd.py b/pubs/commands/edit_cmd.py index 5ea7679..3e52383 100644 --- a/pubs/commands/edit_cmd.py +++ b/pubs/commands/edit_cmd.py @@ -6,7 +6,7 @@ from .. import color from ..uis import get_ui from ..endecoder import EnDecoder -from ..utils import resolve_citekey +from ..utils import resolve_citekey, remove_bibtex_fields from ..completion import CiteKeyCompletion from ..events import ModifyEvent @@ -59,6 +59,9 @@ def command(conf, args): ui.info(("The metadata of paper '{}' was successfully " "edited.".format(color.dye_out(citekey, 'citekey')))) else: + # exclude bibtex fields if specified + remove_bibtex_fields(content, conf['main']['exclude_bibtex_fields']) + new_paper = Paper.from_bibentry(content, metadata=paper.metadata) if rp.rename_paper(new_paper, old_citekey=paper.citekey): diff --git a/pubs/commands/export_cmd.py b/pubs/commands/export_cmd.py index b316efc..9c3831b 100644 --- a/pubs/commands/export_cmd.py +++ b/pubs/commands/export_cmd.py @@ -5,7 +5,7 @@ import argparse from .. import repo from ..uis import get_ui from .. import endecoder -from ..utils import resolve_citekey_list +from ..utils import resolve_citekey_list, remove_bibtex_fields from ..endecoder import BIBFIELD_ORDER from ..completion import CiteKeyCompletion, CommaSeparatedListCompletion @@ -53,6 +53,9 @@ def command(conf, args): for p in papers: bib[p.citekey] = p.bibdata + # exclude bibtex fields if specified + remove_bibtex_fields(bib, conf['main']['exclude_bibtex_fields']) + exporter = endecoder.EnDecoder() bibdata_raw = exporter.encode_bibdata(bib, args.ignore_fields) ui.message(bibdata_raw) diff --git a/pubs/commands/import_cmd.py b/pubs/commands/import_cmd.py index dbc5480..775ae41 100644 --- a/pubs/commands/import_cmd.py +++ b/pubs/commands/import_cmd.py @@ -11,6 +11,7 @@ from .. import content from ..paper import Paper from ..uis import get_ui from ..content import system_path, read_text_file +from ..utils import remove_bibtex_fields from ..command_utils import add_doc_copy_arguments @@ -40,7 +41,7 @@ def parser(subparsers, conf): return parser -def many_from_path(ui, bibpath, ignore=False): +def many_from_path(ui, bibpath, exclude_bibtex_fields=[], ignore=False): """Extract list of papers found in bibliographic files in path. The behavior is to: @@ -62,7 +63,10 @@ def many_from_path(ui, bibpath, ignore=False): biblist = [] for filepath in all_files: try: - biblist.append(coder.decode_bibdata(read_text_file(filepath))) + bibentry = coder.decode_bibdata(read_text_file(filepath)) + # exclude bibtex fields if specified + remove_bibtex_fields(bibentry, exclude_bibtex_fields) + biblist.append(bibentry) except coder.BibDecodingError: error = "Could not parse bibtex at {}.".format(filepath) if ignore: @@ -100,7 +104,9 @@ def command(conf, args): rp = repo.Repository(conf) # Extract papers from bib - papers = many_from_path(ui, bibpath, ignore=args.ignore_malformed) + papers = many_from_path(ui, bibpath, + exclude_bibtex_fields=conf['main']['exclude_bibtex_fields'], + ignore=args.ignore_malformed) keys = args.keys or papers.keys() for k in keys: p = papers[k] diff --git a/pubs/config/spec.py b/pubs/config/spec.py index b691f80..a323ada 100644 --- a/pubs/config/spec.py +++ b/pubs/config/spec.py @@ -35,6 +35,11 @@ max_authors = integer(default=3) # the full python stack is printed. debug = boolean(default=False) +# which bibliographic fields to exclude from bibtex files. By default, none. +# Please note that excluding critical fields such as `title` or `author` +# will break many commands of pubs. +exclude_bibtex_fields = force_list(default=list()) + [formating] # Enable bold formatting, if the terminal supports it. diff --git a/pubs/utils.py b/pubs/utils.py index 120edfd..a49894a 100644 --- a/pubs/utils.py +++ b/pubs/utils.py @@ -87,3 +87,9 @@ def standardize_doi(doi): new_doi = match.group(0) return new_doi + +def remove_bibtex_fields(bibentry, fields): + for item in bibentry.values(): + for field in fields: + if field in item: + del item[field] diff --git a/tests/str_fixtures.py b/tests/str_fixtures.py index d2fbfec..7dfd5b8 100644 --- a/tests/str_fixtures.py +++ b/tests/str_fixtures.py @@ -138,6 +138,9 @@ edit_cmd = "vim" # the full python stack is printed. debug = False +# which bibliographic fields to exclude from bibtex files. +exclude_bibtex_fields = + [formating] # Enable bold formatting, if the terminal supports it. diff --git a/tests/test_usecase.py b/tests/test_usecase.py index 9219657..98f819d 100644 --- a/tests/test_usecase.py +++ b/tests/test_usecase.py @@ -437,6 +437,18 @@ class TestAdd(URLContentTestCase): self.execute_cmds(cmds) self.assertEqual(cm.exception.code, 1) + def test_add_excludes_bibtex_fields(self): + self.execute_cmds(['pubs init']) + config = conf.load_conf() + config['main']['exclude_bibtex_fields'] = ['abstract', 'publisher'] + conf.save_conf(config) + self.execute_cmds(['pubs add data/pagerank.bib']) + with FakeFileOpen(self.fs)(self.default_pubs_dir + '/bib/Page99.bib', 'r') as buf: + out = endecoder.EnDecoder().decode_bibdata(buf.read()) + for bib in out.values(): + self.assertFalse('abstract' in bib or 'publisher' in bib) + self.assertTrue('title' in bib and 'author' in bib) + class TestList(DataCommandTestCase): @@ -829,6 +841,22 @@ class TestUsecase(DataCommandTestCase): ] self.execute_cmds(cmds) + def test_editor_excludes_bibtex_field(self): + cmds = ['pubs init', + 'pubs add data/pagerank.bib', + ] + self.execute_cmds(cmds) + config = conf.load_conf() + config['main']['exclude_bibtex_fields'] = ['author'] + conf.save_conf(config) + cmds = [('pubs edit Page99', ['@misc{Page99, title="TTT", author="auth"}', 'n'])] + self.execute_cmds(cmds) + with FakeFileOpen(self.fs)(self.default_pubs_dir + '/bib/Page99.bib', 'r') as buf: + out = endecoder.EnDecoder().decode_bibdata(buf.read()) + for bib in out.values(): + self.assertFalse('author' in bib) + self.assertTrue('title' in bib) + def test_add_aborts(self): with self.assertRaises(FakeSystemExit): cmds = ['pubs init', @@ -908,6 +936,19 @@ class TestUsecase(DataCommandTestCase): fixtures.page_bibentry, ignore_fields=['author', 'title']) self.assertEqual(outs[2], expected + os.linesep) + def test_export_excludes_bibtex_field(self): + cmds = ['pubs init', + 'pubs add data/pagerank.bib' + ] + self.execute_cmds(cmds) + config = conf.load_conf() + config['main']['exclude_bibtex_fields'] = ['url'] + conf.save_conf(config) + outs = self.execute_cmds(['pubs export Page99']) + for bib in endecoder.EnDecoder().decode_bibdata(outs[0]).values(): + self.assertFalse('url' in bib) + self.assertTrue('title' in bib and 'author' in bib) + def test_import(self): cmds = ['pubs init', 'pubs import data/', @@ -970,6 +1011,18 @@ class TestUsecase(DataCommandTestCase): outs = self.execute_cmds(cmds) self.assertEqual(1 + 1, len(outs[-1].split('\n'))) + def test_import_excludes_bibtex_field(self): + self.execute_cmds(['pubs init']) + config = conf.load_conf() + config['main']['exclude_bibtex_fields'] = ['abstract'] + conf.save_conf(config) + self.execute_cmds(['pubs import data/ Page99']) + with FakeFileOpen(self.fs)(self.default_pubs_dir + '/bib/Page99.bib', 'r') as buf: + out = endecoder.EnDecoder().decode_bibdata(buf.read()) + for bib in out.values(): + self.assertFalse('abstract' in bib) + self.assertTrue('title' in bib and 'author' in bib) + def test_update(self): cmds = ['pubs init', 'pubs add data/pagerank.bib',