Code

Ticket #5222: __init__.py.2.diff

File __init__.py.2.diff, 10.4 KB (added by dnordberg@…, 7 years ago)

Diff file of init.py with last line removed.

Line 
1--- __init__.py 2007-08-21 13:59:59.000000000 +0300
2+++ /home/daniel/Desktop/django_management_init.py      2007-08-21 13:59:46.000000000 +0300
3@@ -1,180 +1,219 @@
4 import django
5 from optparse import OptionParser
6 import os
7 import sys
8 import textwrap
9 
10 # For backwards compatibility: get_version() used to be in this module.
11 get_version = django.get_version
12 
13-def load_command_class(name):
14+def find_commands(path):
15     """
16-    Given a command name, returns the Command class instance. Raises
17-    ImportError if it doesn't exist.
18+    Given a path to a management directory, return a list of all the command names
19+    that are available. Returns an empty list if no commands are defined.
20     """
21-    # Let the ImportError propogate.
22-    return getattr(__import__('django.core.management.commands.%s' % name, {}, {}, ['Command']), 'Command')()
23+    command_dir = os.path.join(path, 'commands')
24+    try:
25+        return [f[:-3] for f in os.listdir(command_dir) if not f.startswith('_') and f.endswith('.py')]
26+    except OSError:
27+        return []
28+
29+def load_default_commands():
30+    """
31+    Returns a dictionary of instances of all available Command classes.
32+
33+    This works by looking for and loading all Python modules in the
34+    django.core.management.commands package.
35+
36+    The dictionary is in the format {name: command_instance}.
37+    """
38+    return dict([(name, getattr(__import__('django.core.management.commands.%s' % (name), {}, {}, ['Command']), 'Command')()) for name in find_commands(__path__[0])])
39+
40+def load_project_commands():
41+    """
42+    Returns a dictionary of instances of all available Command classes.
43+
44+    It looks for a management.commands package in each installed application
45+    -- if a commands package exists, it loads all commands in that
46+    application and raises an AttributeError if a command doesn't contain a
47+    Command instance.
48+
49+    The dictionary is in the format {name: command_instance}.
50+    """
51+   
52+    commands = {}
53+
54+    from django.db import models
55+   
56+    # Get commands from all installed apps
57+    for app in models.get_apps():
58+        try:
59+            app_name = '.'.join(app.__name__.split('.')[:-1])
60+            path = os.path.join(os.path.dirname(app.__file__),'management')
61+            commands.update(dict([(name, getattr(__import__('%s.management.commands.%s' % (app_name, name), {}, {}, ['Command']), 'Command')()) for name in find_commands(path)]))
62+        except AttributeError:
63+            sys.stderr.write("Management command '%s' in application '%s' doesn't contain a Command instance.\n" % (name, app_name))
64+            sys.exit(1)
65+           
66+    return commands
67 
68 def call_command(name, *args, **options):
69     """
70     Calls the given command, with the given options and args/kwargs.
71     
72     This is the primary API you should use for calling specific commands.
73     
74     Some examples:
75         call_command('syncdb')
76         call_command('shell', plain=True)
77         call_command('sqlall', 'myapp')
78     """
79-    klass = load_command_class(name)
80+    klass = getattr(__import__(_DJANGO_COMMANDS[name].__module__, {}, {}, ['Command']), 'Command')()
81     return klass.execute(*args, **options)
82 
83 class ManagementUtility(object):
84     """
85     Encapsulates the logic of the django-admin.py and manage.py utilities.
86 
87     A ManagementUtility has a number of commands, which can be manipulated
88     by editing the self.commands dictionary.
89     """
90     def __init__(self):
91-        self.commands = self.default_commands()
92-
93-    def default_commands(self):
94-        """
95-        Returns a dictionary of instances of all available Command classes.
96-
97-        This works by looking for and loading all Python modules in the
98-        django.core.management.commands package.
99-
100-        The dictionary is in the format {name: command_instance}.
101-        """
102-        command_dir = os.path.join(__path__[0], 'commands')
103-        names = [f[:-3] for f in os.listdir(command_dir) if not f.startswith('_') and f.endswith('.py')]
104-        return dict([(name, load_command_class(name)) for name in names])
105-
106+        self.commands = _DJANGO_COMMANDS
107+       
108     def usage(self):
109         """
110         Returns a usage string, for use with optparse.
111 
112         The string doesn't include the options (e.g., "--verbose"), because
113         optparse puts those in automatically.
114         """
115         usage = ["%prog command [options]\nactions:"]
116         commands = self.commands.items()
117         commands.sort()
118         for name, cmd in commands:
119             usage.append('  %s %s' % (name, cmd.args))
120             usage.extend(textwrap.wrap(cmd.help, initial_indent='    ', subsequent_indent='    '))
121             usage.append('')
122         return '\n'.join(usage[:-1]) # Cut off the last list element, an empty space.
123 
124     def execute(self, argv=None):
125         """
126         Parses the given argv from the command line, determines which command
127         to run and runs the command.
128         """
129         if argv is None:
130             argv = sys.argv
131 
132         # Create the parser object and parse the command-line args.
133         # TODO: Ideally each Command class would register its own options for
134         # add_option(), but we'd need to figure out how to allow for multiple
135         # Commands using the same options. The optparse library gets in the way
136         # by checking for conflicts:
137         # http://docs.python.org/lib/optparse-conflicts-between-options.html
138         parser = OptionParser(usage=self.usage(), version=get_version())
139         parser.add_option('--settings',
140             help='The Python path to a settings module, e.g. "myproject.settings.main". If this isn\'t provided, the DJANGO_SETTINGS_MODULE environment variable will be used.')
141         parser.add_option('--pythonpath',
142             help='A directory to add to the Python path, e.g. "/home/djangoprojects/myproject".')
143         parser.add_option('--plain', action='store_true', dest='plain',
144             help='When using "shell": Tells Django to use plain Python, not IPython.')
145         parser.add_option('--noinput', action='store_false', dest='interactive', default=True,
146             help='Tells Django to NOT prompt the user for input of any kind.')
147         parser.add_option('--noreload', action='store_false', dest='use_reloader', default=True,
148             help='When using "runserver": Tells Django to NOT use the auto-reloader.')
149         parser.add_option('--format', default='json', dest='format',
150             help='Specifies the output serialization format for fixtures')
151         parser.add_option('--indent', default=None, dest='indent',
152             type='int', help='Specifies the indent level to use when pretty-printing output')
153         parser.add_option('--verbosity', action='store', dest='verbosity', default='1',
154             type='choice', choices=['0', '1', '2'],
155             help='Verbosity level; 0=minimal output, 1=normal output, 2=all output')
156         parser.add_option('--adminmedia', dest='admin_media_path', default='',
157             help='When using "runserver": Specifies the directory from which to serve admin media.')
158         options, args = parser.parse_args(argv[1:])
159 
160         # If the 'settings' or 'pythonpath' options were submitted, activate those.
161         if options.settings:
162             os.environ['DJANGO_SETTINGS_MODULE'] = options.settings
163         if options.pythonpath:
164             sys.path.insert(0, options.pythonpath)
165 
166         # Run the appropriate command.
167         try:
168             command_name = args[0]
169         except IndexError:
170             sys.stderr.write("Type '%s --help' for usage.\n" % os.path.basename(argv[0]))
171             sys.exit(1)
172         try:
173             command = self.commands[command_name]
174         except KeyError:
175             sys.stderr.write("Unknown command: %r\nType '%s --help' for usage.\n" % (command_name, os.path.basename(argv[0])))
176             sys.exit(1)
177         command.execute(*args[1:], **options.__dict__)
178 
179 class ProjectManagementUtility(ManagementUtility):
180     """
181     A ManagementUtility that is specific to a particular Django project.
182     As such, its commands are slightly different than those of its parent
183     class.
184 
185     In practice, this class represents manage.py, whereas ManagementUtility
186     represents django-admin.py.
187     """
188     def __init__(self, project_directory):
189         super(ProjectManagementUtility, self).__init__()
190 
191         # Remove the "startproject" command from self.commands, because
192         # that's a django-admin.py command, not a manage.py command.
193         del self.commands['startproject']
194 
195         # Override the startapp command so that it always uses the
196         # project_directory, not the current working directory (which is default).
197         from django.core.management.commands.startapp import ProjectCommand
198         self.commands['startapp'] = ProjectCommand(project_directory)
199 
200 def setup_environ(settings_mod):
201     """
202     Configure the runtime environment. This can also be used by external
203     scripts wanting to set up a similar environment to manage.py.
204     """
205     # Add this project to sys.path so that it's importable in the conventional
206     # way. For example, if this file (manage.py) lives in a directory
207     # "myproject", this code would add "/path/to/myproject" to sys.path.
208     project_directory, settings_filename = os.path.split(settings_mod.__file__)
209     project_name = os.path.basename(project_directory)
210     settings_name = os.path.splitext(settings_filename)[0]
211     sys.path.append(os.path.join(project_directory, '..'))
212     project_module = __import__(project_name, {}, {}, [''])
213     sys.path.pop()
214 
215     # Set DJANGO_SETTINGS_MODULE appropriately.
216     os.environ['DJANGO_SETTINGS_MODULE'] = '%s.%s' % (project_name, settings_name)
217+   
218+    # Update default commands with project commands for django internal
219+    # webservers and the manage.py utility
220+    _DJANGO_COMMANDS.update(load_project_commands())
221+   
222     return project_directory
223 
224 def execute_from_command_line(argv=None):
225     """
226     A simple method that runs a ManagementUtility.
227     """
228     utility = ManagementUtility()
229     utility.execute(argv)
230 
231 def execute_manager(settings_mod, argv=None):
232     """
233     Like execute_from_command_line(), but for use by manage.py, a
234     project-specific django-admin.py utility.
235     """
236     project_directory = setup_environ(settings_mod)
237     utility = ProjectManagementUtility(project_directory)
238     utility.execute(argv)
239+   
240+# Add default commands to a dict
241+_DJANGO_COMMANDS = load_default_commands()
242+
243+