Statistics
| Branch: | Tag: | Revision:

root / snf-webproject / synnefo / webproject / manage.py @ 4691814d

History | View | Annotate | Download (12.9 kB)

1 eeda4702 Kostas Papadimitriou
# Copyright 2011 GRNET S.A. All rights reserved.
2 eeda4702 Kostas Papadimitriou
#
3 eeda4702 Kostas Papadimitriou
# Redistribution and use in source and binary forms, with or
4 eeda4702 Kostas Papadimitriou
# without modification, are permitted provided that the following
5 eeda4702 Kostas Papadimitriou
# conditions are met:
6 eeda4702 Kostas Papadimitriou
#
7 eeda4702 Kostas Papadimitriou
#   1. Redistributions of source code must retain the above
8 eeda4702 Kostas Papadimitriou
#      copyright notice, this list of conditions and the following
9 eeda4702 Kostas Papadimitriou
#      disclaimer.
10 eeda4702 Kostas Papadimitriou
#
11 eeda4702 Kostas Papadimitriou
#   2. Redistributions in binary form must reproduce the above
12 eeda4702 Kostas Papadimitriou
#      copyright notice, this list of conditions and the following
13 eeda4702 Kostas Papadimitriou
#      disclaimer in the documentation and/or other materials
14 eeda4702 Kostas Papadimitriou
#      provided with the distribution.
15 eeda4702 Kostas Papadimitriou
#
16 eeda4702 Kostas Papadimitriou
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
17 eeda4702 Kostas Papadimitriou
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 eeda4702 Kostas Papadimitriou
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 eeda4702 Kostas Papadimitriou
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
20 eeda4702 Kostas Papadimitriou
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 eeda4702 Kostas Papadimitriou
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 eeda4702 Kostas Papadimitriou
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23 eeda4702 Kostas Papadimitriou
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24 eeda4702 Kostas Papadimitriou
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 eeda4702 Kostas Papadimitriou
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26 eeda4702 Kostas Papadimitriou
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 eeda4702 Kostas Papadimitriou
# POSSIBILITY OF SUCH DAMAGE.
28 eeda4702 Kostas Papadimitriou
#
29 eeda4702 Kostas Papadimitriou
# The views and conclusions contained in the software and
30 eeda4702 Kostas Papadimitriou
# documentation are those of the authors and should not be
31 eeda4702 Kostas Papadimitriou
# interpreted as representing official policies, either expressed
32 eeda4702 Kostas Papadimitriou
# or implied, of GRNET S.A.
33 eeda4702 Kostas Papadimitriou
34 18a544f5 Kostas Papadimitriou
"""
35 18a544f5 Kostas Papadimitriou
Extented django management module
36 18a544f5 Kostas Papadimitriou

37 18a544f5 Kostas Papadimitriou
Most of the code is shared from django.core.management module
38 18a544f5 Kostas Papadimitriou
to allow us extend the default django ManagementUtility object
39 18a544f5 Kostas Papadimitriou
used to provide command line interface of the django project
40 18a544f5 Kostas Papadimitriou
included in snf-webproject package.
41 18a544f5 Kostas Papadimitriou

42 18a544f5 Kostas Papadimitriou
The extended class provides the following:
43 18a544f5 Kostas Papadimitriou

44 18a544f5 Kostas Papadimitriou
- additional argument for the configuration of the SYNNEFO_SETTINGS_DIR
45 18a544f5 Kostas Papadimitriou
  environmental variable (--settings-dir).
46 18a544f5 Kostas Papadimitriou
- a fix for management utility to handle custom commands defined in
47 18a544f5 Kostas Papadimitriou
  applications living in namespaced packages (django ticket #14087)
48 18a544f5 Kostas Papadimitriou
- override of --version command to display the snf-webproject version
49 18a544f5 Kostas Papadimitriou
"""
50 8c34763c Giorgos Verigakis
51 d2ff89df Kostas Papadimitriou
from django.core.management import ManagementUtility, setup_environ, \
52 4691814d Ilias Tsitsimpis
    BaseCommand, LaxOptionParser, handle_default_options, find_commands, \
