From e9501a0b54d2067acafcc4ff614c7f3dd824d6d4 Mon Sep 17 00:00:00 2001 From: Jacob Bom Date: Tue, 28 Mar 2017 17:33:17 +0200 Subject: [PATCH 1/3] Add InvertedFilter and use it from __invert__ --- telegram/ext/filters.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/telegram/ext/filters.py b/telegram/ext/filters.py index c16db36cf1b..bc77397ebf8 100644 --- a/telegram/ext/filters.py +++ b/telegram/ext/filters.py @@ -51,10 +51,22 @@ def __and__(self, other): def __or__(self, other): return MergedFilter(self, or_filter=other) + def __invert__(self): + return InvertedFilter(self) + def filter(self, message): raise NotImplementedError +class InvertedFilter(BaseFilter): + + def __init__(self, f): + self.f = f + + def filter(self, message): + return not self.f(message) + + class MergedFilter(BaseFilter): """Represents a filter consisting of two other filters. From e377bd7535b5998dd7338546a939b67a910fd6f4 Mon Sep 17 00:00:00 2001 From: Jacob Bom Date: Tue, 28 Mar 2017 17:37:28 +0200 Subject: [PATCH 2/3] Add docstrings and __str__ for inverting filters --- telegram/ext/filters.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/telegram/ext/filters.py b/telegram/ext/filters.py index bc77397ebf8..4b3cbd48244 100644 --- a/telegram/ext/filters.py +++ b/telegram/ext/filters.py @@ -32,9 +32,14 @@ class BaseFilter(object): >>> (Filters.audio | Filters.video) + Not: + + >>> ~ Filters.command + Also works with more than two filters: >>> (Filters.text & (Filters.entity(URL) | Filters.entity(TEXT_LINK))) + >>> Filters.text & (~ Filters.forwarded) If you want to create your own filters create a class inheriting from this class and implement a `filter` method that returns a boolean: `True` if the message should be handled, `False` @@ -59,6 +64,11 @@ def filter(self, message): class InvertedFilter(BaseFilter): + """Represents a filter that has been inverted. + + Args: + f: The filter to invert + """ def __init__(self, f): self.f = f @@ -66,6 +76,11 @@ def __init__(self, f): def filter(self, message): return not self.f(message) + def __str__(self): + return "".format(self.f) + + __repr__ = __str__ + class MergedFilter(BaseFilter): """Represents a filter consisting of two other filters. From 607dd2b7283706259a6da3c50fbae76a05c5832d Mon Sep 17 00:00:00 2001 From: Jacob Bom Date: Tue, 28 Mar 2017 17:52:38 +0200 Subject: [PATCH 3/3] Tests for inverted filters --- tests/test_filters.py | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/tests/test_filters.py b/tests/test_filters.py index 814a85ae669..ec38c4ec2ed 100644 --- a/tests/test_filters.py +++ b/tests/test_filters.py @@ -226,6 +226,32 @@ def test_and_or_filters(self): r" or " r">>") + def test_inverted_filters(self): + self.message.text = '/test' + self.assertTrue((Filters.command)(self.message)) + self.assertFalse((~Filters.command)(self.message)) + self.message.text = 'test' + self.assertFalse((Filters.command)(self.message)) + self.assertTrue((~Filters.command)(self.message)) + + def test_inverted_and_filters(self): + self.message.text = '/test' + self.message.forward_date = 1 + self.assertTrue((Filters.forwarded & Filters.command)(self.message)) + self.assertFalse((~Filters.forwarded & Filters.command)(self.message)) + self.assertFalse((Filters.forwarded & ~Filters.command)(self.message)) + self.assertFalse((~(Filters.forwarded & Filters.command))(self.message)) + self.message.forward_date = None + self.assertFalse((Filters.forwarded & Filters.command)(self.message)) + self.assertTrue((~Filters.forwarded & Filters.command)(self.message)) + self.assertFalse((Filters.forwarded & ~Filters.command)(self.message)) + self.assertTrue((~(Filters.forwarded & Filters.command))(self.message)) + self.message.text = 'test' + self.assertFalse((Filters.forwarded & Filters.command)(self.message)) + self.assertFalse((~Filters.forwarded & Filters.command)(self.message)) + self.assertFalse((Filters.forwarded & ~Filters.command)(self.message)) + self.assertTrue((~(Filters.forwarded & Filters.command))(self.message)) + def test_faulty_custom_filter(self): class _CustomFilter(BaseFilter):