Commit e71d9adf authored by Bram Schoenmakers's avatar Bram Schoenmakers

Introduce ordinal tag filter, filter ordinal tag values with a comparator.

It's possible to use <, <=, =, > and >= to select todo items based
on a integer or date tag.
parent fd7bf73b
...@@ -183,3 +183,104 @@ class FilterTest(unittest.TestCase): ...@@ -183,3 +183,104 @@ class FilterTest(unittest.TestCase):
self.assertEquals(todolist_to_string(filtered_todos), \ self.assertEquals(todolist_to_string(filtered_todos), \
todolist_to_string(reference)) todolist_to_string(reference))
def test_filter19(self):
todos = load_file('data/FilterTest3.txt')
otf = Filter.OrdinalTagFilter('due:<2014-11-10')
filtered_todos = otf.filter(todos)
reference = load_file('data/FilterTest6-result.txt')
self.assertEquals(todolist_to_string(filtered_todos), \
todolist_to_string(reference))
def test_filter20(self):
todos = load_file('data/FilterTest3.txt')
otf = Filter.OrdinalTagFilter('due:=2014-11-10')
filtered_todos = otf.filter(todos)
reference = load_file('data/FilterTest6-result.txt')
self.assertEquals(todolist_to_string(filtered_todos), "")
def test_filter21(self):
todos = load_file('data/FilterTest3.txt')
otf = Filter.OrdinalTagFilter('due:=2014-11-10')
filtered_todos = otf.filter(todos)
self.assertEquals(todolist_to_string(filtered_todos), "")
def test_filter22(self):
todos = load_file('data/FilterTest3.txt')
otf = Filter.OrdinalTagFilter('due:=2014-11-99')
filtered_todos = otf.filter(todos)
self.assertEquals(todolist_to_string(filtered_todos), "")
def test_filter23(self):
todos = load_file('data/FilterTest3.txt')
otf = Filter.OrdinalTagFilter('due:=garbage')
filtered_todos = otf.filter(todos)
self.assertEquals(todolist_to_string(filtered_todos), "")
def test_filter24(self):
todos = load_file('data/FilterTest3.txt')
otf = Filter.OrdinalTagFilter('value:<10')
filtered_todos = otf.filter(todos)
reference = load_file('data/FilterTest8-result.txt')
self.assertEquals(todolist_to_string(filtered_todos),
todolist_to_string(reference))
def test_filter25(self):
todos = load_file('data/FilterTest3.txt')
otf = Filter.OrdinalTagFilter('value:<=16')
filtered_todos = otf.filter(todos)
reference = load_file('data/FilterTest9-result.txt')
self.assertEquals(todolist_to_string(filtered_todos),
todolist_to_string(reference))
def test_filter26(self):
todos = load_file('data/FilterTest3.txt')
otf = Filter.OrdinalTagFilter('value:<16')
filtered_todos = otf.filter(todos)
reference = load_file('data/FilterTest10-result.txt')
self.assertEquals(todolist_to_string(filtered_todos),
todolist_to_string(reference))
def test_filter27(self):
todos = load_file('data/FilterTest3.txt')
otf = Filter.OrdinalTagFilter('value:<16a')
filtered_todos = otf.filter(todos)
self.assertEquals(todolist_to_string(filtered_todos), "")
def test_filter28(self):
todos = load_file('data/FilterTest3.txt')
otf = Filter.OrdinalTagFilter('value:>8')
filtered_todos = otf.filter(todos)
reference = load_file('data/FilterTest11-result.txt')
self.assertEquals(todolist_to_string(filtered_todos),
todolist_to_string(reference))
def test_filter29(self):
todos = load_file('data/FilterTest3.txt')
otf = Filter.OrdinalTagFilter('value:>=8')
filtered_todos = otf.filter(todos)
reference = load_file('data/FilterTest12-result.txt')
self.assertEquals(todolist_to_string(filtered_todos),
todolist_to_string(reference))
Tag with some other value:16
Tag with some value:8
Tag with some other value:16
Tag with past due date due:2014-01-01
Tag with future due date due:2030-01-01
Tag with some value:8
Tag with some other value:16
Tag with past due date due:2014-01-01
Tag with future due date due:2030-01-01
Tag with some value:8
Tag with some other value:16
...@@ -14,6 +14,13 @@ ...@@ -14,6 +14,13 @@
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
from datetime import date
import re
from Config import config
from RelativeDate import relative_date_to_date
from Utils import date_string_to_date
class Filter(object): class Filter(object):
def filter(self, p_todos): def filter(self, p_todos):
""" """
...@@ -140,3 +147,43 @@ class LimitFilter(Filter): ...@@ -140,3 +147,43 @@ class LimitFilter(Filter):
def filter(self, p_todos): def filter(self, p_todos):
return p_todos[:self.limit] if self.limit >= 0 else p_todos return p_todos[:self.limit] if self.limit >= 0 else p_todos
ORDINAL_TAG_MATCH = r"(?P<key>[^:]*):(?P<operator><=?|=|>=?)?(?P<value>\S*)"
class OrdinalTagFilter(Filter):
def __init__(self, p_expression):
match = re.match(ORDINAL_TAG_MATCH, p_expression)
if match:
self.key = match.group('key')
self.operator = match.group('operator') or '='
self.value = match.group('value')
def match(self, p_todo):
if not self.key or not p_todo.has_tag(self.key):
return False
if self.key == config().tag_due() or self.key == config().tag_start():
operand1 = date_string_to_date(p_todo.tag_value(self.key))
operand2 = relative_date_to_date(self.value)
if not operand2:
operand2 = date_string_to_date(self.value)
else:
try:
operand1 = int(p_todo.tag_value(self.key))
operand2 = int(self.value)
except ValueError:
return False
if self.operator == '<':
return operand1 < operand2
elif self.operator == '<=':
return operand1 <= operand2
elif self.operator == '=':
return operand1 == operand2
elif self.operator == '>=':
return operand1 >= operand2
elif self.operator == '>':
return operand1 > operand2
return False
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment