Code

Ticket #14087: namespace_package_pth.2.diff

File namespace_package_pth.2.diff, 15.6 KB (added by bhuztez, 2 years ago)

update patch for revision 17517

Line 
1diff --git a/django/core/management/__init__.py b/django/core/management/__init__.py
2index 8e83304..f31bcc5 100644
3--- a/django/core/management/__init__.py
4+++ b/django/core/management/__init__.py
5@@ -39,26 +39,56 @@ def find_management_module(app_name):
6     """
7     parts = app_name.split('.')
8     parts.append('management')
9-    parts.reverse()
10-    part = parts.pop()
11-    path = None
12-
13-    # When using manage.py, the project module is added to the path,
14-    # loaded, then removed from the path. This means that
15-    # testproject.testapp.models can be loaded in future, even if
16-    # testproject isn't in the path. When looking for the management
17-    # module, we need look for the case where the project name is part
18-    # of the app_name but the project directory itself isn't on the path.
19-    try:
20-        f, path, descr = imp.find_module(part,path)
21-    except ImportError,e:
22-        if os.path.basename(os.getcwd()) != part:
23-            raise e
24+
25+    for i in range(len(parts), 0, -1):
26+        try:
27+            path = sys.modules['.'.join(parts[:i])].__path__
28+        except AttributeError:
29+            raise ImportError("No package named %s" % parts[i-1])
30+        except KeyError:
31+            continue
32+
33+        parts = parts[i:]
34+        parts.reverse()
35+        break
36+    else:
37+        parts.reverse()
38+        part = parts.pop()
39+        path = sys.path
40+
41+        # When using manage.py, the project module is added to the path,
42+        # loaded, then removed from the path. This means that
43+        # testproject.testapp.models can be loaded in future, even if
44+        # testproject isn't in the path. When looking for the management
45+        # module, we need look for the case where the project name is part
46+        # of the app_name but the project directory itself isn't on the path.
47+        try:
48+            next_path = []
49+            for p in path:
50+                try:
51+                    next_path.append(imp.find_module(part, [p])[1])
52+                except ImportError:
53+                    pass
54+            if not next_path:
55+                raise ImportError("No module named %s" % part)
56+            path = next_path
57+        except ImportError,e:
58+            if os.path.basename(os.getcwd()) != part:
59+                raise e
60 
61     while parts:
62         part = parts.pop()
63-        f, path, descr = imp.find_module(part, path and [path] or None)
64-    return path
65+        next_path = []
66+        for p in path:
67+            try:
68+                next_path.append(imp.find_module(part, [p])[1])
69+            except ImportError:
70+                pass
71+        if not next_path:
72+            raise ImportError("No module named %s" % part)
73+        path = next_path
74+
75+    return path[0]
76 
77 def load_command_class(app_name, name):
78     """
79diff --git a/tests/regressiontests/admin_scripts/lib1/nons_app/__init__.py b/tests/regressiontests/admin_scripts/lib1/nons_app/__init__.py
80new file mode 100644
81index 0000000..e69de29
82diff --git a/tests/regressiontests/admin_scripts/lib1/nons_app/management/__init__.py b/tests/regressiontests/admin_scripts/lib1/nons_app/management/__init__.py
83new file mode 100644
84index 0000000..e69de29
85diff --git a/tests/regressiontests/admin_scripts/lib1/nons_app/management/commands/__init__.py b/tests/regressiontests/admin_scripts/lib1/nons_app/management/commands/__init__.py
86new file mode 100644
87index 0000000..e69de29
88diff --git a/tests/regressiontests/admin_scripts/lib1/nons_app/management/commands/nons_app_command1.py b/tests/regressiontests/admin_scripts/lib1/nons_app/management/commands/nons_app_command1.py
89new file mode 100644
90index 0000000..a393663
91--- /dev/null
92+++ b/tests/regressiontests/admin_scripts/lib1/nons_app/management/commands/nons_app_command1.py
93@@ -0,0 +1,9 @@
94+from django.core.management.base import BaseCommand
95+
96+class Command(BaseCommand):
97+    help = 'Test managment commands in non-namespaced app'
98+    requires_model_validation = False
99+    args = ''
100+
101+    def handle(self, *labels, **options):
102+        print 'EXECUTE:nons_app_command1'
103diff --git a/tests/regressiontests/admin_scripts/lib1/nons_app/models.py b/tests/regressiontests/admin_scripts/lib1/nons_app/models.py
104new file mode 100644
105index 0000000..e69de29
106diff --git a/tests/regressiontests/admin_scripts/lib1/nsapps/__init__.py b/tests/regressiontests/admin_scripts/lib1/nsapps/__init__.py
107new file mode 100644
108index 0000000..32f26d8
109--- /dev/null
110+++ b/tests/regressiontests/admin_scripts/lib1/nsapps/__init__.py
111@@ -0,0 +1,6 @@
112+# http://packages.python.org/distribute/setuptools.html#namespace-packages
113+try:
114+    __import__('pkg_resources').declare_namespace(__name__)
115+except ImportError:
116+    from pkgutil import extend_path
117+    __path__ = extend_path(__path__, __name__)
118diff --git a/tests/regressiontests/admin_scripts/lib1/nsapps/contrib/__init__.py b/tests/regressiontests/admin_scripts/lib1/nsapps/contrib/__init__.py
119new file mode 100644
120index 0000000..32f26d8
121--- /dev/null
122+++ b/tests/regressiontests/admin_scripts/lib1/nsapps/contrib/__init__.py
123@@ -0,0 +1,6 @@
124+# http://packages.python.org/distribute/setuptools.html#namespace-packages
125+try:
126+    __import__('pkg_resources').declare_namespace(__name__)
127+except ImportError:
128+    from pkgutil import extend_path
129+    __path__ = extend_path(__path__, __name__)
130diff --git a/tests/regressiontests/admin_scripts/lib1/nsapps/contrib/app1/__init__.py b/tests/regressiontests/admin_scripts/lib1/nsapps/contrib/app1/__init__.py
131new file mode 100644
132index 0000000..e69de29
133diff --git a/tests/regressiontests/admin_scripts/lib1/nsapps/contrib/app1/management/__init__.py b/tests/regressiontests/admin_scripts/lib1/nsapps/contrib/app1/management/__init__.py
134new file mode 100644
135index 0000000..e69de29
136diff --git a/tests/regressiontests/admin_scripts/lib1/nsapps/contrib/app1/management/commands/__init__.py b/tests/regressiontests/admin_scripts/lib1/nsapps/contrib/app1/management/commands/__init__.py
137new file mode 100644
138index 0000000..e69de29
139diff --git a/tests/regressiontests/admin_scripts/lib1/nsapps/contrib/app1/management/commands/app1_command1.py b/tests/regressiontests/admin_scripts/lib1/nsapps/contrib/app1/management/commands/app1_command1.py
140new file mode 100644
141index 0000000..2f479bb
142--- /dev/null
143+++ b/tests/regressiontests/admin_scripts/lib1/nsapps/contrib/app1/management/commands/app1_command1.py
144@@ -0,0 +1,9 @@
145+from django.core.management.base import BaseCommand
146+
147+class Command(BaseCommand):
148+    help = 'Test managment commands in namespaced apps'
149+    requires_model_validation = False
150+    args = ''
151+
152+    def handle(self, *labels, **options):
153+        print 'EXECUTE:app1_command1'
154diff --git a/tests/regressiontests/admin_scripts/lib1/nsapps/contrib/app1/models.py b/tests/regressiontests/admin_scripts/lib1/nsapps/contrib/app1/models.py
155new file mode 100644
156index 0000000..e69de29
157diff --git a/tests/regressiontests/admin_scripts/lib2/nsapps/__init__.py b/tests/regressiontests/admin_scripts/lib2/nsapps/__init__.py
158new file mode 100644
159index 0000000..32f26d8
160--- /dev/null
161+++ b/tests/regressiontests/admin_scripts/lib2/nsapps/__init__.py
162@@ -0,0 +1,6 @@
163+# http://packages.python.org/distribute/setuptools.html#namespace-packages
164+try:
165+    __import__('pkg_resources').declare_namespace(__name__)
166+except ImportError:
167+    from pkgutil import extend_path
168+    __path__ = extend_path(__path__, __name__)
169diff --git a/tests/regressiontests/admin_scripts/lib2/nsapps/contrib/__init__.py b/tests/regressiontests/admin_scripts/lib2/nsapps/contrib/__init__.py
170new file mode 100644
171index 0000000..32f26d8
172--- /dev/null
173+++ b/tests/regressiontests/admin_scripts/lib2/nsapps/contrib/__init__.py
174@@ -0,0 +1,6 @@
175+# http://packages.python.org/distribute/setuptools.html#namespace-packages
176+try:
177+    __import__('pkg_resources').declare_namespace(__name__)
178+except ImportError:
179+    from pkgutil import extend_path
180+    __path__ = extend_path(__path__, __name__)
181diff --git a/tests/regressiontests/admin_scripts/lib2/nsapps/contrib/app2/__init__.py b/tests/regressiontests/admin_scripts/lib2/nsapps/contrib/app2/__init__.py
182new file mode 100644
183index 0000000..e69de29
184diff --git a/tests/regressiontests/admin_scripts/lib2/nsapps/contrib/app2/management/__init__.py b/tests/regressiontests/admin_scripts/lib2/nsapps/contrib/app2/management/__init__.py
185new file mode 100644
186index 0000000..e69de29
187diff --git a/tests/regressiontests/admin_scripts/lib2/nsapps/contrib/app2/management/commands/__init__.py b/tests/regressiontests/admin_scripts/lib2/nsapps/contrib/app2/management/commands/__init__.py
188new file mode 100644
189index 0000000..e69de29
190diff --git a/tests/regressiontests/admin_scripts/lib2/nsapps/contrib/app2/management/commands/app2_command1.py b/tests/regressiontests/admin_scripts/lib2/nsapps/contrib/app2/management/commands/app2_command1.py
191new file mode 100644
192index 0000000..b9e20a7
193--- /dev/null
194+++ b/tests/regressiontests/admin_scripts/lib2/nsapps/contrib/app2/management/commands/app2_command1.py
195@@ -0,0 +1,9 @@
196+from django.core.management.base import BaseCommand
197+
198+class Command(BaseCommand):
199+    help = 'Test managment commands in namespaced apps'
200+    requires_model_validation = False
201+    args = ''
202+
203+    def handle(self, *labels, **options):
204+        print 'EXECUTE:app2_command1'
205diff --git a/tests/regressiontests/admin_scripts/lib2/nsapps/contrib/app2/models.py b/tests/regressiontests/admin_scripts/lib2/nsapps/contrib/app2/models.py
206new file mode 100644
207index 0000000..e69de29
208diff --git a/tests/regressiontests/admin_scripts/lib3/_addsitedir.py b/tests/regressiontests/admin_scripts/lib3/_addsitedir.py
209new file mode 100644
210index 0000000..9e264d2
211--- /dev/null
212+++ b/tests/regressiontests/admin_scripts/lib3/_addsitedir.py
213@@ -0,0 +1 @@
214+import os.path, site; site.addsitedir(os.path.dirname(__file__))
215diff --git a/tests/regressiontests/admin_scripts/lib3/exapps-nspkg.pth b/tests/regressiontests/admin_scripts/lib3/exapps-nspkg.pth
216new file mode 100644
217index 0000000..1f31155
218--- /dev/null
219+++ b/tests/regressiontests/admin_scripts/lib3/exapps-nspkg.pth
220@@ -0,0 +1 @@
221+import sys,new,os; p = os.path.join(sys._getframe(1).f_locals['sitedir'], *('exapps',)); ie = os.path.exists(os.path.join(p,'__init__.py')); m = not ie and sys.modules.setdefault('exapps',new.module('exapps')); mp = (m or []) and m.__dict__.setdefault('__path__',[]); (p not in mp) and mp.append(p)
222diff --git a/tests/regressiontests/admin_scripts/lib3/exapps/app3/__init__.py b/tests/regressiontests/admin_scripts/lib3/exapps/app3/__init__.py
223new file mode 100644
224index 0000000..e69de29
225diff --git a/tests/regressiontests/admin_scripts/lib3/exapps/app3/management/__init__.py b/tests/regressiontests/admin_scripts/lib3/exapps/app3/management/__init__.py
226new file mode 100644
227index 0000000..e69de29
228diff --git a/tests/regressiontests/admin_scripts/lib3/exapps/app3/management/commands/__init__.py b/tests/regressiontests/admin_scripts/lib3/exapps/app3/management/commands/__init__.py
229new file mode 100644
230index 0000000..e69de29
231diff --git a/tests/regressiontests/admin_scripts/lib3/exapps/app3/management/commands/app3_command1.py b/tests/regressiontests/admin_scripts/lib3/exapps/app3/management/commands/app3_command1.py
232new file mode 100644
233index 0000000..97f5d33
234--- /dev/null
235+++ b/tests/regressiontests/admin_scripts/lib3/exapps/app3/management/commands/app3_command1.py
236@@ -0,0 +1,9 @@
237+from django.core.management.base import BaseCommand
238+
239+class Command(BaseCommand):
240+    help = 'Test managment commands in namespaced apps'
241+    requires_model_validation = False
242+    args = ''
243+
244+    def handle(self, *labels, **options):
245+        print 'EXECUTE:app3_command1'
246diff --git a/tests/regressiontests/admin_scripts/lib3/exapps/app3/models.py b/tests/regressiontests/admin_scripts/lib3/exapps/app3/models.py
247new file mode 100644
248index 0000000..e69de29
249diff --git a/tests/regressiontests/admin_scripts/tests.py b/tests/regressiontests/admin_scripts/tests.py
250index dd7e4b3..aa56c45 100644
251--- a/tests/regressiontests/admin_scripts/tests.py
252+++ b/tests/regressiontests/admin_scripts/tests.py
253@@ -90,6 +90,9 @@ class AdminScriptTestCase(unittest.TestCase):
254     def run_test(self, script, args, settings_file=None, apps=None):
255         project_dir = os.path.dirname(test_dir)
256         base_dir = os.path.dirname(project_dir)
257+        lib1_dir = os.path.join(os.path.dirname(__file__), 'lib1')
258+        lib2_dir = os.path.join(os.path.dirname(__file__), 'lib2')
259+        lib3_dir = os.path.join(os.path.dirname(__file__), 'lib3')
260         ext_backend_base_dirs = self._ext_backend_paths()
261 
262         # Remember the old environment
263@@ -107,7 +110,7 @@ class AdminScriptTestCase(unittest.TestCase):
264             os.environ['DJANGO_SETTINGS_MODULE'] = settings_file
265         elif 'DJANGO_SETTINGS_MODULE' in os.environ:
266             del os.environ['DJANGO_SETTINGS_MODULE']
267-        python_path = [project_dir, base_dir]
268+        python_path = [project_dir, base_dir, lib1_dir, lib2_dir, lib3_dir]
269         python_path.extend(ext_backend_base_dirs)
270         os.environ[python_path_var_name] = os.pathsep.join(python_path)
271 
272@@ -1533,3 +1536,75 @@ class StartProject(LiveServerTestCase, AdminScriptTestCase):
273             with open(os.path.join(base_path, f)) as fh:
274                 self.assertEqual(fh.read(),
275                     '# some file for customtestproject test project')
276+
277+class NamespacePackagedApps(AdminScriptTestCase):
278+    def setUp(self):
279+        self.write_settings('settings.py', apps=['nons_app', 'nsapps.contrib.app1','nsapps.contrib.app2','exapps.app3'])
280+        test_dir = os.path.dirname(os.path.dirname(__file__))
281+        settings_file = open(os.path.join(test_dir, 'settings.py'), 'a')
282+        settings_file.write('import _addsitedir')
283+        settings_file.close()
284+
285+    def tearDown(self):
286+        self.remove_settings('settings.py')
287+
288+    def test_help(self):
289+        out, err = self.run_manage(['help'])
290+        self.assertNoOutput(err)
291+        self.assertOutput(out, "nons_app_command1")
292+        self.assertOutput(out, "app1_command1")
293+        self.assertOutput(out, "app2_command1")
294+        self.assertOutput(out, "app3_command1")
295+
296+    def test_nons_app(self):
297+        args = ['nons_app_command1']
298+        out, err = self.run_manage(args)
299+        self.assertNoOutput(err)
300+        self.assertOutput(out, "EXECUTE:nons_app_command1")
301+
302+    def test_nsapps(self):
303+        args = ['app1_command1']
304+        out, err = self.run_manage(args)
305+        self.assertNoOutput(err)
306+        self.assertOutput(out, "EXECUTE:app1_command1")
307+
308+        args = ['app2_command1']
309+        out, err = self.run_manage(args)
310+        self.assertNoOutput(err)
311+        self.assertOutput(out, "EXECUTE:app2_command1")
312+
313+    def test_exapps(self):
314+        args = ['app3_command1']
315+        out, err = self.run_manage(args)
316+        self.assertNoOutput(err)
317+        self.assertOutput(out, "EXECUTE:app3_command1")
318+
319+class PreloadedNamespacePackagedApps(AdminScriptTestCase):
320+    def setUp(self):
321+        self.write_settings('settings.py', apps=['nsapps.contrib.app1','nsapps.contrib.app2'])
322+        test_dir = os.path.dirname(os.path.dirname(__file__))
323+        settings_file = open(os.path.join(test_dir, 'settings.py'), 'a')
324+        settings_file.write('import nsapps')
325+        settings_file.close()
326+       
327+    def tearDown(self):
328+        self.remove_settings('settings.py')
329+
330+    def test_help(self):
331+        out, err = self.run_manage(['help'])
332+        self.assertNoOutput(err)
333+        self.assertOutput(out, "app1_command1")
334+        self.assertOutput(out, "app2_command1")
335+
336+
337+    def test_nsapps(self):
338+        args = ['app1_command1']
339+        out, err = self.run_manage(args)
340+        self.assertNoOutput(err)
341+        self.assertOutput(out, "EXECUTE:app1_command1")
342+
343+        args = ['app2_command1']
344+        out, err = self.run_manage(args)
345+        self.assertNoOutput(err)
346+        self.assertOutput(out, "EXECUTE:app2_command1")
347+