Introduce DynamicURLResolver, and use it for extensions.

Review Request #3577 — Created Nov. 28, 2012 and submitted — Latest diff uploaded

Information

Djblets
master

Reviewers

Introduce DynamicURLResolver, and use it for extensions.

Getting dynamic URL patterns working in Django is tricky, since Django
assumes URL patterns will be set once and will never change.

DynamicURLResolver is the answer to that. It takes the place of a url()
in a urlpatterns list, and provides add_patterns() and
remove_patterns() functions that callers can use to modify the URL
patterns list.

To do this, it manipulates its own list of URL patterns, and the caching
of every URL resolver between the root resolver and itself. Whenever the
list is manipulated, all resolvers in that chain have their caches
emptied, causing the next lookup to traverse up to the
DynamicURLResolver. This means there's a little bit of overhead every
time the list is manipulated, but it's not terrible, and won't affect
resolvers outside that chain.

This is being used for URLHooks, WebAPIResources on extensions, and
admin URLs for extensions.
Tested a repro case we found where API resources for models in extensions
weren't able to reverse a URL from inside that extension's API tree properly.
This now works fine.

Added unit tests, which pass (and failed before).

More work will need to be done to ensure URLHooks work properly in all cases,
and unit tests should be written there as well.