53 4691814d Ilias Tsitsimpis
    load_command_class
54 d2ff89df Kostas Papadimitriou
55 18a544f5 Kostas Papadimitriou
from django.core import management
56 18a544f5 Kostas Papadimitriou
from django.utils.importlib import import_module
57 4691814d Ilias Tsitsimpis
from optparse import make_option
58 07d104d8 Kostas Papadimitriou
from synnefo.util.version import get_component_version
59 d01cd522 Christos Stavrakakis
from synnefo.lib.dictconfig import dictConfig
60 d2ff89df Kostas Papadimitriou
61 d2ff89df Kostas Papadimitriou
import sys
62 a45fc1ae Christos Stavrakakis
import locale
63 d2ff89df Kostas Papadimitriou
import os
64 18a544f5 Kostas Papadimitriou
import imp
65 18a544f5 Kostas Papadimitriou
66 18a544f5 Kostas Papadimitriou
_commands = None
67 18a544f5 Kostas Papadimitriou
68 d01cd522 Christos Stavrakakis
69 18a544f5 Kostas Papadimitriou
def find_modules(name, path=None):
70 18a544f5 Kostas Papadimitriou
    """Find all modules with name 'name'
71 18a544f5 Kostas Papadimitriou

72 18a544f5 Kostas Papadimitriou
    Unlike find_module in the imp package this returns a list of all
73 18a544f5 Kostas Papadimitriou
    matched modules.
74 18a544f5 Kostas Papadimitriou
    """
75 18c15348 Kostas Papadimitriou
76 18a544f5 Kostas Papadimitriou
    results = []
77 bc89ff1a Georgios D. Tsoukalas
    if path is None:
78 bc89ff1a Georgios D. Tsoukalas
        path = sys.path
79 18a544f5 Kostas Papadimitriou
    for p in path:
80 18a544f5 Kostas Papadimitriou
        importer = sys.path_importer_cache.get(p, None)
81 18a544f5 Kostas Papadimitriou
        if importer is None:
82 18a544f5 Kostas Papadimitriou
            find_module = imp.find_module
83 18a544f5 Kostas Papadimitriou
        else:
84 18a544f5 Kostas Papadimitriou
            find_module = importer.find_module
85 18a544f5 Kostas Papadimitriou
86 18a544f5 Kostas Papadimitriou
        try:
87 18a544f5 Kostas Papadimitriou
            result = find_module(name, [p])
88 18a544f5 Kostas Papadimitriou
            if result is not None:
89 18a544f5 Kostas Papadimitriou
                results.append(result)
90 18a544f5 Kostas Papadimitriou
        except ImportError:
91 18c15348 Kostas Papadimitriou
            if sys.modules.get(name, None):
92 18c15348 Kostas Papadimitriou
                modpath = sys.modules[name].__path__
93 4691814d Ilias Tsitsimpis
                if isinstance(modpath, basestring) \
94 4691814d Ilias Tsitsimpis
                   and not ('', modpath) in results:
95 4691814d Ilias Tsitsimpis
                    results.append(('', sys.modules[name].__path__))
96 18c15348 Kostas Papadimitriou
                else:
97 18c15348 Kostas Papadimitriou
                    for mp in modpath:
98 18c15348 Kostas Papadimitriou
                        if not ('', mp) in results:
99 18c15348 Kostas Papadimitriou
                            results.append(('', mp))
100 18a544f5 Kostas Papadimitriou
            pass
101 18c15348 Kostas Papadimitriou
102 18a544f5 Kostas Papadimitriou
    if not results:
103 18a544f5 Kostas Papadimitriou
        raise ImportError("No module named %.200s" % name)
104 18c15348 Kostas Papadimitriou
105 18a544f5 Kostas Papadimitriou
    return results
