Skip to content

Refactor Filters #2178

Closed
Closed
@Bibo-Joshi

Description

@Bibo-Joshi

Currently filters check updates via the __call__ method. When switching from function-based filters to class-based filters, this was mainly done to maintain backwards compatibility with filter(update). However with some of the new filters functionalities, this leads to ugly workarounds like

class _Text(MessageFilter):
name = 'Filters.text'
class _TextStrings(MessageFilter):
def __init__(self, strings: List[str]):
self.strings = strings
self.name = 'Filters.text({})'.format(strings)
def filter(self, message: Message) -> bool:
if message.text:
return message.text in self.strings
return False
def __call__( # type: ignore[override]
self, update: Union[Update, List[str]]
) -> Union[bool, '_TextStrings']:
if isinstance(update, Update):
return self.filter(update.effective_message)
return self._TextStrings(update)
def filter(self, message: Message) -> bool:
return bool(message.text)

I therefore propose to refactor to something along the lines of

class BaseFilter:
    def __call__(self, *args, **kwargs):
        return self.__class__(*args, **kwargs)

    @abstractmethod
    def check_update(update/method):
        ...

This matches the Handler.check_update interface and allows for filters having a custom __init__, wich can still be called through instances of those filters.

However, this is somewhat breaking: While BaseFilter.__call__ is undocumented, people might still have Filters.existing_filter(update) somewhere within their custom filters. So maybe this is better suited for a major release.

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions