diff --git a/changelog.md b/changelog.md index 1e1f3e0..73db144 100644 --- a/changelog.md +++ b/changelog.md @@ -7,6 +7,8 @@ ### Implemented enhancements +- Add `citekey` filter to `query` ([#193](https://github.com/pubs/pubs/pull/193) by [Shane Stone](https://github.com/shanewstone)) + ### Fixed bugs diff --git a/pubs/query.py b/pubs/query.py index 9e65eb1..7bcb656 100644 --- a/pubs/query.py +++ b/pubs/query.py @@ -6,7 +6,8 @@ from . import bibstruct QUERY_HELP = ('Paper query ("author:Einstein", "title:learning",' - '"year:2000", "year:2000-2010", or "tags:math")') + ' "year:2000", "year:2000-2010", "citekey:Einstein_1935",' + ' or "tags:math")') FIELD_ALIASES = { @@ -15,6 +16,7 @@ FIELD_ALIASES = { 't': 'title', 'tags': 'tag', 'y': 'year', + 'key': 'citekey', } @@ -78,6 +80,12 @@ class AuthorFilter(QueryFilter): for author in paper.bibdata['author']]) +class CitekeyFilter(QueryFilter): + + def __call__(self, paper): + return self._is_query_in(paper.citekey) + + class TagFilter(QueryFilter): def __call__(self, paper): @@ -137,6 +145,9 @@ def _query_block_to_filter(query_block, case_sensitive=None, strict=False): field, value = _get_field_value(query_block) if field == 'tag': return TagFilter(value, case_sensitive=case_sensitive, strict=strict) + elif field == 'citekey': + return CitekeyFilter(value, case_sensitive=case_sensitive, + strict=strict) elif field == 'author': return AuthorFilter(value, case_sensitive=case_sensitive, strict=strict) diff --git a/readme.md b/readme.md index dd2d902..a2c8c2c 100644 --- a/readme.md +++ b/readme.md @@ -142,3 +142,4 @@ You can access the self-documented configuration by using `pubs conf`, and all t - [Dennis Wilson](https://github.com/d9w) - [Bill Flynn](https://github.com/wflynny) - [ksunden](https://github.com/ksunden) +- [Shane Stone](https://github.com/shanewstone) diff --git a/tests/test_queries.py b/tests/test_queries.py index d8cfa86..207c4fc 100644 --- a/tests/test_queries.py +++ b/tests/test_queries.py @@ -4,9 +4,9 @@ from __future__ import unicode_literals import unittest import dotdot -from pubs.query import (AuthorFilter, FieldFilter, YearFilter, - _query_block_to_filter, get_paper_filter, - InvalidQuery) +from pubs.query import (AuthorFilter, CitekeyFilter, FieldFilter, + YearFilter, _query_block_to_filter, + get_paper_filter, InvalidQuery) from pubs.paper import Paper @@ -43,6 +43,49 @@ class TestAuthorFilter(unittest.TestCase): self.assertFalse(AuthorFilter('lawrence')(page_paper)) +class TestCitekeyFilter(unittest.TestCase): + + def test_fails_if_no_citekey(self): + no_citekey = doe_paper.deepcopy() + no_citekey.citekey = '' + self.assertFalse(CitekeyFilter('whatever')(no_citekey)) + + def test_match_case(self): + self.assertTrue(CitekeyFilter('doe201')(doe_paper)) + self.assertTrue(CitekeyFilter('doe201', case_sensitive=False)(doe_paper)) + self.assertTrue(CitekeyFilter('Doe201')(doe_paper)) + + def test_do_not_match_case(self): + self.assertFalse(CitekeyFilter('dOe201')(doe_paper)) + self.assertFalse(CitekeyFilter('dOe201', case_sensitive=True)(doe_paper)) + self.assertFalse(CitekeyFilter('doe201', case_sensitive=True)(doe_paper)) + self.assertTrue(CitekeyFilter('dOe201', case_sensitive=False)(doe_paper)) + + def test_latex_enc(self): + latexenc_paper = doe_paper.deepcopy() + latexenc_paper.citekey = "{G}r{\\\"u}n2013" + self.assertTrue(CitekeyFilter('GrĂ¼n')(latexenc_paper)) + self.assertTrue(CitekeyFilter('Gr{\\\"u}n')(latexenc_paper)) + + def test_normalize_unicode(self): + latexenc_paper = doe_paper.deepcopy() + latexenc_paper.citekey = "Jalape\u00f1o2013" + self.assertTrue(CitekeyFilter("Jalapen\u0303o")(latexenc_paper)) + + def test_strict(self): + latexenc_paper = doe_paper.deepcopy() + latexenc_paper.citekey = "Jalape\u00f1o2013" + self.assertFalse(CitekeyFilter("Jalapen\u0303o", strict=True)(latexenc_paper)) + latexenc_paper.citekey = "{G}ros2013" + self.assertFalse(CitekeyFilter("Gros", strict=True)(latexenc_paper)) + + def test_strict_implies_case(self): + latexenc_paper = doe_paper.deepcopy() + latexenc_paper.citekey = "Gros2013" + self.assertFalse( + CitekeyFilter("gros", case_sensitive=False, strict=True)(latexenc_paper)) + + class TestCheckTag(unittest.TestCase): pass diff --git a/tests/test_usecase.py b/tests/test_usecase.py index c83a626..48b1e81 100644 --- a/tests/test_usecase.py +++ b/tests/test_usecase.py @@ -505,6 +505,18 @@ class TestList(DataCommandTestCase): outs = self.execute_cmds(cmds) self.assertEqual(1 + 1, len(outs[-1].split('\n'))) + def test_list_with_citekey_query(self): + cmds = ['pubs init', + 'pubs import data/', + 'pubs list citekey:Page99', + 'pubs list key:eiNstein_1935', + 'pubs list --ignore-case key:eiNstein_1935', + ] + outs = self.execute_cmds(cmds) + self.assertEqual(1, len(outs[2].splitlines())) + self.assertEqual(0, len(outs[3].splitlines())) + self.assertEqual(1, len(outs[4].splitlines())) + class TestTag(DataCommandTestCase):