106 18a544f5 Kostas Papadimitriou
107 bc89ff1a Georgios D. Tsoukalas
108 18a544f5 Kostas Papadimitriou
def find_management_module(app_name):
109 18a544f5 Kostas Papadimitriou
    """
110 18a544f5 Kostas Papadimitriou
    Determines the path to the management module for the given app_name,
111 18a544f5 Kostas Papadimitriou
    without actually importing the application or the management module.
112 18a544f5 Kostas Papadimitriou

113 18a544f5 Kostas Papadimitriou
    Raises ImportError if the management module cannot be found for any reason.
114 18a544f5 Kostas Papadimitriou
    """
115 18a544f5 Kostas Papadimitriou
    parts = app_name.split('.')
116 18a544f5 Kostas Papadimitriou
    parts.append('management')
117 18a544f5 Kostas Papadimitriou
    parts.reverse()
118 18a544f5 Kostas Papadimitriou
    part = parts.pop()
119 18a544f5 Kostas Papadimitriou
    paths = None
120 18a544f5 Kostas Papadimitriou
121 18a544f5 Kostas Papadimitriou
    # When using manage.py, the project module is added to the path,
122 18a544f5 Kostas Papadimitriou
    # loaded, then removed from the path. This means that
123 18a544f5 Kostas Papadimitriou
    # testproject.testapp.models can be loaded in future, even if
124 18a544f5 Kostas Papadimitriou
    # testproject isn't in the path. When looking for the management
125 18a544f5 Kostas Papadimitriou
    # module, we need look for the case where the project name is part
126 18a544f5 Kostas Papadimitriou
    # of the app_name but the project directory itself isn't on the path.
127 18a544f5 Kostas Papadimitriou
    try:
128 18a544f5 Kostas Papadimitriou
        modules = find_modules(part, paths)
129 18a544f5 Kostas Papadimitriou
        paths = [m[1] for m in modules]
130 bc89ff1a Georgios D. Tsoukalas
    except ImportError:
131 18a544f5 Kostas Papadimitriou
        if os.path.basename(os.getcwd()) != part:
132 bc89ff1a Georgios D. Tsoukalas
            raise
133 18a544f5 Kostas Papadimitriou
134 18a544f5 Kostas Papadimitriou
    while parts:
135 18a544f5 Kostas Papadimitriou
        part = parts.pop()
136 18a544f5 Kostas Papadimitriou
        modules = find_modules(part, paths)
137 18a544f5 Kostas Papadimitriou
        paths = [m[1] for m in modules]
138 18a544f5 Kostas Papadimitriou
    return paths[0]
139 18a544f5 Kostas Papadimitriou
140 18a544f5 Kostas Papadimitriou
141 18a544f5 Kostas Papadimitriou
def get_commands():
142 18a544f5 Kostas Papadimitriou
    """
143 18a544f5 Kostas Papadimitriou
    Returns a dictionary mapping command names to their callback applications.
144 18a544f5 Kostas Papadimitriou

145 18a544f5 Kostas Papadimitriou
    This works by looking for a management.commands package in django.core, and
146 18a544f5 Kostas Papadimitriou
    in each installed application -- if a commands package exists, all commands
147 18a544f5 Kostas Papadimitriou
    in that package are registered.
148 18a544f5 Kostas Papadimitriou

149 18a544f5 Kostas Papadimitriou
    Core commands are always included. If a settings module has been
150 18a544f5 Kostas Papadimitriou
    specified, user-defined commands will also be included, the
151 18a544f5 Kostas Papadimitriou
    startproject command will be disabled, and the startapp command
152 18a544f5 Kostas Papadimitriou
    will be modified to use the directory in which the settings module appears.
153 18a544f5 Kostas Papadimitriou

154 18a544f5 Kostas Papadimitriou
    The dictionary is in the format {command_name: app_name}. Key-value
155 18a544f5 Kostas Papadimitriou
    pairs from this dictionary can then be used in calls to
156 18a544f5 Kostas Papadimitriou
    load_command_class(app_name, command_name)
157 18a544f5 Kostas Papadimitriou

158 18a544f5 Kostas Papadimitriou
    If a specific version of a command must be loaded (e.g., with the
159 18a544f5 Kostas Papadimitriou
    startapp command), the instantiated module can be placed in the
160 18a544f5 Kostas Papadimitriou
    dictionary in place of the application name.
161 18a544f5 Kostas Papadimitriou

162 18a544f5 Kostas Papadimitriou
    The dictionary is cached on the first call and reused on subsequent
163 18a544f5 Kostas Papadimitriou
    calls.
164 18a544f5 Kostas Papadimitriou
    """
