Merge pull request #227 from pubs/feat/remove_prompt
Feat/remove prompt
This commit is contained in:
commit
46da2c9187
@ -5,8 +5,14 @@
|
|||||||
|
|
||||||
[Full Changelog](https://github.com/pubs/pubs/compare/v0.8.3...master)
|
[Full Changelog](https://github.com/pubs/pubs/compare/v0.8.3...master)
|
||||||
|
|
||||||
|
### Implemented enhancements
|
||||||
|
|
||||||
|
- Added support for non-standard bibtex types, e.g. @collection, @software, etc. ([#226](https://github.com/pubs/pubs/pull/226)
|
||||||
|
- The number of displayed authors in listings is now configurable, as the `max_authors` value in the `main` section of the configuration. ([#225](https://github.com/pubs/pubs/pull/225)
|
||||||
|
|
||||||
### Fixed bugs
|
### Fixed bugs
|
||||||
|
|
||||||
|
- Tests don't run on python 2.7 or <=3.4. They may still work, but support will not be tested and will eventually be dropped. ([#223](https://github.com/pubs/pubs/pull/223)
|
||||||
|
|
||||||
## [v0.8.3](https://github.com/pubs/pubs/compare/v0.8.2...v0.8.3) (2019-08-12)
|
## [v0.8.3](https://github.com/pubs/pubs/compare/v0.8.2...v0.8.3) (2019-08-12)
|
||||||
|
|
||||||
|
@ -144,7 +144,7 @@ def setup(conf, force_colors=False):
|
|||||||
|
|
||||||
|
|
||||||
# undye
|
# undye
|
||||||
undye_re = re.compile('\x1b\[[;\d]*[A-Za-z]')
|
undye_re = re.compile('\x1b\\[[;\d]*[A-Za-z]')
|
||||||
|
|
||||||
def undye(s):
|
def undye(s):
|
||||||
"""Purge string s of color"""
|
"""Purge string s of color"""
|
||||||
|
@ -2,6 +2,7 @@ from __future__ import unicode_literals
|
|||||||
|
|
||||||
from .. import repo
|
from .. import repo
|
||||||
from .. import color
|
from .. import color
|
||||||
|
from .. import pretty
|
||||||
from ..uis import get_ui
|
from ..uis import get_ui
|
||||||
from ..utils import resolve_citekey_list
|
from ..utils import resolve_citekey_list
|
||||||
from ..p3 import ustr, u_maybe
|
from ..p3 import ustr, u_maybe
|
||||||
@ -25,11 +26,15 @@ def command(conf, args):
|
|||||||
rp = repo.Repository(conf)
|
rp = repo.Repository(conf)
|
||||||
|
|
||||||
keys = resolve_citekey_list(repo=rp, citekeys=args.citekeys, ui=ui, exit_on_fail=True)
|
keys = resolve_citekey_list(repo=rp, citekeys=args.citekeys, ui=ui, exit_on_fail=True)
|
||||||
|
plural = 's' if len(keys) > 1 else ''
|
||||||
|
|
||||||
if force is None:
|
if force is None:
|
||||||
are_you_sure = (("Are you sure you want to delete the publication(s) [{}]"
|
to_remove_str = '\n'.join(pretty.paper_oneliner(rp.pull_paper(key),
|
||||||
" (this will also delete associated documents)?")
|
max_authors=conf['main']['max_authors'])
|
||||||
.format(', '.join([color.dye_out(c, 'citekey') for c in args.citekeys])))
|
for key in keys)
|
||||||
|
are_you_sure = (("Are you sure you want to delete the following publication{}"
|
||||||
|
" (this will also delete associated documents)?:\n{}\n")
|
||||||
|
.format(plural, to_remove_str))
|
||||||
sure = ui.input_yn(question=are_you_sure, default='n')
|
sure = ui.input_yn(question=are_you_sure, default='n')
|
||||||
if force or sure:
|
if force or sure:
|
||||||
failed = False # Whether something failed
|
failed = False # Whether something failed
|
||||||
@ -42,11 +47,12 @@ def command(conf, args):
|
|||||||
if failed:
|
if failed:
|
||||||
ui.exit() # Exit with nonzero error code
|
ui.exit() # Exit with nonzero error code
|
||||||
else:
|
else:
|
||||||
ui.message('The publication(s) [{}] were removed'.format(
|
|
||||||
|
ui.message('The publication{} {} were removed'.format(plural,
|
||||||
', '.join([color.dye_out(c, 'citekey') for c in keys])))
|
', '.join([color.dye_out(c, 'citekey') for c in keys])))
|
||||||
|
|
||||||
# FIXME: print should check that removal proceeded well.
|
# FIXME: print should check that removal proceeded well.
|
||||||
else:
|
else:
|
||||||
ui.message('The publication(s) [{}] were {} removed'.format(
|
ui.message('The publication{} {} were {} removed'.format(plural,
|
||||||
', '.join([color.dye_out(c, 'citekey') for c in keys]),
|
', '.join([color.dye_out(c, 'citekey') for c in keys]),
|
||||||
color.dye_out('not','bold')))
|
color.dye_out('not','bold')))
|
||||||
|
@ -119,18 +119,18 @@ class EnDecoder(object):
|
|||||||
keyword for keyword in entry['keyword'])
|
keyword for keyword in entry['keyword'])
|
||||||
return entry
|
return entry
|
||||||
|
|
||||||
def decode_bibdata(self, bibdata):
|
def decode_bibdata(self, bibstr):
|
||||||
"""Decodes bibdata from string.
|
"""Decodes bibdata from string.
|
||||||
|
|
||||||
If the decoding fails, returns a BibDecodingError.
|
If the decoding fails, returns a BibDecodingError.
|
||||||
"""
|
"""
|
||||||
if len(bibdata) == 0:
|
if len(bibstr) == 0:
|
||||||
error_msg = 'parsing error: the provided string has length zero.'
|
error_msg = 'parsing error: the provided string has length zero.'
|
||||||
raise self.BibDecodingError(error_msg, bibdata)
|
raise self.BibDecodingError(error_msg, bibstr)
|
||||||
try:
|
try:
|
||||||
entries = bp.bparser.BibTexParser(
|
entries = bp.bparser.BibTexParser(
|
||||||
bibdata, common_strings=True, customization=customizations,
|
bibstr, common_strings=True, customization=customizations,
|
||||||
homogenize_fields=True).get_entry_dict()
|
homogenize_fields=True, ignore_nonstandard_types=False).get_entry_dict()
|
||||||
# Remove id from bibtexparser attribute which is stored as citekey
|
# Remove id from bibtexparser attribute which is stored as citekey
|
||||||
for e in entries:
|
for e in entries:
|
||||||
entries[e].pop(BP_ID_KEY)
|
entries[e].pop(BP_ID_KEY)
|
||||||
@ -147,13 +147,13 @@ class EnDecoder(object):
|
|||||||
return entries
|
return entries
|
||||||
else:
|
else:
|
||||||
raise self.BibDecodingError(('no valid entry found in the provided data: '
|
raise self.BibDecodingError(('no valid entry found in the provided data: '
|
||||||
' {}').format(bibdata), bibdata)
|
' {}').format(bibstr), bibstr)
|
||||||
except (pyparsing.ParseException, pyparsing.ParseSyntaxException) as e:
|
except (pyparsing.ParseException, pyparsing.ParseSyntaxException) as e:
|
||||||
error_msg = self._format_parsing_error(e)
|
error_msg = self._format_parsing_error(e)
|
||||||
raise self.BibDecodingError(error_msg, bibdata)
|
raise self.BibDecodingError(error_msg, bibstr)
|
||||||
except bibtexparser.bibdatabase.UndefinedString as e:
|
except bibtexparser.bibdatabase.UndefinedString as e:
|
||||||
error_msg = 'parsing error: undefined string in provided data: {}'.format(e)
|
error_msg = 'parsing error: undefined string in provided data: {}'.format(e)
|
||||||
raise self.BibDecodingError(error_msg, bibdata)
|
raise self.BibDecodingError(error_msg, bibstr)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _format_parsing_error(cls, e):
|
def _format_parsing_error(cls, e):
|
||||||
|
@ -16,7 +16,7 @@ def filter_filename(filename, ext):
|
|||||||
""" Return the filename without the extension if the extension matches ext.
|
""" Return the filename without the extension if the extension matches ext.
|
||||||
Otherwise return None
|
Otherwise return None
|
||||||
"""
|
"""
|
||||||
pattern = '.*\{}$'.format(ext)
|
pattern = '.*\\{}$'.format(ext)
|
||||||
if re.match(pattern, filename) is not None:
|
if re.match(pattern, filename) is not None:
|
||||||
return u_maybe(filename[:-len(ext)])
|
return u_maybe(filename[:-len(ext)])
|
||||||
|
|
||||||
|
9
tests/data_non_standard/non_standard_collection.bib
Normal file
9
tests/data_non_standard/non_standard_collection.bib
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
@collection{Geometric_phases,
|
||||||
|
title = {Geometric phases in physics},
|
||||||
|
editor = {Shapere, Alfred and Wilczek, Frank},
|
||||||
|
year = {1989},
|
||||||
|
series = {Advanced Series in Mathematical Physics},
|
||||||
|
volume = {5},
|
||||||
|
publisher = {World Scientific},
|
||||||
|
isbn = {9789971506216}
|
||||||
|
}
|
7
tests/data_non_standard/non_standard_software.bib
Normal file
7
tests/data_non_standard/non_standard_software.bib
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
@software{hadoop,
|
||||||
|
author = {{Apache Software Foundation}},
|
||||||
|
title = {Hadoop},
|
||||||
|
url = {https://hadoop.apache.org},
|
||||||
|
version = {0.20.2},
|
||||||
|
date = {2010-02-19},
|
||||||
|
}
|
@ -43,8 +43,8 @@ def capture(f, verbose=False):
|
|||||||
"""
|
"""
|
||||||
def newf(*args, **kwargs):
|
def newf(*args, **kwargs):
|
||||||
old_stderr, old_stdout = sys.stderr, sys.stdout
|
old_stderr, old_stdout = sys.stderr, sys.stdout
|
||||||
sys.stdout = _fake_stdio(additional_out=old_stderr if verbose else None)
|
sys.stdout = _fake_stdio(additional_out=old_stdout if verbose else None)
|
||||||
sys.stderr = _fake_stdio(additional_out=old_stderr if False else None)
|
sys.stderr = _fake_stdio(additional_out=old_stderr if verbose else None)
|
||||||
try:
|
try:
|
||||||
return f(*args, **kwargs), _get_fake_stdio_ucontent(sys.stdout), _get_fake_stdio_ucontent(sys.stderr)
|
return f(*args, **kwargs), _get_fake_stdio_ucontent(sys.stdout), _get_fake_stdio_ucontent(sys.stderr)
|
||||||
finally:
|
finally:
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
|
||||||
bibtex_external0 = """
|
bibtex_external0 = r"""
|
||||||
@techreport{Page99,
|
@techreport{Page99,
|
||||||
number = {1999-66},
|
number = {1999-66},
|
||||||
month = {November},
|
month = {November},
|
||||||
@ -17,7 +17,7 @@ institution = {Stanford InfoLab},
|
|||||||
}
|
}
|
||||||
"""
|
"""
|
||||||
|
|
||||||
bibtex_external_alt = """
|
bibtex_external_alt = r"""
|
||||||
@techreport{Page99,
|
@techreport{Page99,
|
||||||
number = {1999-66},
|
number = {1999-66},
|
||||||
month = {November},
|
month = {November},
|
||||||
@ -33,7 +33,7 @@ institution = {Stanford InfoLab},
|
|||||||
}
|
}
|
||||||
"""
|
"""
|
||||||
|
|
||||||
bibtex_raw0 = """@techreport{
|
bibtex_raw0 = r"""@techreport{
|
||||||
Page99,
|
Page99,
|
||||||
author = "Page, Lawrence and Brin, Sergey and Motwani, Rajeev and Winograd, Terry",
|
author = "Page, Lawrence and Brin, Sergey and Motwani, Rajeev and Winograd, Terry",
|
||||||
publisher = "Stanford InfoLab",
|
publisher = "Stanford InfoLab",
|
||||||
@ -50,12 +50,12 @@ bibtex_raw0 = """@techreport{
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
metadata_raw0 = """docfile: docsdir://Page99.pdf
|
metadata_raw0 = r"""docfile: docsdir://Page99.pdf
|
||||||
tags: [search, network]
|
tags: [search, network]
|
||||||
added: '2013-11-14 13:14:20'
|
added: '2013-11-14 13:14:20'
|
||||||
"""
|
"""
|
||||||
|
|
||||||
turing_bib = """@article{turing1950computing,
|
turing_bib = r"""@article{turing1950computing,
|
||||||
title={Computing machinery and intelligence},
|
title={Computing machinery and intelligence},
|
||||||
author={Turing, Alan M},
|
author={Turing, Alan M},
|
||||||
journal={Mind},
|
journal={Mind},
|
||||||
@ -75,7 +75,7 @@ added: '2013-11-14 13:14:20'
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
# Should not parse (see #113)
|
# Should not parse (see #113)
|
||||||
bibtex_no_citekey = """@Manual{,
|
bibtex_no_citekey = r"""@Manual{,
|
||||||
title = {R: A Language and Environment for Statistical Computing},
|
title = {R: A Language and Environment for Statistical Computing},
|
||||||
author = {{R Core Team}},
|
author = {{R Core Team}},
|
||||||
organization = {R Foundation for Statistical Computing},
|
organization = {R Foundation for Statistical Computing},
|
||||||
@ -85,7 +85,7 @@ bibtex_no_citekey = """@Manual{,
|
|||||||
}
|
}
|
||||||
"""
|
"""
|
||||||
|
|
||||||
bibtex_month = """@inproceedings{Goyal2017,
|
bibtex_month = r"""@inproceedings{Goyal2017,
|
||||||
author = {Goyal, Anirudh and Sordoni, Alessandro and C{\^{o}}t{\'{e}}, Marc-Alexandre and Ke, Nan Rosemary and Bengio, Yoshua},
|
author = {Goyal, Anirudh and Sordoni, Alessandro and C{\^{o}}t{\'{e}}, Marc-Alexandre and Ke, Nan Rosemary and Bengio, Yoshua},
|
||||||
title = {Z-Forcing: Training Stochastic Recurrent Networks},
|
title = {Z-Forcing: Training Stochastic Recurrent Networks},
|
||||||
year = {2017},
|
year = {2017},
|
||||||
@ -94,15 +94,15 @@ bibtex_month = """@inproceedings{Goyal2017,
|
|||||||
}
|
}
|
||||||
"""
|
"""
|
||||||
|
|
||||||
not_bibtex = """@misc{this looks,
|
not_bibtex = r"""@misc{this looks,
|
||||||
like = a = bibtex file but
|
like = a = bibtex file but
|
||||||
, is not a real one!
|
, is not a real one!
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
bibtex_with_latex = """@article{kjaer2018large,
|
bibtex_with_latex = r"""@article{kjaer2018large,
|
||||||
title={A large impact crater beneath Hiawatha Glacier in northwest Greenland},
|
title={A large impact crater beneath Hiawatha Glacier in northwest Greenland},
|
||||||
author={Kj{\\ae}r, Kurt H and Larsen, Nicolaj K and Binder, Tobias and Bj{\\o}rk, Anders A and Eisen, Olaf and Fahnestock, Mark A and Funder, Svend and Garde, Adam A and Haack, Henning and Helm, Veit and others},
|
author={Kj{\ae}r, Kurt H and Larsen, Nicolaj K and Binder, Tobias and Bj{\o}rk, Anders A and Eisen, Olaf and Fahnestock, Mark A and Funder, Svend and Garde, Adam A and Haack, Henning and Helm, Veit and others},
|
||||||
journal={Science advances},
|
journal={Science advances},
|
||||||
volume={4},
|
volume={4},
|
||||||
number={11},
|
number={11},
|
||||||
|
@ -200,8 +200,8 @@ class TestFilterPaper(unittest.TestCase):
|
|||||||
|
|
||||||
def test_latex_enc(self):
|
def test_latex_enc(self):
|
||||||
latexenc_paper = doe_paper.deepcopy()
|
latexenc_paper = doe_paper.deepcopy()
|
||||||
latexenc_paper.bibentry['Doe2013']['title'] = "{E}l Ni{\~n}o"
|
latexenc_paper.bibentry['Doe2013']['title'] = r"{E}l Ni{\~n}o"
|
||||||
latexenc_paper.bibentry['Doe2013']['author'][0] = "Erd\H{o}s, Paul"
|
latexenc_paper.bibentry['Doe2013']['author'][0] = r"Erd\H{o}s, Paul"
|
||||||
self.assertTrue(get_paper_filter(['title:El'])(latexenc_paper))
|
self.assertTrue(get_paper_filter(['title:El'])(latexenc_paper))
|
||||||
self.assertTrue(get_paper_filter(['title:Niño'])(latexenc_paper))
|
self.assertTrue(get_paper_filter(['title:Niño'])(latexenc_paper))
|
||||||
self.assertTrue(get_paper_filter(['author:erdős'])(latexenc_paper))
|
self.assertTrue(get_paper_filter(['author:erdős'])(latexenc_paper))
|
||||||
@ -209,12 +209,12 @@ class TestFilterPaper(unittest.TestCase):
|
|||||||
|
|
||||||
def test_normalize_unicode(self):
|
def test_normalize_unicode(self):
|
||||||
latexenc_paper = doe_paper.deepcopy()
|
latexenc_paper = doe_paper.deepcopy()
|
||||||
latexenc_paper.bibentry['Doe2013']['title'] = "{E}l Ni{\~n}o"
|
latexenc_paper.bibentry['Doe2013']['title'] = r"{E}l Ni{\~n}o"
|
||||||
self.assertTrue(get_paper_filter(['title:Nin\u0303o'])(latexenc_paper))
|
self.assertTrue(get_paper_filter(['title:Nin\u0303o'])(latexenc_paper))
|
||||||
|
|
||||||
def test_strict(self):
|
def test_strict(self):
|
||||||
latexenc_paper = doe_paper.deepcopy()
|
latexenc_paper = doe_paper.deepcopy()
|
||||||
latexenc_paper.bibentry['Doe2013']['title'] = "El Ni{\~n}o"
|
latexenc_paper.bibentry['Doe2013']['title'] = r"El Ni{\~n}o"
|
||||||
self.assertFalse(get_paper_filter(
|
self.assertFalse(get_paper_filter(
|
||||||
['title:Nin\u0303o'], strict=True)(latexenc_paper))
|
['title:Nin\u0303o'], strict=True)(latexenc_paper))
|
||||||
|
|
||||||
|
@ -1091,6 +1091,22 @@ class TestUsecase(DataCommandTestCase):
|
|||||||
actual = self.execute_cmds(cmds, capture_output=True)
|
actual = self.execute_cmds(cmds, capture_output=True)
|
||||||
self.assertEqual(correct, actual)
|
self.assertEqual(correct, actual)
|
||||||
|
|
||||||
|
def test_add_non_standard(self):
|
||||||
|
"""Test that non-standard bibtex are correctly added"""
|
||||||
|
self.fs.add_real_directory(os.path.join(self.rootpath, 'data_non_standard'), read_only=False)
|
||||||
|
correct = ['Initializing pubs in /pubs\n',
|
||||||
|
'added to pubs:\n[Geometric_phases] "Geometric phases in physics" (1989) \n',
|
||||||
|
'added to pubs:\n[hadoop] Foundation, Apache Software "Hadoop" \n',
|
||||||
|
]
|
||||||
|
cmds = ['pubs init -p /pubs',
|
||||||
|
'pubs add data_non_standard/non_standard_collection.bib',
|
||||||
|
'pubs add data_non_standard/non_standard_software.bib',
|
||||||
|
# 'pubs list',
|
||||||
|
]
|
||||||
|
actual = self.execute_cmds(cmds, capture_output=True)
|
||||||
|
self.assertEqual(correct, actual)
|
||||||
|
|
||||||
|
|
||||||
@mock.patch('pubs.apis.requests.get', side_effect=mock_requests.mock_requests_get)
|
@mock.patch('pubs.apis.requests.get', side_effect=mock_requests.mock_requests_get)
|
||||||
def test_readme(self, reqget):
|
def test_readme(self, reqget):
|
||||||
"""Test that the readme example work."""
|
"""Test that the readme example work."""
|
||||||
@ -1099,7 +1115,7 @@ class TestUsecase(DataCommandTestCase):
|
|||||||
self.fs.add_real_file(os.path.join(self.rootpath, 'data/pagerank.pdf'), target_path='data/Knuth1995.pdf')
|
self.fs.add_real_file(os.path.join(self.rootpath, 'data/pagerank.pdf'), target_path='data/Knuth1995.pdf')
|
||||||
|
|
||||||
cmds = ['pubs init',
|
cmds = ['pubs init',
|
||||||
'pubs import data/collection.bib',
|
'pubs import data/three_articles.bib',
|
||||||
'pubs add data/pagerank.bib -d data/pagerank.pdf',
|
'pubs add data/pagerank.bib -d data/pagerank.pdf',
|
||||||
#'pubs add -D 10.1007/s00422-012-0514-6 -d data/pagerank.pdf',
|
#'pubs add -D 10.1007/s00422-012-0514-6 -d data/pagerank.pdf',
|
||||||
'pubs add -I 978-0822324669 -d data/oyama2000the.pdf',
|
'pubs add -I 978-0822324669 -d data/oyama2000the.pdf',
|
||||||
|
Loading…
x
Reference in New Issue
Block a user