Changeset 6528
- Timestamp:
- 10/18/07 20:26:09 (1 year ago)
- Files:
-
- django/trunk/django/core/management/__init__.py (modified) (17 diffs)
- django/trunk/django/utils/datastructures.py (modified) (8 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
django/trunk/django/core/management/__init__.py
r6456 r6528 1 import django2 from django.core.management.base import BaseCommand, CommandError, handle_default_options3 from optparse import OptionParser4 1 import os 5 2 import sys 3 from optparse import OptionParser 6 4 from imp import find_module 5 6 import django 7 from django.core.management.base import BaseCommand, CommandError, handle_default_options 7 8 8 9 # For backwards compatibility: get_version() used to be in this module. 9 10 get_version = django.get_version 10 11 11 # A cache of loaded commands, so that call_command 12 # A cache of loaded commands, so that call_command 12 13 # doesn't have to reload every time it is called 13 14 _commands = None … … 15 16 def find_commands(management_dir): 16 17 """ 17 Given a path to a management directory, return a list of all the command names 18 that are available. Returns an empty list if no commands are defined. 19 """ 20 command_dir = os.path.join(management_dir,'commands') 18 Given a path to a management directory, returns a list of all the command 19 names that are available. 20 21 Returns an empty list if no commands are defined. 22 """ 23 command_dir = os.path.join(management_dir, 'commands') 21 24 try: 22 return [f[:-3] for f in os.listdir(command_dir) if not f.startswith('_') and f.endswith('.py')] 25 return [f[:-3] for f in os.listdir(command_dir) 26 if not f.startswith('_') and f.endswith('.py')] 23 27 except OSError: 24 28 return [] … … 26 30 def find_management_module(app_name): 27 31 """ 28 Determine the path to the management module for the application named,32 Determines the path to the management module for the application named, 29 33 without acutally importing the application or the management module. 30 34 … … 37 41 while parts: 38 42 part = parts.pop() 39 f, path,descr = find_module(part, path and [path] or None)43 f, path, descr = find_module(part, path and [path] or None) 40 44 return path 41 45 42 46 def load_command_class(app_name, name): 43 47 """ 44 Given a command name and an application name, returns the Command 48 Given a command name and an application name, returns the Command 45 49 class instance. All errors raised by the importation process 46 50 (ImportError, AttributeError) are allowed to propagate. 47 51 """ 48 return getattr(__import__('%s.management.commands.%s' % (app_name, name), 52 return getattr(__import__('%s.management.commands.%s' % (app_name, name), 49 53 {}, {}, ['Command']), 'Command')() 50 54 … … 52 56 """ 53 57 Returns a dictionary of commands against the application in which 54 those commands can be found. This works by looking for a 55 management.commands package in django.core, and in each installed 58 those commands can be found. This works by looking for a 59 management.commands package in django.core, and in each installed 56 60 application -- if a commands package exists, all commands in that 57 61 package are registered. … … 63 67 64 68 The dictionary is in the format {command_name: app_name}. Key-value 65 pairs from this dictionary can then be used in calls to 69 pairs from this dictionary can then be used in calls to 66 70 load_command_class(app_name, command_name) 67 71 68 72 If a specific version of a command must be loaded (e.g., with the 69 73 startapp command), the instantiated module can be placed in the 70 74 dictionary in place of the application name. 71 75 72 76 The dictionary is cached on the first call, and reused on subsequent 73 77 calls. … … 75 79 global _commands 76 80 if _commands is None: 77 _commands = dict([(name, 'django.core') 81 _commands = dict([(name, 'django.core') 78 82 for name in find_commands(__path__[0])]) 79 83 if load_user_commands: 80 # Get commands from all installed apps 84 # Get commands from all installed apps. 81 85 from django.conf import settings 82 86 for app_name in settings.INSTALLED_APPS: 83 87 try: 84 88 path = find_management_module(app_name) 85 _commands.update(dict([(name, app_name) 89 _commands.update(dict([(name, app_name) 86 90 for name in find_commands(path)])) 87 91 except ImportError: 88 92 pass # No management module - ignore this app 89 93 90 94 if project_directory: 91 95 # Remove the "startproject" command from self.commands, because … … 94 98 95 99 # Override the startapp command so that it always uses the 96 # project_directory, not the current working directory 100 # project_directory, not the current working directory 97 101 # (which is default). 98 102 from django.core.management.commands.startapp import ProjectCommand … … 114 118 try: 115 119 app_name = get_commands()[name] 116 if isinstance(app_name, BaseCommand): 120 if isinstance(app_name, BaseCommand): 117 121 # If the command is already loaded, use it directly. 118 122 klass = app_name … … 122 126 raise CommandError, "Unknown command: %r" % name 123 127 return klass.execute(*args, **options) 124 125 class LaxOptionParser(OptionParser): 128 129 class LaxOptionParser(OptionParser): 126 130 """ 127 131 An option parser that doesn't raise any errors on unknown options. 128 132 129 133 This is needed because the --settings and --pythonpath options affect 130 the commands (and thus the options) that are available to the user. 131 """ 132 def error(self, msg): 133 pass134 the commands (and thus the options) that are available to the user. 135 """ 136 def error(self, msg): 137 pass 134 138 135 139 class ManagementUtility(object): … … 145 149 self.project_directory = None 146 150 self.user_commands = False 147 151 148 152 def main_help_text(self): 149 153 """ … … 151 155 """ 152 156 usage = ['%s <subcommand> [options] [args]' % self.prog_name] 153 usage.append('Django command line tool, version %s' % django.get_version()) 154 usage.append("Type '%s help <subcommand>' for help on a specific subcommand." % self.prog_name) 157 usage.append('Django command line tool,' 158 ' version %s' % django.get_version()) 159 usage.append("Type '%s help <subcommand>' for help on a specific" 160 " subcommand." % self.prog_name) 155 161 usage.append('Available subcommands:') 156 commands = get_commands(self.user_commands, self.project_directory).keys() 162 commands = get_commands(self.user_commands, 163 self.project_directory).keys() 157 164 commands.sort() 158 165 for cmd in commands: … … 167 174 """ 168 175 try: 169 app_name = get_commands(self.user_commands, self.project_directory)[subcommand] 170 if isinstance(app_name, BaseCommand): 176 app_name = get_commands(self.user_commands, 177 self.project_directory)[subcommand] 178 if isinstance(app_name, BaseCommand): 171 179 # If the command is already loaded, use it directly. 172 180 klass = app_name … … 174 182 klass = load_command_class(app_name, subcommand) 175 183 except KeyError: 176 sys.stderr.write("Unknown command: %r\nType '%s help' for usage.\n" % (subcommand, self.prog_name)) 184 sys.stderr.write("Unknown command: %r\nType '%s help' for" 185 " usage.\n" % (subcommand, self.prog_name)) 177 186 sys.exit(1) 178 187 return klass 179 188 180 189 def execute(self): 181 190 """ … … 183 192 being run, creates a parser appropriate to that command, and runs it. 184 193 """ 185 # Preprocess options to extract --settings and --pythonpath. These options186 # could affect the commands that are available, so they must be processed187 # early188 parser = LaxOptionParser(version=get_version(), 189 option_list=BaseCommand.option_list) 194 # Preprocess options to extract --settings and --pythonpath. 195 # These options could affect the commands that are available, so they 196 # must be processed early. 197 parser = LaxOptionParser(version=get_version(), 198 option_list=BaseCommand.option_list) 190 199 try: 191 options, args = parser.parse_args(self.argv) 200 options, args = parser.parse_args(self.argv) 192 201 handle_default_options(options) 193 except: 202 except: 194 203 pass # Ignore any option errors at this point. 195 204 196 205 try: 197 206 subcommand = self.argv[1] … … 228 237 self.project_directory = project_directory 229 238 self.user_commands = True 230 239 231 240 def setup_environ(settings_mod): 232 241 """ 233 Configure the runtime environment. This can also be used by external242 Configures the runtime environment. This can also be used by external 234 243 scripts wanting to set up a similar environment to manage.py. 235 244 """ … … 245 254 246 255 # Set DJANGO_SETTINGS_MODULE appropriately. 247 os.environ['DJANGO_SETTINGS_MODULE'] = '%s.%s' % (project_name, settings_name) 256 os.environ['DJANGO_SETTINGS_MODULE'] = '%s.%s' % (project_name, 257 settings_name) 248 258 return project_directory 249 259 django/trunk/django/utils/datastructures.py
r6506 r6528 43 43 return True 44 44 return False 45 45 46 46 __contains__ = has_key 47 47 48 48 def copy(self): 49 """ returns a copy of this object"""49 """Returns a copy of this object.""" 50 50 return self.__copy__() 51 51 52 52 class SortedDict(dict): 53 "A dictionary that keeps its keys in the order in which they're inserted." 53 """ 54 A dictionary that keeps its keys in the order in which they're inserted. 55 """ 54 56 def __init__(self, data=None): 55 if data is None: data = {} 57 if data is None: 58 data = {} 56 59 dict.__init__(self, data) 57 60 if isinstance(data, dict): 58 61 self.keyOrder = data.keys() 59 62 else: 60 self.keyOrder =[key for key, value in data]63 self.keyOrder = [key for key, value in data] 61 64 62 65 def __setitem__(self, key, value): … … 103 106 104 107 def value_for_index(self, index): 105 " Returns the value of the item at the given zero-based index."108 """Returns the value of the item at the given zero-based index.""" 106 109 return self[self.keyOrder[index]] 107 110 108 111 def insert(self, index, key, value): 109 " Inserts the key, value pair before the item with the given index."112 """Inserts the key, value pair before the item with the given index.""" 110 113 if key in self.keyOrder: 111 114 n = self.keyOrder.index(key) 112 115 del self.keyOrder[n] 113 if n < index: index -= 1 116 if n < index: 117 index -= 1 114 118 self.keyOrder.insert(index, key) 115 119 dict.__setitem__(self, key, value) 116 120 117 121 def copy(self): 118 " Returns a copy of this object."122 """Returns a copy of this object.""" 119 123 # This way of initializing the copy means it works for subclasses, too. 120 124 obj = self.__class__(self) … … 134 138 class MultiValueDict(dict): 135 139 """ 136 A subclass of dictionary customized to handle multiple values for the same key. 140 A subclass of dictionary customized to handle multiple values for the 141 same key. 137 142 138 143 >>> d = MultiValueDict({'name': ['Adrian', 'Simon'], 'position': ['Developer']}) … … 177 182 def __deepcopy__(self, memo=None): 178 183 import copy 179 if memo is None: memo = {} 184 if memo is None: 185 memo = {} 180 186 result = self.__class__() 181 187 memo[id(self)] = result 182 188 for key, value in dict.items(self): 183 dict.__setitem__(result, copy.deepcopy(key, memo), copy.deepcopy(value, memo)) 189 dict.__setitem__(result, copy.deepcopy(key, memo), 190 copy.deepcopy(value, memo)) 184 191 return result 185 192 186 193 def get(self, key, default=None): 187 " Returns the default value if the requested data doesn't exist"194 """Returns the default value if the requested data doesn't exist.""" 188 195 try: 189 196 val = self[key] … … 195 202 196 203 def getlist(self, key): 197 " Returns an empty list if the requested data doesn't exist"204 """Returns an empty list if the requested data doesn't exist.""" 198 205 try: 199 206 return dict.__getitem__(self, key) … … 215 222 216 223 def appendlist(self, key, value): 217 " Appends an item to the internal list associated with key"224 """Appends an item to the internal list associated with key.""" 218 225 self.setlistdefault(key, []) 219 226 dict.__setitem__(self, key, self.getlist(key) + [value]) … … 227 234 228 235 def lists(self): 229 " Returns a list of (key, list) pairs."236 """Returns a list of (key, list) pairs.""" 230 237 return dict.items(self) 231 238 232 239 def values(self): 233 " Returns a list of the last value on every key list."240 """Returns a list of the last value on every key list.""" 234 241 return [self[key] for key in self.keys()] 235 242 236 243 def copy(self): 237 " Returns a copy of this object."244 """Returns a copy of this object.""" 238 245 return self.__deepcopy__() 239 246 240 247 def update(self, *args, **kwargs): 241 "update() extends rather than replaces existing key lists. Also accepts keyword args." 248 """ 249 update() extends rather than replaces existing key lists. 250 Also accepts keyword args. 251 """ 242 252 if len(args) > 1: 243 253 raise TypeError, "update expected at most 1 arguments, got %d" % len(args) … … 300 310 return dict.__repr__(d) 301 311 return dict.__repr__(self) 302