165 18a544f5 Kostas Papadimitriou
    global _commands
166 18a544f5 Kostas Papadimitriou
    if _commands is None:
167 4691814d Ilias Tsitsimpis
        _commands = dict([(name, 'django.core') for name in
168 4691814d Ilias Tsitsimpis
                         find_commands(management.__path__[0])])
169 18a544f5 Kostas Papadimitriou
170 18a544f5 Kostas Papadimitriou
        # Find the installed apps
171 18a544f5 Kostas Papadimitriou
        try:
172 18a544f5 Kostas Papadimitriou
            from django.conf import settings
173 18a544f5 Kostas Papadimitriou
            apps = settings.INSTALLED_APPS
174 18a544f5 Kostas Papadimitriou
        except (AttributeError, EnvironmentError, ImportError):
175 18a544f5 Kostas Papadimitriou
            apps = []
176 18a544f5 Kostas Papadimitriou
177 18a544f5 Kostas Papadimitriou
        # Find the project directory
178 18a544f5 Kostas Papadimitriou
        try:
179 18a544f5 Kostas Papadimitriou
            from django.conf import settings
180 18a544f5 Kostas Papadimitriou
            module = import_module(settings.SETTINGS_MODULE)
181 18a544f5 Kostas Papadimitriou
            project_directory = setup_environ(module, settings.SETTINGS_MODULE)
182 18a544f5 Kostas Papadimitriou
        except (AttributeError, EnvironmentError, ImportError, KeyError):
183 18a544f5 Kostas Papadimitriou
            project_directory = None
184 18a544f5 Kostas Papadimitriou
185 18a544f5 Kostas Papadimitriou
        # Find and load the management module for each installed app.
186 18a544f5 Kostas Papadimitriou
        for app_name in apps:
187 18a544f5 Kostas Papadimitriou
            try:
188 18a544f5 Kostas Papadimitriou
                path = find_management_module(app_name)
189 18a544f5 Kostas Papadimitriou
                _commands.update(dict([(name, app_name)
190 18a544f5 Kostas Papadimitriou
                                       for name in find_commands(path)]))
191 18a544f5 Kostas Papadimitriou
            except ImportError:
192 bc89ff1a Georgios D. Tsoukalas
                pass  # No management module - ignore this app
193 18a544f5 Kostas Papadimitriou
194 18a544f5 Kostas Papadimitriou
        if project_directory:
195 18a544f5 Kostas Papadimitriou
            # Remove the "startproject" command from self.commands, because
196 18a544f5 Kostas Papadimitriou
            # that's a django-admin.py command, not a manage.py command.
197 18a544f5 Kostas Papadimitriou
            del _commands['startproject']
198 18a544f5 Kostas Papadimitriou
199 18a544f5 Kostas Papadimitriou
            # Override the startapp command so that it always uses the
200 18a544f5 Kostas Papadimitriou
            # project_directory, not the current working directory
201 18a544f5 Kostas Papadimitriou
            # (which is default).
202 18a544f5 Kostas Papadimitriou
            from django.core.management.commands.startapp import ProjectCommand
203 18a544f5 Kostas Papadimitriou
            _commands['startapp'] = ProjectCommand(project_directory)
204 18a544f5 Kostas Papadimitriou
205 18a544f5 Kostas Papadimitriou
    return _commands
