Merge branch 'master' into feat/new_config
Add StringIO and BytesIO to FakeIO. Fixes bytes/string problem in update()
This commit is contained in:
commit
392ee0c3c1
@ -19,33 +19,29 @@ The different use cases are :
|
||||
|
||||
import re
|
||||
|
||||
from ..repo import Repository, InvalidReference
|
||||
|
||||
from ..repo import Repository
|
||||
from ..uis import get_ui
|
||||
from .. import pretty
|
||||
from .. import color
|
||||
|
||||
|
||||
def parser(subparsers):
|
||||
parser = subparsers.add_parser('tag', help="add, remove and show tags")
|
||||
parser.add_argument('citekeyOrTag', nargs='?', default=None,
|
||||
help='citekey or tag.')
|
||||
parser.add_argument('tags', nargs='*', default = None,
|
||||
parser.add_argument('tags', nargs='?', default=None,
|
||||
help='If the previous argument was a citekey, then '
|
||||
'then a list of tags separated by a +.')
|
||||
'a list of tags separated by a +.')
|
||||
# TODO find a way to display clear help for multiple command semantics,
|
||||
# indistinguisable for argparse. (fabien, 201306)
|
||||
return parser
|
||||
|
||||
def _parse_tags(list_tags):
|
||||
"""Transform 'math-ai network -search' in ['+math', '-ai', '+network', '-search']"""
|
||||
tags = []
|
||||
for s in list_tags:
|
||||
tags += _parse_tag_seq(s)
|
||||
return tags
|
||||
|
||||
def _parse_tag_seq(s):
|
||||
"""Transform 'math-ai' in ['+math', '-ai']"""
|
||||
tags = []
|
||||
if s[0] == ':':
|
||||
s = '-' + s[1:]
|
||||
if s[0] not in ['+', '-']:
|
||||
s = '+' + s
|
||||
last = 0
|
||||
@ -62,6 +58,7 @@ def _parse_tag_seq(s):
|
||||
tags.append(s[last:])
|
||||
return tags
|
||||
|
||||
|
||||
def _tag_groups(tags):
|
||||
plus_tags, minus_tags = [], []
|
||||
for tag in tags:
|
||||
@ -79,7 +76,6 @@ def command(conf, args):
|
||||
citekeyOrTag = args.citekeyOrTag
|
||||
tags = args.tags
|
||||
|
||||
|
||||
rp = Repository(conf)
|
||||
|
||||
if citekeyOrTag is None:
|
||||
@ -87,20 +83,21 @@ def command(conf, args):
|
||||
else:
|
||||
if rp.databroker.exists(citekeyOrTag):
|
||||
p = rp.pull_paper(citekeyOrTag)
|
||||
if tags == []:
|
||||
if tags is None:
|
||||
ui.message(color.dye_out(' '.join(sorted(p.tags)), 'tag'))
|
||||
else:
|
||||
add_tags, remove_tags = _tag_groups(_parse_tags(tags))
|
||||
add_tags, remove_tags = _tag_groups(_parse_tag_seq(tags))
|
||||
for tag in add_tags:
|
||||
p.add_tag(tag)
|
||||
for tag in remove_tags:
|
||||
p.remove_tag(tag)
|
||||
rp.push_paper(p, overwrite=True)
|
||||
elif tags is not None:
|
||||
ui.error(ui.error('no entry found for citekey {}.'.format(citekeyOrTag)))
|
||||
ui.exit()
|
||||
else:
|
||||
# case where we want to find papers with specific tags
|
||||
all_tags = [citekeyOrTag]
|
||||
all_tags += tags
|
||||
included, excluded = _tag_groups(_parse_tags(all_tags))
|
||||
included, excluded = _tag_groups(_parse_tag_seq(citekeyOrTag))
|
||||
papers_list = []
|
||||
for p in rp.all_papers():
|
||||
if (p.tags.issuperset(included) and
|
||||
|
@ -27,11 +27,13 @@ def _get_encoding(conf):
|
||||
return enc or 'utf-8'
|
||||
return conf.get('terminal-encoding', enc or 'utf-8')
|
||||
|
||||
|
||||
def get_ui():
|
||||
if _ui is None:
|
||||
return PrintUI() # no editor support. (#FIXME?)
|
||||
return _ui
|
||||
|
||||
|
||||
def init_ui(conf):
|
||||
global _ui
|
||||
_ui = InputUI(conf)
|
||||
|
@ -1,6 +1,6 @@
|
||||
import shutil
|
||||
import StringIO
|
||||
|
||||
import io
|
||||
from . import config
|
||||
from . import uis
|
||||
from . import color
|
||||
@ -81,7 +81,7 @@ def update(conf, code_version, repo_version, path=None):
|
||||
# comparing potential changes
|
||||
with open(path, 'r') as f:
|
||||
old_conf_text = f.read()
|
||||
new_conf_text = StringIO.StringIO()
|
||||
new_conf_text = io.BytesIO()
|
||||
default_conf.write(outfile=new_conf_text)
|
||||
|
||||
if new_conf_text.getvalue() != old_conf_text:
|
||||
|
11
readme.md
11
readme.md
@ -52,6 +52,17 @@ This ensure that your reference file is always up-to-date; you can cite a paper
|
||||
|
||||
and then add `\cite{Loeb_2012}` in your manuscript. After running the bash script, the citation will correctly appear in your compiled pdf.
|
||||
|
||||
Customization
|
||||
-------------
|
||||
Pubs is designed to interact well with your command line tool chain. You can add custom commands to pubs by defining aliases in your config file. Here are a few examples.
|
||||
|
||||
[alias]
|
||||
print = open -w lp
|
||||
count = !pubs list -k | wc -l
|
||||
|
||||
For more advanced functionalities, pubs also support plugins. Actually *alias* is itself a plugin!
|
||||
|
||||
|
||||
Requirements
|
||||
------------
|
||||
- python >= 2.7 or >= 3.3
|
||||
|
@ -103,6 +103,8 @@ class FakeIO(object):
|
||||
fakefs_stringio = self.fake_open.Call(*args, **kwargs)
|
||||
return UnicodeStringIOWrapper(fakefs_stringio)
|
||||
|
||||
BytesIO = real_io.BytesIO
|
||||
StringIO = real_io.StringIO
|
||||
|
||||
def create_fake_fs(module_list):
|
||||
|
||||
|
@ -2,20 +2,25 @@
|
||||
import unittest
|
||||
|
||||
import dotdot
|
||||
from pubs.commands.tag_cmd import _parse_tags, _tag_groups
|
||||
from pubs.commands.tag_cmd import _parse_tag_seq, _tag_groups
|
||||
|
||||
class TestTag(unittest.TestCase):
|
||||
|
||||
def test_tag_parsing(self):
|
||||
def test_parse_tags(self):
|
||||
self.assertEqual(['+abc', '+def9'], _parse_tag_seq('abc+def9'))
|
||||
self.assertEqual(['+abc', '-def9'], _parse_tag_seq('abc-def9'))
|
||||
self.assertEqual(['-abc', '-def9'], _parse_tag_seq('-abc-def9'))
|
||||
self.assertEqual(['+abc', '-def9'], _parse_tag_seq('+abc-def9'))
|
||||
|
||||
self.assertEqual(['+abc', '+def9'], _parse_tags([ 'abc+def9']))
|
||||
self.assertEqual(['+abc', '-def9'], _parse_tags([ 'abc-def9']))
|
||||
self.assertEqual(['-abc', '-def9'], _parse_tags(['-abc-def9']))
|
||||
self.assertEqual(['+abc', '-def9'], _parse_tags(['+abc-def9']))
|
||||
|
||||
self.assertEqual(({'math', 'romance'}, {'war'}), _tag_groups(_parse_tags(['-war+math+romance'])))
|
||||
self.assertEqual(({'math', 'romance'}, {'war'}), _tag_groups(_parse_tags(['+math+romance-war'])))
|
||||
self.assertEqual(({'math', 'romance'}, {'war'}), _tag_groups(_parse_tags(['math+romance-war'])))
|
||||
def test_tag_groups(self):
|
||||
self.assertEqual(({'math', 'romance'}, {'war'}),
|
||||
_tag_groups(_parse_tag_seq('-war+math+romance')))
|
||||
self.assertEqual(({'math', 'romance'}, {'war'}),
|
||||
_tag_groups(_parse_tag_seq(':war+math+romance')))
|
||||
self.assertEqual(({'math', 'romance'}, {'war'}),
|
||||
_tag_groups(_parse_tag_seq('+math+romance-war')))
|
||||
self.assertEqual(({'math', 'romance'}, {'war'}),
|
||||
_tag_groups(_parse_tag_seq('math+romance-war')))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
@ -7,8 +7,7 @@ import os
|
||||
import dotdot
|
||||
import fake_env
|
||||
|
||||
from pubs import pubs_cmd
|
||||
from pubs import color, content, filebroker, uis, p3, endecoder
|
||||
from pubs import pubs_cmd, update, color, content, filebroker, uis, p3, endecoder
|
||||
from pubs.config import conf
|
||||
import configobj
|
||||
|
||||
@ -58,7 +57,7 @@ class CommandTestCase(unittest.TestCase):
|
||||
maxDiff = 1000000
|
||||
|
||||
def setUp(self):
|
||||
self.fs = fake_env.create_fake_fs([content, filebroker, conf, init_cmd, import_cmd, configobj])
|
||||
self.fs = fake_env.create_fake_fs([content, filebroker, conf, init_cmd, import_cmd, configobj, update])
|
||||
self.default_pubs_dir = self.fs['os'].path.expanduser('~/.pubs')
|
||||
|
||||
def execute_cmds(self, cmds, capture_output=CAPTURE_OUTPUT):
|
||||
@ -118,7 +117,7 @@ class DataCommandTestCase(CommandTestCase):
|
||||
"""
|
||||
|
||||
def setUp(self):
|
||||
CommandTestCase.setUp(self)
|
||||
super(DataCommandTestCase, self).setUp()
|
||||
fake_env.copy_dir(self.fs, os.path.join(os.path.dirname(__file__), 'data'), 'data')
|
||||
|
||||
|
||||
@ -251,6 +250,76 @@ class TestList(DataCommandTestCase):
|
||||
self.assertEqual(0 + 1, len(outs[-1].split('\n')))
|
||||
|
||||
|
||||
class TestTag(DataCommandTestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(TestTag, self).setUp()
|
||||
init = ['pubs init',
|
||||
'pubs add data/pagerank.bib',
|
||||
'pubs add -k Turing1950 data/turing1950.bib',
|
||||
]
|
||||
self.execute_cmds(init)
|
||||
|
||||
def test_add_tag(self):
|
||||
cmds = ['pubs tag Page99 search',
|
||||
'pubs tag Turing1950 ai',
|
||||
'pubs list',
|
||||
]
|
||||
correct = ['',
|
||||
'',
|
||||
'[Page99] Page, Lawrence et al. "The PageRank Citation Ranking: Bringing Order to the Web." (1999) | search\n' +
|
||||
'[Turing1950] Turing, Alan M "Computing machinery and intelligence" Mind (1950) | ai\n',
|
||||
]
|
||||
out = self.execute_cmds(cmds)
|
||||
self.assertEqual(out, correct)
|
||||
|
||||
def test_add_tags(self):
|
||||
"""Adds several tags at once.
|
||||
Also checks that tags printed in alphabetic order.
|
||||
"""
|
||||
cmds = ['pubs tag Page99 search+network',
|
||||
'pubs list',
|
||||
]
|
||||
correct = ['',
|
||||
'[Page99] Page, Lawrence et al. "The PageRank Citation Ranking: Bringing Order to the Web." (1999) | network,search\n' +
|
||||
'[Turing1950] Turing, Alan M "Computing machinery and intelligence" Mind (1950) \n',
|
||||
]
|
||||
out = self.execute_cmds(cmds)
|
||||
self.assertEqual(out, correct)
|
||||
|
||||
def test_remove_tag(self):
|
||||
cmds = ['pubs tag Page99 search+network',
|
||||
'pubs tag Page99 :network',
|
||||
'pubs list',
|
||||
]
|
||||
correct = ['',
|
||||
'',
|
||||
'[Page99] Page, Lawrence et al. "The PageRank Citation Ranking: Bringing Order to the Web." (1999) | search\n' +
|
||||
'[Turing1950] Turing, Alan M "Computing machinery and intelligence" Mind (1950) \n',
|
||||
]
|
||||
out = self.execute_cmds(cmds)
|
||||
self.assertEqual(out, correct)
|
||||
|
||||
def test_add_remove_tag(self):
|
||||
cmds = ['pubs tag Page99 a',
|
||||
'pubs tag Page99 b-a',
|
||||
'pubs list',
|
||||
]
|
||||
correct = ['',
|
||||
'',
|
||||
'[Page99] Page, Lawrence et al. "The PageRank Citation Ranking: Bringing Order to the Web." (1999) | b\n' +
|
||||
'[Turing1950] Turing, Alan M "Computing machinery and intelligence" Mind (1950) \n',
|
||||
]
|
||||
out = self.execute_cmds(cmds)
|
||||
self.assertEqual(out, correct)
|
||||
|
||||
def test_wrong_citekey(self):
|
||||
cmds = ['pubs tag Page999 a',
|
||||
]
|
||||
with self.assertRaises(SystemExit):
|
||||
self.execute_cmds(cmds)
|
||||
|
||||
|
||||
class TestUsecase(DataCommandTestCase):
|
||||
|
||||
def test_first(self):
|
||||
|
Loading…
x
Reference in New Issue
Block a user