~ibid-core/ibid/old-trunk-1.6

« back to all changes in this revision

Viewing changes to ibid/plugins/__init__.py

  • Committer: Tarmac
  • Author(s): Keegan Carruthers-Smith
  • Date: 2011-03-23 16:11:13 UTC
  • mfrom: (1015.6.8 named-groups-656201)
  • Revision ID: ibid-lp-lander@rivera.za.net-20110323161113-vzgpclmucy8fxyzi
Added named arguments to the match decorator.
Author: Keegan Carruthers-Smith
Merge Request: http://code.launchpad.net/~keegan-csmith/ibid/named-groups-656201/+merge/51159
Approved by: Stefano Rivera, Max Rabkin
Fixes LP: #656201

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (c) 2008-2010, Michael Gorven, Stefano Rivera
 
1
# Copyright (c) 2008-2011, Michael Gorven, Stefano Rivera, Keegan Carruthers-Smith
2
2
# Released under terms of the MIT/X/Expat Licence. See COPYING for details.
3
3
 
4
4
from copy import copy
23
23
            if not os.path.exists(os.path.join(x, *package + ['__init__.py']))]
24
24
 
25
25
import ibid
26
 
from ibid.compat import json
 
26
from ibid.compat import json, defaultdict
27
27
from ibid.utils import url_regex
28
28
 
29
29
__path__ = pluginPackagePaths(__name__) + __path__
142
142
                        event.message[method.message_version])
143
143
                if match is not None:
144
144
                    args = match.groups()
 
145
                    kwargs = match.groupdict()
 
146
                    if kwargs:
 
147
                        assert len(args) == len(kwargs), (
 
148
                            "Can't intermix named and positional arguments.")
 
149
                        # Convert the names from the %s__%d_ format to %s
 
150
                        args = {}
 
151
                        for name, value in kwargs.iteritems():
 
152
                            name = re.match(r'^(\S+?)(?:__\d+_)?$', name).group(1)
 
153
                            if args.get(name, None) is None:
 
154
                                args[name] = value
 
155
                            else:
 
156
                                assert value is None, (
 
157
                                    'named argument %s was matched more '
 
158
                                    'than once.' % name)
145
159
            if args is not None:
146
160
                if (not getattr(method, 'auth_required', False)
147
161
                        or auth_responses(event, self.permission)):
148
 
                    method(event, *args)
 
162
                    if isinstance(args, dict):
 
163
                        method(event, **args)
 
164
                    else:
 
165
                        method(event, *args)
149
166
                elif not getattr(method, 'auth_fallthrough', True):
150
167
                    event.processed = True
151
168
 
214
231
def _match_sub_selectors(regex):
215
232
    selector_patterns = {
216
233
        'alpha'   : r'[a-zA-Z]+',
217
 
        'any'     : r'.*',
 
234
        'any'     : r'.+',
218
235
        'chunk'   : r'\S+',
219
236
        'digits'  : r'\d+',
220
237
        'number'  : r'\d*\.?\d+',
224
241
 
225
242
    regex = regex.replace(' ', r'(?:\s+)')
226
243
 
227
 
    for pattern in re.finditer('{(%s)}' % '|'.join(selector_patterns.keys()),
228
 
                               regex):
229
 
        pattern = pattern.group(1)
230
 
        old = '{%s}' % pattern
231
 
        new = '(%s)' % selector_patterns[pattern]
232
 
        regex = regex.replace(old, new)
 
244
    name_count = defaultdict(int)
 
245
    def selector_to_re(match):
 
246
        name    = match.group(1)
 
247
        pattern = match.group(2)
 
248
 
 
249
        if name is None:
 
250
            return '(%s)' % selector_patterns[pattern]
 
251
 
 
252
        # Prevent conflicts when reusing a name
 
253
        name_count[name] += 1
 
254
        name = '%s__%d_' % (name, name_count[name])
 
255
 
 
256
        return '(?P<%s>%s)' % (name, selector_patterns[pattern])
 
257
 
 
258
    regex = re.sub(r'{(?:(\w+):)?(%s)}' % '|'.join(selector_patterns.keys()),
 
259
                   selector_to_re, regex)
233
260
 
234
261
    if not regex.startswith('^'):
235
262
        regex = '^' + regex