Skip to content

Commit

Permalink
Improve the filter configuration
Browse files Browse the repository at this point in the history
Move enabled filter list to the config file, add support
for custom filter types, updated the configuration.
  • Loading branch information
Justus Winter committed Oct 15, 2011
1 parent f19a015 commit c3775e8
Show file tree
Hide file tree
Showing 4 changed files with 104 additions and 14 deletions.
29 changes: 24 additions & 5 deletions README
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ And I'd like to suggest to install afew as your unprivileged user.
If you do, make sure ~/.local/bin is in your path.

$ python setup.py install --prefix=~/.local
$ mkdir -p ~/.local/share/afew/categories
$ mkdir -p ~/.config/afew ~/.local/share/afew/categories


Configuration
Expand All @@ -56,6 +56,18 @@ Make sure that ~/.notmuch-config reads:
tags=new
~~~ snip ~~~

Put a list of filters into ~/.config/afew/config:
~~~ snip ~~~
# This is the default filter chain
[SpamFilter]
[ClassifyingFilter]
[KillThreadsFilter]
[ListMailsFilter]
[ArchiveSentMailsFilter]
[InboxFilter]
~~~ snip ~~~



Commandline help
================
Expand Down Expand Up @@ -94,7 +106,8 @@ Options:
path to the notmuch configuration file [default:
$NOTMUCH_CONFIG or ~/.notmuch-config]
-e ENABLE_FILTERS, --enable-filters=ENABLE_FILTERS
filter classes to use, separated by ',' [default: all]
filter classes to use, separated by ',' [default:
filters specified in afew's config]
-d, --dry-run don't change the db [default: False]
-R REFERENCE_SET_SIZE, --reference-set-size=REFERENCE_SET_SIZE
size of the reference set [default: 1000]
Expand Down Expand Up @@ -127,11 +140,17 @@ postsynchook = ionice -c 3 chrt --idle 0 /bin/sh -c "notmuch new && afew --tag -

Tag filters
-----------
Tag filters are plugin-like modules that encapsulate tagging functionality. There is a filter that handles the archiving of mails you sent, one that handles spam, one for killed threads, one for mailing list magic...
Tag filters are plugin-like modules that encapsulate tagging
functionality. There is a filter that handles the archiving of mails
you sent, one that handles spam, one for killed threads, one for
mailing list magic...

By default, all filters are enabled and when you run afew with the --tag option, you get all of the goodness afew has to offer. If you want to change that behaviour, you can override the default by specifying what filters should be run with the --enable-filters option.
The tag filter concept allows you to easily extend afew's tagging
abilities by writing your own filters. Take a look at the default
configuration file (afew/defaults/afew.config) for a list of
available filters and how to enable filters and create customize
filter types.

The tag filter concept allows you to easily extend afew's tagging abilities by writing your own filters.


The real deal
Expand Down
40 changes: 40 additions & 0 deletions afew/Settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,12 @@
#

import os
import re
import functools
import ConfigParser

from .Filter import all_filters, register_filter

notmuch_config = ConfigParser.RawConfigParser()

def read_notmuch_config(path = None):
Expand All @@ -32,3 +36,39 @@ def read_notmuch_config(path = None):
settings.read(os.path.join(os.environ.get('XDG_CONFIG_HOME',
os.path.expanduser('~/.config')),
'afew', 'config'))

def make_factory(klass, kwargs):
@functools.wraps(klass)
def factory(db_path):
return klass(db_path, **kwargs)
return factory

section_re = re.compile(r'''^(?P<name>[a-z_][a-z0-9_]*)(\((?P<parent_class>[a-z_][a-z0-9_]*)\)|\.(?P<index>\d+))?$''', re.I)
def get_filter_chain():
filter_chain = []

for section in settings.sections():
if section == 'global':
continue

match = section_re.match(section)
if not match:
raise SyntaxError('Malformed section title %r.' % section)

if match.group('parent_class'):
try:
parent_class = all_filters[match.group('parent_class')]
except KeyError as e:
raise NameError('Parent class %r not found in filter type definition %r.' % (match.group('parent_class'), section))

new_type = type(match.group('name'), (parent_class, ), dict(settings.items(section)))
register_filter(new_type)
else:
try:
klass = all_filters[match.group('name')]
except KeyError as e:
raise NameError('Filter type %r not found.' % match.group('name'))

filter_chain.append(make_factory(klass, dict(settings.items(section))))

return filter_chain
28 changes: 28 additions & 0 deletions afew/defaults/afew.config
Original file line number Diff line number Diff line change
@@ -1 +1,29 @@
# global configuration
[global]

# This is the default filter chain
#[SpamFilter]
#[ClassifyingFilter]
#[KillThreadsFilter]
#[ListMailsFilter]
#[ArchiveSentMailsFilter]
#[InboxFilter]

# Let's say you like the SpamFilter, but it is way too polite

# 1. create an filter object and customize it
#[SpamFilter.0] # note the index
#message = meh

# 2. create a new type and...
#[ShitFilter(SpamFilter)]
#message = I hatez teh spam!

# create an object or two...
#[ShitFilter.0]
#[ShitFilter.1]
#message = Me hatez it too.

# 3. drop a custom filter type in ~/.config/afew/
# TODO: implement this
# and create objects of this kind
21 changes: 12 additions & 9 deletions bin/afew
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import optparse

from afew.main import main
from afew.Filter import all_filters
from afew.Settings import read_notmuch_config
from afew.Settings import read_notmuch_config, get_filter_chain

option_parser = optparse.OptionParser(
usage = '%prog [options] [--] [query]'
Expand Down Expand Up @@ -89,8 +89,7 @@ options_group.add_option(
)
options_group.add_option(
'-e', '--enable-filters',
default = 'SpamFilter,ClassifyingFilter,KillThreadsFilter,ListMailsFilter,ArchiveSentMailsFilter,InboxFilter',
help = "filter classes to use, separated by ',' [default: all]"
help = "filter classes to use, separated by ',' [default: filters specified in afew's config]"
)
options_group.add_option(
'-d', '--dry-run', default = False, action = 'store_true',
Expand Down Expand Up @@ -142,14 +141,18 @@ elif options.update or options.update_reference:
else:
sys.exit('Weird... please file a bug containing your command line.')

options.enable_filters = options.enable_filters.split(',')
configured_filter_chain = get_filter_chain()
if options.enable_filters:
options.enable_filters = options.enable_filters.split(',')

all_filters_set = set(all_filters.keys())
enabled_filters_set = set(options.enable_filters)
if not all_filters_set.issuperset(enabled_filters_set):
sys.exit('Unknown filter(s) selected: %s' % (' '.join(enabled_filters_set.difference(all_filters_set))))
all_filters_set = set(all_filters.keys())
enabled_filters_set = set(options.enable_filters)
if not all_filters_set.issuperset(enabled_filters_set):
sys.exit('Unknown filter(s) selected: %s' % (' '.join(enabled_filters_set.difference(all_filters_set))))

options.enable_filters = [all_filters[filter_name] for filter_name in options.enable_filters]
options.enable_filters = [all_filters[filter_name] for filter_name in options.enable_filters]
else:
options.enable_filters = configured_filter_chain

loglevel = {
0: logging.WARNING,
Expand Down

0 comments on commit c3775e8

Please sign in to comment.