from django.core.urlresolvers import RegexURLResolver

def extend(root_resolver, extra_parm_dct, require_matches=True):
    '''
        Extend a resolver to have extra parameters
        passed in by a per-name basis, and also
        validate that names exist so that child 
        application can essentially validate the API
        of the app whose urls it is including
        
        root_resolver: should be url w/include (see example below)
        extra_parm_dct:
            keys: should be names defined for reverse calls
            values: dictionaries of extra parameters to be sent to views
        require_matches: if True, raise exception if some names are not found
        
        Limitations: 
            1) only tested on python 2.5, django 1.1
            2) modifies resolvers directly, does not clone them

        Example usage:
            extend(url(r'', include('member.urls')),
                    {
                        'make_payment':
                            {'make_payment_form': QuickEnrollPaymentForm}, 
                        'home_page': {}, # simply must exist
                    }
                ),
            
    '''
    if not isinstance(root_resolver, RegexURLResolver):
        raise TypeError('Expected RegexURLResolver argument')
    names_to_extend = set(extra_parm_dct.keys())

    def _extend(resolver):
        for pattern in resolver.url_patterns:
            if isinstance(pattern, RegexURLResolver):
                _extend(pattern)
            else:
                name = pattern.name
                if name in extra_parm_dct:
                    extra_args = extra_parm_dct[name]
                    pattern.default_args.update(extra_args)
                    names_to_extend.discard(name)
    
    _extend(root_resolver)
    if require_matches and len(names_to_extend) > 0:
        raise Exception('The following names do not exist in extended urlconf: %s' % names_to_extend)
    return root_resolver