206 d2ff89df Kostas Papadimitriou
207 bc89ff1a Georgios D. Tsoukalas
208 d2ff89df Kostas Papadimitriou
class SynnefoManagementUtility(ManagementUtility):
209 d2ff89df Kostas Papadimitriou
    """
210 d2ff89df Kostas Papadimitriou
    Override django ManagementUtility to allow us provide a custom
211 d2ff89df Kostas Papadimitriou
    --settings-dir option for synnefo application.
212 d2ff89df Kostas Papadimitriou

213 d2ff89df Kostas Papadimitriou
    Most of the following code is a copy from django.core.management module
214 d2ff89df Kostas Papadimitriou
    """
215 d2ff89df Kostas Papadimitriou
216 d2ff89df Kostas Papadimitriou
    def execute(self):
217 d2ff89df Kostas Papadimitriou
        """
218 d2ff89df Kostas Papadimitriou
        Given the command-line arguments, this figures out which subcommand is
219 d2ff89df Kostas Papadimitriou
        being run, creates a parser appropriate to that command, and runs it.
220 d2ff89df Kostas Papadimitriou
        """
221 d2ff89df Kostas Papadimitriou
222 d2ff89df Kostas Papadimitriou
        # --settings-dir option
223 d2ff89df Kostas Papadimitriou
        # will remove it later to avoid django commands from raising errors
224 d2ff89df Kostas Papadimitriou
        option_list = BaseCommand.option_list + (
225 4691814d Ilias Tsitsimpis
            make_option(
226 4691814d Ilias Tsitsimpis
                '--settings-dir',
227 d2ff89df Kostas Papadimitriou
                action='store',
228 d2ff89df Kostas Papadimitriou
                dest='settings_dir',
229 d2ff89df Kostas Papadimitriou
                default=None,
230 d2ff89df Kostas Papadimitriou
                help='Load *.conf files from directory as settings'),)
231 d2ff89df Kostas Papadimitriou
232 d2ff89df Kostas Papadimitriou
        # Preprocess options to extract --settings and --pythonpath.
233 d2ff89df Kostas Papadimitriou
        # These options could affect the commands that are available, so they
234 d2ff89df Kostas Papadimitriou
        # must be processed early.
235 d2ff89df Kostas Papadimitriou
        parser = LaxOptionParser(usage="%prog subcommand [options] [args]",
236 07d104d8 Kostas Papadimitriou
                                 version=get_component_version('webproject'),
237 d2ff89df Kostas Papadimitriou
                                 option_list=option_list)
238 d2ff89df Kostas Papadimitriou
        self.autocomplete()
239 d2ff89df Kostas Papadimitriou
        try:
240 d2ff89df Kostas Papadimitriou
            options, args = parser.parse_args(self.argv)
241 d2ff89df Kostas Papadimitriou
            handle_default_options(options)
242 d2ff89df Kostas Papadimitriou
        except:
243 bc89ff1a Georgios D. Tsoukalas
            pass  # Ignore any option errors at this point.
244 d2ff89df Kostas Papadimitriou
245 d2ff89df Kostas Papadimitriou
        # user provides custom settings dir
246 d2ff89df Kostas Papadimitriou
        # set it as environmental variable and remove it from self.argv
247 d2ff89df Kostas Papadimitriou
        if options.settings_dir:
248 d2ff89df Kostas Papadimitriou
            os.environ['SYNNEFO_SETTINGS_DIR'] = options.settings_dir
249 d2ff89df Kostas Papadimitriou
            for arg in self.argv:
250 d2ff89df Kostas Papadimitriou
                if arg.startswith('--settings-dir'):
251 d2ff89df Kostas Papadimitriou
                    self.argv.remove(arg)
252 d2ff89df Kostas Papadimitriou
253 d2ff89df Kostas Papadimitriou
        try:
254 d2ff89df Kostas Papadimitriou
            subcommand = self.argv[1]
255 d2ff89df Kostas Papadimitriou
        except IndexError:
256 bc89ff1a Georgios D. Tsoukalas
            subcommand = 'help'  # Display help if no arguments were given.
257 d2ff89df Kostas Papadimitriou
258 e43ac298 Christos Stavrakakis
        # Encode stdout. This check is required because of the way python
