commit ad80a813decc7809c7f8d7c0693ac3216f6ac655
Author: Grzegorz Nosek <root@localdomain.pl>
Date:   Sat Feb 4 18:13:52 2012 +0100

    #17551

diff --git a/django/core/urlresolvers.py b/django/core/urlresolvers.py
index b634b56..4a8ec2d 100644
--- a/django/core/urlresolvers.py
+++ b/django/core/urlresolvers.py
@@ -245,7 +245,7 @@ class RegexURLResolver(LocaleRegexProvider):
                 p_pattern = p_pattern[1:]
             if isinstance(pattern, RegexURLResolver):
                 if pattern.namespace:
-                    namespaces[pattern.namespace] = (p_pattern, pattern)
+                    namespaces.setdefault(pattern.namespace, []).append((p_pattern, pattern))
                     if pattern.app_name:
                         apps.setdefault(pattern.app_name, []).append(pattern.namespace)
                 else:
@@ -256,8 +256,9 @@ class RegexURLResolver(LocaleRegexProvider):
                             for piece, p_args in parent:
                                 new_matches.extend([(piece + suffix, p_args + args) for (suffix, args) in matches])
                             lookups.appendlist(name, (new_matches, p_pattern + pat, dict(defaults, **pattern.default_kwargs)))
-                    for namespace, (prefix, sub_pattern) in pattern.namespace_dict.items():
-                        namespaces[namespace] = (p_pattern + prefix, sub_pattern)
+                    for namespace, sub_patterns in pattern.namespace_dict.items():
+                        for prefix, sub_pattern in sub_patterns:
+                            namespaces.setdefault(namespace, []).append((p_pattern + prefix, sub_pattern))
                     for app_name, namespace_list in pattern.app_dict.items():
                         apps.setdefault(app_name, []).extend(namespace_list)
             else:
@@ -459,9 +460,15 @@ def reverse(viewname, urlconf=None, args=None, kwargs=None, prefix=None, current
                 pass
 
             try:
-                extra, resolver = resolver.namespace_dict[ns]
+                resolvers = resolver.namespace_dict[ns]
+                if len(resolvers) > 1:
+                    ns_resolvers = [RegexURLResolver(extra, ns_resolver.url_patterns)
+                                    for extra, ns_resolver in resolvers]
+                    resolver = RegexURLResolver('', ns_resolvers)
+                else:
+                    extra, resolver = resolver.namespace_dict[ns][0]
+                    ns_pattern = ns_pattern + extra
                 resolved_path.append(ns)
-                ns_pattern = ns_pattern + extra
             except KeyError, key:
                 if resolved_path:
                     raise NoReverseMatch(
diff --git a/tests/regressiontests/urlpatterns_reverse/namespace_urls.py b/tests/regressiontests/urlpatterns_reverse/namespace_urls.py
index fa892a4..2d95a8f 100644
--- a/tests/regressiontests/urlpatterns_reverse/namespace_urls.py
+++ b/tests/regressiontests/urlpatterns_reverse/namespace_urls.py
@@ -6,16 +6,19 @@ from .views import view_class_instance
 
 
 class URLObject(object):
-    def __init__(self, app_name, namespace):
+    def __init__(self, app_name, namespace, _patterns=None):
+        if _patterns is None:
+            _patterns = patterns('',
+                url(r'^inner/$', 'empty_view', name='urlobject-view'),
+                url(r'^inner/(?P<arg1>\d+)/(?P<arg2>\d+)/$', 'empty_view', name='urlobject-view'),
+                url(r'^inner/\+\\\$\*/$', 'empty_view', name='urlobject-special-view'),
+            )
+        self.patterns = _patterns
         self.app_name = app_name
         self.namespace = namespace
 
     def urls(self):
-        return patterns('',
-            url(r'^inner/$', 'empty_view', name='urlobject-view'),
-            url(r'^inner/(?P<arg1>\d+)/(?P<arg2>\d+)/$', 'empty_view', name='urlobject-view'),
-            url(r'^inner/\+\\\$\*/$', 'empty_view', name='urlobject-special-view'),
-        ), self.app_name, self.namespace
+        return self.patterns, self.app_name, self.namespace
     urls = property(urls)
 
 testobj1 = URLObject('testapp', 'test-ns1')
@@ -25,6 +28,25 @@ default_testobj = URLObject('testapp', 'testapp')
 otherobj1 = URLObject('nodefault', 'other-ns1')
 otherobj2 = URLObject('nodefault', 'other-ns2')
 
+double_nested1 = URLObject('randomapp', 'nested',
+    patterns('', url(r'^f1/$', 'empty_view', name='view_f1'))
+)
+
+double_nested2 = URLObject('randomapp', 'nested',
+    patterns('', url(r'^f2/$', 'empty_view', name='view_f2'))
+)
+
+first_patterns = patterns('',
+    url(r'^$', 'empty_view', name='first'),
+    url(r'^nested1/', include(double_nested1.urls)),
+    url(r'^nested2/', include(double_nested2.urls)),
+)
+first = URLObject('first', 'inc-some', first_patterns)
+second_patterns = patterns('',
+    url(r'^$', 'empty_view', name='second'),
+)
+second = URLObject('second', 'inc-some', second_patterns)
+
 urlpatterns = patterns('regressiontests.urlpatterns_reverse.views',
     url(r'^normal/$', 'empty_view', name='normal-view'),
     url(r'^normal/(?P<arg1>\d+)/(?P<arg2>\d+)/$', 'empty_view', name='normal-view'),
@@ -55,4 +77,7 @@ urlpatterns = patterns('regressiontests.urlpatterns_reverse.views',
     (r'^ns-outer/(?P<outer>\d+)/', include('regressiontests.urlpatterns_reverse.included_namespace_urls', namespace='inc-outer')),
 
     (r'^\+\\\$\*/', include('regressiontests.urlpatterns_reverse.namespace_urls', namespace='special')),
+
+    url(r'^first/', include(first.urls)),
+    url(r'^second/', include(second.urls)),
 )
diff --git a/tests/regressiontests/urlpatterns_reverse/tests.py b/tests/regressiontests/urlpatterns_reverse/tests.py
index a1c9244..53759cd 100644
--- a/tests/regressiontests/urlpatterns_reverse/tests.py
+++ b/tests/regressiontests/urlpatterns_reverse/tests.py
@@ -392,6 +392,13 @@ class NamespaceTests(TestCase):
         self.assertEqual('/inc70/', reverse('inc-ns5:inner-nothing', args=['70']))
         self.assertEqual('/inc78/extra/foobar/', reverse('inc-ns5:inner-extra', args=['78','foobar']))
 
+    def test_namespaces_in_different_includes(self):
+        "Namespaces declared in different places: see #17551"
+        self.assertEqual('/first/', reverse('inc-some:first'))
+        self.assertEqual('/second/', reverse('inc-some:second'))
+        self.assertEqual('/first/nested1/f1/', reverse('inc-some:randomapp:view_f1'))
+        self.assertEqual('/first/nested2/f2/', reverse('inc-some:randomapp:view_f2'))
+
 class RequestURLconfTests(TestCase):
     def setUp(self):
         self.root_urlconf = settings.ROOT_URLCONF