259 bc89ff1a Georgios D. Tsoukalas
        # checks if something is tty:
260 bc89ff1a Georgios D. Tsoukalas
        # https://bugzilla.redhat.com/show_bug.cgi?id=841152
261 1f0030e6 Kostas Papadimitriou
        if not subcommand in ['test'] and not 'shell' in subcommand:
262 e43ac298 Christos Stavrakakis
            sys.stdout = EncodedStdOut(sys.stdout)
263 e43ac298 Christos Stavrakakis
264 d2ff89df Kostas Papadimitriou
        if subcommand == 'help':
265 d2ff89df Kostas Papadimitriou
            if len(args) > 2:
266 d2ff89df Kostas Papadimitriou
                self.fetch_command(args[2]).print_help(self.prog_name, args[2])
267 d2ff89df Kostas Papadimitriou
            else:
268 d2ff89df Kostas Papadimitriou
                parser.print_lax_help()
269 d2ff89df Kostas Papadimitriou
                sys.stdout.write(self.main_help_text() + '\n')
270 d2ff89df Kostas Papadimitriou
                sys.exit(1)
271 d2ff89df Kostas Papadimitriou
        # Special-cases: We want 'django-admin.py --version' and
272 d2ff89df Kostas Papadimitriou
        # 'django-admin.py --help' to work, for backwards compatibility.
273 d2ff89df Kostas Papadimitriou
        elif self.argv[1:] == ['--version']:
274 d2ff89df Kostas Papadimitriou
            # LaxOptionParser already takes care of printing the version.
275 d2ff89df Kostas Papadimitriou
            pass
276 d2ff89df Kostas Papadimitriou
        elif self.argv[1:] in (['--help'], ['-h']):
277 d2ff89df Kostas Papadimitriou
            parser.print_lax_help()
278 d2ff89df Kostas Papadimitriou
            sys.stdout.write(self.main_help_text() + '\n')
279 d2ff89df Kostas Papadimitriou
        else:
280 d2ff89df Kostas Papadimitriou
            self.fetch_command(subcommand).run_from_argv(self.argv)
281 00b4f1be Faidon Liambotis
282 18a544f5 Kostas Papadimitriou
    def main_help_text(self):
283 18a544f5 Kostas Papadimitriou
        """
284 18a544f5 Kostas Papadimitriou
        Returns the script's main help text, as a string.
285 18a544f5 Kostas Papadimitriou
        """
286 bc89ff1a Georgios D. Tsoukalas
        usage = ['', ("Type '%s help <subcommand>' for help"
287 bc89ff1a Georgios D. Tsoukalas
                      "on a specific subcommand.") % self.prog_name, '']
288 18a544f5 Kostas Papadimitriou
        usage.append('Available subcommands:')
289 18a544f5 Kostas Papadimitriou
        commands = get_commands().keys()
290 18a544f5 Kostas Papadimitriou
        commands.sort()
291 18a544f5 Kostas Papadimitriou
        for cmd in commands:
292 18a544f5 Kostas Papadimitriou
            usage.append('  %s' % cmd)
293 18a544f5 Kostas Papadimitriou
        return '\n'.join(usage)
294 18a544f5 Kostas Papadimitriou
295 18a544f5 Kostas Papadimitriou
    def fetch_command(self, subcommand):
296 18a544f5 Kostas Papadimitriou
        """
297 18a544f5 Kostas Papadimitriou
        Tries to fetch the given subcommand, printing a message with the
298 18a544f5 Kostas Papadimitriou
        appropriate command called from the command line (usually
299 18a544f5 Kostas Papadimitriou
        "django-admin.py" or "manage.py") if it can't be found.
300 18a544f5 Kostas Papadimitriou
        """
301 18a544f5 Kostas Papadimitriou
        try:
302 18a544f5 Kostas Papadimitriou
            app_name = get_commands()[subcommand]
303 18a544f5 Kostas Papadimitriou
        except KeyError:
304 bc89ff1a Georgios D. Tsoukalas
            sys.stderr.write(("Unknown command: %r\n"
305 bc89ff1a Georgios D. Tsoukalas
                              "Type '%s help' for usage.\n") %
306 bc89ff1a Georgios D. Tsoukalas
                             (subcommand, self.prog_name))
307 18a544f5 Kostas Papadimitriou
            sys.exit(1)
308 18a544f5 Kostas Papadimitriou
        if isinstance(app_name, BaseCommand):
309 18a544f5 Kostas Papadimitriou
            # If the command is already loaded, use it directly.
310 18a544f5 Kostas Papadimitriou
            klass = app_name
311 18a544f5 Kostas Papadimitriou
        else:
312 18a544f5 Kostas Papadimitriou
            klass = load_command_class(app_name, subcommand)
313 18a544f5 Kostas Papadimitriou
        return klass
314 18a544f5 Kostas Papadimitriou
315 d01cd522 Christos Stavrakakis
316 d01cd522 Christos Stavrakakis
def configure_logging():
317 d01cd522 Christos Stavrakakis
    try:
318 d01cd522 Christos Stavrakakis
        from synnefo.settings import SNF_MANAGE_LOGGING_SETUP
319 d01cd522 Christos Stavrakakis
        dictConfig(SNF_MANAGE_LOGGING_SETUP)
320 d01cd522 Christos Stavrakakis
    except ImportError:
321 d01cd522 Christos Stavrakakis
        import logging
322 d01cd522 Christos Stavrakakis
        logging.basicConfig()
323 d01cd522 Christos Stavrakakis
        log = logging.getLogger()
324 d01cd522 Christos Stavrakakis
        log.warning("SNF_MANAGE_LOGGING_SETUP setting missing.")
325 d01cd522 Christos Stavrakakis
326 d01cd522 Christos Stavrakakis
327 a45fc1ae Christos Stavrakakis
class EncodedStdOut(object):
328 21ce46e9 Christos Stavrakakis
    def __init__(self, stdout):
329 c9284fad Christos Stavrakakis
        try:
330 c9284fad Christos Stavrakakis
            std_encoding = stdout.encoding
331 c9284fad Christos Stavrakakis
        except AttributeError:
332 c9284fad Christos Stavrakakis
            std_encoding = None
333 c9284fad Christos Stavrakakis
        self.encoding = std_encoding or locale.getpreferredencoding()
334 65e4e685 Christos Stavrakakis
        self.original_stdout = stdout
335 a45fc1ae Christos Stavrakakis
336 a45fc1ae Christos Stavrakakis
    def write(self, string):
337 a45fc1ae Christos Stavrakakis
        if isinstance(string, unicode):
338 a45fc1ae Christos Stavrakakis
            string = string.encode(self.encoding)
339 21ce46e9 Christos Stavrakakis
        self.original_stdout.write(string)
340 a45fc1ae Christos Stavrakakis
341 c9284fad Christos Stavrakakis
    def __getattr__(self, name):
342 c9284fad Christos Stavrakakis
        return getattr(self.original_stdout, name)
343 c9284fad Christos Stavrakakis
344 a45fc1ae Christos Stavrakakis
345 b9685924 Kostas Papadimitriou
def main():
346 d2ff89df Kostas Papadimitriou
    # no need to run setup_environ
347 d2ff89df Kostas Papadimitriou
    # we already know our project
348 4691814d Ilias Tsitsimpis
    os.environ['DJANGO_SETTINGS_MODULE'] = \
349 4691814d Ilias Tsitsimpis
        os.environ.get('DJANGO_SETTINGS_MODULE', 'synnefo.settings')
350 d01cd522 Christos Stavrakakis
    configure_logging()
351 d2ff89df Kostas Papadimitriou
    mu = SynnefoManagementUtility(sys.argv)
352 d2ff89df Kostas Papadimitriou
    mu.execute()
353 b9685924 Kostas Papadimitriou
354 b9685924 Kostas Papadimitriou
if __name__ == "__main__":
355 b9685924 Kostas Papadimitriou
    main()