<commit_before>"""
Base classes for writing management commands (named commands which can
be executed through ``django-admin.py`` or ``manage.py``).

"""

import os
import sys
from optparse import make_option, OptionParser

import django
from django.core.exceptions import ImproperlyConfigured
from django.core.management.color import color_style

try:
    set
except NameError:
    from sets import Set as set     # For Python 2.3

class CommandError(Exception):
    """
    Exception class indicating a problem while executing a management
    command.

    If this exception is raised during the execution of a management
    command, it will be caught and turned into a nicely-printed error
    message to the appropriate output stream (i.e., stderr); as a
    result, raising this exception (with a sensible description of the
    error) is the preferred way to indicate that something has gone
    wrong in the execution of a command.

    """
    pass

def handle_default_options(options):
    """
    Include any default options that all commands should accept here
    so that ManagementUtility can handle them before searching for
    user commands.

    """
    if options.settings:
        os.environ['DJANGO_SETTINGS_MODULE'] = options.settings
    if options.pythonpath:
        sys.path.insert(0, options.pythonpath)

class BaseCommand(object):
    """
    The base class from which all management commands ultimately
    derive.

    Use this class if you want access to all of the mechanisms which
    parse the command-line arguments and work out what code to call in
    response; if you don't need to change any of that behavior,
    consider using one of the subclasses defined in this file.

    If you are interested in overriding/customizing various aspects of
    the command-parsing and -execution behavior, the normal flow works
    as follows:

    1. ``django-admin.py`` or ``manage.py`` loads the command class
       and calls its ``run_from_argv()`` method.

    2. The ``run_from_argv()`` method calls ``create_parser()`` to get
       an ``OptionParser`` for the arguments, parses them, performs
       any environment changes requested by options like
       ``pythonpath``, and then calls the ``execute()`` method,
       passing the parsed arguments.

    3. The ``execute()`` method attempts to carry out the command by
       calling the ``handle()`` method with the parsed arguments; any
       output produced by ``handle()`` will be printed to standard
       output and, if the command is intended to produce a block of
       SQL statements, will be wrapped in ``BEGIN`` and ``COMMIT``.

    4. If ``handle()`` raised a ``CommandError``, ``execute()`` will
       instead print an error message to ``stderr``.

    Thus, the ``handle()`` method is typically the starting point for
    subclasses; many built-in commands and command types either place
    all of their logic in ``handle()``, or perform some additional
    parsing work in ``handle()`` and then delegate from it to more
    specialized methods as needed.

    Several attributes affect behavior at various steps along the way:

    ``args``
        A string listing the arguments accepted by the command,
        suitable for use in help messages; e.g., a command which takes
        a list of application names might set this to '<appname
        appname ...>'.

    ``can_import_settings``
        A boolean indicating whether the command needs to be able to
        import Django settings; if ``True``, ``execute()`` will verify
        that this is possible before proceeding. Default value is
        ``True``.

    ``help``
        A short description of the command, which will be printed in
        help messages.

    ``option_list``
        This is the list of ``optparse`` options which will be fed
        into the command's ``OptionParser`` for parsing arguments.

    ``output_transaction``
        A boolean indicating whether the command outputs SQL
        statements; if ``True``, the output will automatically be
        wrapped with ``BEGIN;`` and ``COMMIT;``. Default value is
        ``False``.

    ``requires_model_validation``
        A boolean; if ``True``, validation of installed models will be
        performed prior to executing the command. Default value is
        ``True``. To validate an individual application's models
        rather than all applications' models, call
        ``self.validate(app)`` from ``handle()``, where ``app`` is the
        application's Python module.

    """
    # Metadata about this command.
    option_list = (
        make_option('-v', '--verbosity', action='store', dest='verbosity', default='1',
            type='choice', choices=['0', '1', '2'],
            help='Verbosity level; 0=minimal output, 1=normal output, 2=all output'),
        make_option('--settings',
            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.'),
        make_option('--pythonpath',
            help='A directory to add to the Python path, e.g. "/home/djangoprojects/myproject".'),
        make_option('--traceback', action='store_true',
            help='Print traceback on exception'),
    )
    help = ''
    args = ''

    # Configuration shortcuts that alter various logic.
    can_import_settings = True
    requires_model_validation = True
    output_transaction = False # Whether to wrap the output in a "BEGIN; COMMIT;"

    def __init__(self):
        self.style = color_style()

    def get_version(self):
        """
        Return the Django version, which should be correct for all
        built-in Django commands. User-supplied commands should
        override this method.

        """
        return django.get_version()

    def usage(self, subcommand):
        """
        Return a brief description of how to use this command, by
        default from the attribute ``self.help``.

        """
        usage = '%%prog %s [options] %s' % (subcommand, self.args)
        if self.help:
            return '%s\n\n%s' % (usage, self.help)
        else:
            return usage

    def create_parser(self, prog_name, subcommand):
        """
        Create and return the ``OptionParser`` which will be used to
        parse the arguments to this command.

        """
        return OptionParser(prog=prog_name,
                            usage=self.usage(subcommand),
                            version=self.get_version(),
                            option_list=self.option_list)

    def print_help(self, prog_name, subcommand):
        """
        Print the help message for this command, derived from
        ``self.usage()``.

        """
        parser = self.create_parser(prog_name, subcommand)
        parser.print_help()

    def run_from_argv(self, argv):
        """
        Set up any environment changes requested (e.g., Python path
        and Django settings), then run this command.

        """
        parser = self.create_parser(argv[0], argv[1])
        options, args = parser.parse_args(argv[2:])
        handle_default_options(options)
        self.execute(*args, **options.__dict__)

    def execute(self, *args, **options):
        """
        Try to execute this command, performing model validation if
        needed (as controlled by the attribute
        ``self.requires_model_validation``). If the command raises a
        ``CommandError``, intercept it and print it sensibly to
        stderr.

        """
        # Switch to English, because django-admin.py creates database content
        # like permissions, and those shouldn't contain any translations.
        # But only do this if we can assume we have a working settings file,
        # because django.utils.translation requires settings.
        if self.can_import_settings:
            try:
                from django.utils import translation
                translation.activate('en-us')
            except ImportError, e:
                # If settings should be available, but aren't,
                # raise the error and quit.
                sys.stderr.write(self.style.ERROR(str('Error: %s\n' % e)))
                sys.exit(1)
        try:
            if self.requires_model_validation:
                self.validate()
            output = self.handle(*args, **options)
            if output:
                if self.output_transaction:
                    # This needs to be imported here, because it relies on settings.
                    from django.db import connection
                    if connection.ops.start_transaction_sql():
                        print self.style.SQL_KEYWORD(connection.ops.start_transaction_sql())
                print output
                if self.output_transaction:
                    print self.style.SQL_KEYWORD("COMMIT;")
        except CommandError, e:
            sys.stderr.write(self.style.ERROR(str('Error: %s\n' % e)))
            sys.exit(1)

    def validate(self, app=None, display_num_errors=False):
        """
        Validates the given app, raising CommandError for any errors.

        If app is None, then this will validate all installed apps.

        """
        from django.core.management.validation import get_validation_errors
        try:
            from cStringIO import StringIO
        except ImportError:
            from StringIO import StringIO
        s = StringIO()
        num_errors = get_validation_errors(s, app)
        if num_errors:
            s.seek(0)
            error_text = s.read()
            raise CommandError("One or more models did not validate:\n%s" % error_text)
        if display_num_errors:
            print "%s error%s found" % (num_errors, num_errors != 1 and 's' or '')

    def handle(self, *args, **options):
        """
        The actual logic of the command. Subclasses must implement
        this method.

        """
        raise NotImplementedError()

class AppCommand(BaseCommand):
    """
    A management command which takes one or more installed application
    names as arguments, and does something with each of them.

    Rather than implementing ``handle()``, subclasses must implement
    ``handle_app()``, which will be called once for each application.

    """
    args = '<appname appname ...>'

    def handle(self, *app_labels, **options):
        from django.db import models
        if not app_labels:
            raise CommandError('Enter at least one appname.')
        try:
            app_list = [models.get_app(app_label) for app_label in app_labels]
        except (ImproperlyConfigured, ImportError), e:
            raise CommandError("%s. Are you sure your INSTALLED_APPS setting is correct?" % e)
        output = []
        for app in app_list:
            app_output = self.handle_app(app, **options)
            if app_output:
                output.append(app_output)
        return '\n'.join(output)

    def handle_app(self, app, **options):
        """
        Perform the command's actions for ``app``, which will be the
        Python module corresponding to an application name given on
        the command line.

        """
        raise NotImplementedError()

class LabelCommand(BaseCommand):
    """
    A management command which takes one or more arbitrary arguments
    (labels) on the command line, and does something with each of
    them.

    Rather than implementing ``handle()``, subclasses must implement
    ``handle_label()``, which will be called once for each label.

    If the arguments should be names of installed applications, use
    ``AppCommand`` instead.

    """
    args = '<label label ...>'
    label = 'label'

    def handle(self, *labels, **options):
        if not labels:
            raise CommandError('Enter at least one %s.' % self.label)

        output = []
        for label in labels:
            label_output = self.handle_label(label, **options)
            if label_output:
                output.append(label_output)
        return '\n'.join(output)

    def handle_label(self, label, **options):
        """
        Perform the command's actions for ``label``, which will be the
        string as given on the command line.

        """
        raise NotImplementedError()

class NoArgsCommand(BaseCommand):
    """
    A command which takes no arguments on the command line.

    Rather than implementing ``handle()``, subclasses must implement
    ``handle_noargs()``; ``handle()`` itself is overridden to ensure
    no arguments are passed to the command.

    Attempting to pass arguments will raise ``CommandError``.

    """
    args = ''

    def handle(self, *args, **options):
        if args:
            raise CommandError("Command doesn't accept any arguments")
        return self.handle_noargs(**options)

    def handle_noargs(self, **options):
        """
        Perform this command's actions.

        """
        raise NotImplementedError()

def copy_helper(style, app_or_project, name, directory, other_name=''):
    """
    Copies either a Django application layout template or a Django project
    layout template into the specified directory.

    """
    # style -- A color style object (see django.core.management.color).
    # app_or_project -- The string 'app' or 'project'.
    # name -- The name of the application or project.
    # directory -- The directory to which the layout template should be copied.
    # other_name -- When copying an application layout, this should be the name
    #               of the project.
    import re
    import shutil
    other = {'project': 'app', 'app': 'project'}[app_or_project]
    if not re.search(r'^[_a-zA-Z]\w*$', name): # If it's not a valid directory name.
        # Provide a smart error message, depending on the error.
        if not re.search(r'^[_a-zA-Z]', name):
            message = 'make sure the name begins with a letter or underscore'
        else:
            message = 'use only numbers, letters and underscores'
        raise CommandError("%r is not a valid %s name. Please %s." % (name, app_or_project, message))
    top_dir = os.path.join(directory, name)
    try:
        os.mkdir(top_dir)
    except OSError, e:
        raise CommandError(e)

    # Determine where the app or project templates are. Use
    # django.__path__[0] because we don't know into which directory
    # django has been installed.
    template_dir = os.path.join(django.__path__[0], 'conf', '%s_template' % app_or_project)

    for d, subdirs, files in os.walk(template_dir):
        relative_dir = d[len(template_dir)+1:].replace('%s_name' % app_or_project, name)
        if relative_dir:
            os.mkdir(os.path.join(top_dir, relative_dir))
        for i, subdir in enumerate(subdirs):
            if subdir.startswith('.'):
                del subdirs[i]
        for f in files:
            if f.endswith('.pyc'):
                continue
            path_old = os.path.join(d, f)
            path_new = os.path.join(top_dir, relative_dir, f.replace('%s_name' % app_or_project, name))
            fp_old = open(path_old, 'r')
            fp_new = open(path_new, 'w')
            fp_new.write(fp_old.read().replace('{{ %s_name }}' % app_or_project, name).replace('{{ %s_name }}' % other, other_name))
            fp_old.close()
            fp_new.close()
            try:
                shutil.copymode(path_old, path_new)
                _make_writeable(path_new)
            except OSError:
                sys.stderr.write(style.NOTICE("Notice: Couldn't set permission bits on %s. You're probably using an uncommon filesystem setup. No problem.\n" % path_new))

def _make_writeable(filename):
    """
    Make sure that the file is writeable. Useful if our source is
    read-only.

    """
    import stat
    if sys.platform.startswith('java'):
        # On Jython there is no os.access()
        return
    if not os.access(filename, os.W_OK):
        st = os.stat(filename)
        new_permissions = stat.S_IMODE(st.st_mode) | stat.S_IWUSR
        os.chmod(filename, new_permissions)
<commit_msg>Fixed #11621 - don't copy .pyo and .py.class files from example app/project<commit_after>"""
Base classes for writing management commands (named commands which can
be executed through ``django-admin.py`` or ``manage.py``).

"""

import os
import sys
from optparse import make_option, OptionParser

import django
from django.core.exceptions import ImproperlyConfigured
from django.core.management.color import color_style

try:
    set
except NameError:
    from sets import Set as set     # For Python 2.3

class CommandError(Exception):
    """
    Exception class indicating a problem while executing a management
    command.

    If this exception is raised during the execution of a management
    command, it will be caught and turned into a nicely-printed error
    message to the appropriate output stream (i.e., stderr); as a
    result, raising this exception (with a sensible description of the
    error) is the preferred way to indicate that something has gone
    wrong in the execution of a command.

    """
    pass

def handle_default_options(options):
    """
    Include any default options that all commands should accept here
    so that ManagementUtility can handle them before searching for
    user commands.

    """
    if options.settings:
        os.environ['DJANGO_SETTINGS_MODULE'] = options.settings
    if options.pythonpath:
        sys.path.insert(0, options.pythonpath)

class BaseCommand(object):
    """
    The base class from which all management commands ultimately
    derive.

    Use this class if you want access to all of the mechanisms which
    parse the command-line arguments and work out what code to call in
    response; if you don't need to change any of that behavior,
    consider using one of the subclasses defined in this file.

    If you are interested in overriding/customizing various aspects of
    the command-parsing and -execution behavior, the normal flow works
    as follows:

    1. ``django-admin.py`` or ``manage.py`` loads the command class
       and calls its ``run_from_argv()`` method.

    2. The ``run_from_argv()`` method calls ``create_parser()`` to get
       an ``OptionParser`` for the arguments, parses them, performs
       any environment changes requested by options like
       ``pythonpath``, and then calls the ``execute()`` method,
       passing the parsed arguments.

    3. The ``execute()`` method attempts to carry out the command by
       calling the ``handle()`` method with the parsed arguments; any
       output produced by ``handle()`` will be printed to standard
       output and, if the command is intended to produce a block of
       SQL statements, will be wrapped in ``BEGIN`` and ``COMMIT``.

    4. If ``handle()`` raised a ``CommandError``, ``execute()`` will
       instead print an error message to ``stderr``.

    Thus, the ``handle()`` method is typically the starting point for
    subclasses; many built-in commands and command types either place
    all of their logic in ``handle()``, or perform some additional
    parsing work in ``handle()`` and then delegate from it to more
    specialized methods as needed.

    Several attributes affect behavior at various steps along the way:

    ``args``
        A string listing the arguments accepted by the command,
        suitable for use in help messages; e.g., a command which takes
        a list of application names might set this to '<appname
        appname ...>'.

    ``can_import_settings``
        A boolean indicating whether the command needs to be able to
        import Django settings; if ``True``, ``execute()`` will verify
        that this is possible before proceeding. Default value is
        ``True``.

    ``help``
        A short description of the command, which will be printed in
        help messages.

    ``option_list``
        This is the list of ``optparse`` options which will be fed
        into the command's ``OptionParser`` for parsing arguments.

    ``output_transaction``
        A boolean indicating whether the command outputs SQL
        statements; if ``True``, the output will automatically be
        wrapped with ``BEGIN;`` and ``COMMIT;``. Default value is
        ``False``.

    ``requires_model_validation``
        A boolean; if ``True``, validation of installed models will be
        performed prior to executing the command. Default value is
        ``True``. To validate an individual application's models
        rather than all applications' models, call
        ``self.validate(app)`` from ``handle()``, where ``app`` is the
        application's Python module.

    """
    # Metadata about this command.
    option_list = (
        make_option('-v', '--verbosity', action='store', dest='verbosity', default='1',
            type='choice', choices=['0', '1', '2'],
            help='Verbosity level; 0=minimal output, 1=normal output, 2=all output'),
        make_option('--settings',
            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.'),
        make_option('--pythonpath',
            help='A directory to add to the Python path, e.g. "/home/djangoprojects/myproject".'),
        make_option('--traceback', action='store_true',
            help='Print traceback on exception'),
    )
    help = ''
    args = ''

    # Configuration shortcuts that alter various logic.
    can_import_settings = True
    requires_model_validation = True
    output_transaction = False # Whether to wrap the output in a "BEGIN; COMMIT;"

    def __init__(self):
        self.style = color_style()

    def get_version(self):
        """
        Return the Django version, which should be correct for all
        built-in Django commands. User-supplied commands should
        override this method.

        """
        return django.get_version()

    def usage(self, subcommand):
        """
        Return a brief description of how to use this command, by
        default from the attribute ``self.help``.

        """
        usage = '%%prog %s [options] %s' % (subcommand, self.args)
        if self.help:
            return '%s\n\n%s' % (usage, self.help)
        else:
            return usage

    def create_parser(self, prog_name, subcommand):
        """
        Create and return the ``OptionParser`` which will be used to
        parse the arguments to this command.

        """
        return OptionParser(prog=prog_name,
                            usage=self.usage(subcommand),
                            version=self.get_version(),
                            option_list=self.option_list)

    def print_help(self, prog_name, subcommand):
        """
        Print the help message for this command, derived from
        ``self.usage()``.

        """
        parser = self.create_parser(prog_name, subcommand)
        parser.print_help()

    def run_from_argv(self, argv):
        """
        Set up any environment changes requested (e.g., Python path
        and Django settings), then run this command.

        """
        parser = self.create_parser(argv[0], argv[1])
        options, args = parser.parse_args(argv[2:])
        handle_default_options(options)
        self.execute(*args, **options.__dict__)

    def execute(self, *args, **options):
        """
        Try to execute this command, performing model validation if
        needed (as controlled by the attribute
        ``self.requires_model_validation``). If the command raises a
        ``CommandError``, intercept it and print it sensibly to
        stderr.

        """
        # Switch to English, because django-admin.py creates database content
        # like permissions, and those shouldn't contain any translations.
        # But only do this if we can assume we have a working settings file,
        # because django.utils.translation requires settings.
        if self.can_import_settings:
            try:
                from django.utils import translation
                translation.activate('en-us')
            except ImportError, e:
                # If settings should be available, but aren't,
                # raise the error and quit.
                sys.stderr.write(self.style.ERROR(str('Error: %s\n' % e)))
                sys.exit(1)
        try:
            if self.requires_model_validation:
                self.validate()
            output = self.handle(*args, **options)
            if output:
                if self.output_transaction:
                    # This needs to be imported here, because it relies on settings.
                    from django.db import connection
                    if connection.ops.start_transaction_sql():
                        print self.style.SQL_KEYWORD(connection.ops.start_transaction_sql())
                print output
                if self.output_transaction:
                    print self.style.SQL_KEYWORD("COMMIT;")
        except CommandError, e:
            sys.stderr.write(self.style.ERROR(str('Error: %s\n' % e)))
            sys.exit(1)

    def validate(self, app=None, display_num_errors=False):
        """
        Validates the given app, raising CommandError for any errors.

        If app is None, then this will validate all installed apps.

        """
        from django.core.management.validation import get_validation_errors
        try:
            from cStringIO import StringIO
        except ImportError:
            from StringIO import StringIO
        s = StringIO()
        num_errors = get_validation_errors(s, app)
        if num_errors:
            s.seek(0)
            error_text = s.read()
            raise CommandError("One or more models did not validate:\n%s" % error_text)
        if display_num_errors:
            print "%s error%s found" % (num_errors, num_errors != 1 and 's' or '')

    def handle(self, *args, **options):
        """
        The actual logic of the command. Subclasses must implement
        this method.

        """
        raise NotImplementedError()

class AppCommand(BaseCommand):
    """
    A management command which takes one or more installed application
    names as arguments, and does something with each of them.

    Rather than implementing ``handle()``, subclasses must implement
    ``handle_app()``, which will be called once for each application.

    """
    args = '<appname appname ...>'

    def handle(self, *app_labels, **options):
        from django.db import models
        if not app_labels:
            raise CommandError('Enter at least one appname.')
        try:
            app_list = [models.get_app(app_label) for app_label in app_labels]
        except (ImproperlyConfigured, ImportError), e:
            raise CommandError("%s. Are you sure your INSTALLED_APPS setting is correct?" % e)
        output = []
        for app in app_list:
            app_output = self.handle_app(app, **options)
            if app_output:
                output.append(app_output)
        return '\n'.join(output)

    def handle_app(self, app, **options):
        """
        Perform the command's actions for ``app``, which will be the
        Python module corresponding to an application name given on
        the command line.

        """
        raise NotImplementedError()

class LabelCommand(BaseCommand):
    """
    A management command which takes one or more arbitrary arguments
    (labels) on the command line, and does something with each of
    them.

    Rather than implementing ``handle()``, subclasses must implement
    ``handle_label()``, which will be called once for each label.

    If the arguments should be names of installed applications, use
    ``AppCommand`` instead.

    """
    args = '<label label ...>'
    label = 'label'

    def handle(self, *labels, **options):
        if not labels:
            raise CommandError('Enter at least one %s.' % self.label)

        output = []
        for label in labels:
            label_output = self.handle_label(label, **options)
            if label_output:
                output.append(label_output)
        return '\n'.join(output)

    def handle_label(self, label, **options):
        """
        Perform the command's actions for ``label``, which will be the
        string as given on the command line.

        """
        raise NotImplementedError()

class NoArgsCommand(BaseCommand):
    """
    A command which takes no arguments on the command line.

    Rather than implementing ``handle()``, subclasses must implement
    ``handle_noargs()``; ``handle()`` itself is overridden to ensure
    no arguments are passed to the command.

    Attempting to pass arguments will raise ``CommandError``.

    """
    args = ''

    def handle(self, *args, **options):
        if args:
            raise CommandError("Command doesn't accept any arguments")
        return self.handle_noargs(**options)

    def handle_noargs(self, **options):
        """
        Perform this command's actions.

        """
        raise NotImplementedError()

def copy_helper(style, app_or_project, name, directory, other_name=''):
    """
    Copies either a Django application layout template or a Django project
    layout template into the specified directory.

    """
    # style -- A color style object (see django.core.management.color).
    # app_or_project -- The string 'app' or 'project'.
    # name -- The name of the application or project.
    # directory -- The directory to which the layout template should be copied.
    # other_name -- When copying an application layout, this should be the name
    #               of the project.
    import re
    import shutil
    other = {'project': 'app', 'app': 'project'}[app_or_project]
    if not re.search(r'^[_a-zA-Z]\w*$', name): # If it's not a valid directory name.
        # Provide a smart error message, depending on the error.
        if not re.search(r'^[_a-zA-Z]', name):
            message = 'make sure the name begins with a letter or underscore'
        else:
            message = 'use only numbers, letters and underscores'
        raise CommandError("%r is not a valid %s name. Please %s." % (name, app_or_project, message))
    top_dir = os.path.join(directory, name)
    try:
        os.mkdir(top_dir)
    except OSError, e:
        raise CommandError(e)

    # Determine where the app or project templates are. Use
    # django.__path__[0] because we don't know into which directory
    # django has been installed.
    template_dir = os.path.join(django.__path__[0], 'conf', '%s_template' % app_or_project)

    for d, subdirs, files in os.walk(template_dir):
        relative_dir = d[len(template_dir)+1:].replace('%s_name' % app_or_project, name)
        if relative_dir:
            os.mkdir(os.path.join(top_dir, relative_dir))
        for i, subdir in enumerate(subdirs):
            if subdir.startswith('.'):
                del subdirs[i]
        for f in files:
            if not f.endswith('.py'):
                # Ignore .pyc, .pyo, .py.class etc, as they cause various
                # breakages.
                continue
            path_old = os.path.join(d, f)
            path_new = os.path.join(top_dir, relative_dir, f.replace('%s_name' % app_or_project, name))
            fp_old = open(path_old, 'r')
            fp_new = open(path_new, 'w')
            fp_new.write(fp_old.read().replace('{{ %s_name }}' % app_or_project, name).replace('{{ %s_name }}' % other, other_name))
            fp_old.close()
            fp_new.close()
            try:
                shutil.copymode(path_old, path_new)
                _make_writeable(path_new)
            except OSError:
                sys.stderr.write(style.NOTICE("Notice: Couldn't set permission bits on %s. You're probably using an uncommon filesystem setup. No problem.\n" % path_new))

def _make_writeable(filename):
    """
    Make sure that the file is writeable. Useful if our source is
    read-only.

    """
    import stat
    if sys.platform.startswith('java'):
        # On Jython there is no os.access()
        return
    if not os.access(filename, os.W_OK):
        st = os.stat(filename)
        new_permissions = stat.S_IMODE(st.st_mode) | stat.S_IWUSR
        os.chmod(filename, new_permissions)
<|endoftext|>


<commit_before># Copyright 2012 Google Inc. All Rights Reserved.

"""Management shell 'build' command.
"""

__author__ = 'benvanik@google.com (Ben Vanik)'

import argparse
import os
import sys

from build.context import BuildEnvironment, BuildContext
from build.manage import manage_command
from build.project import FileModuleResolver, Project
from build.task import InProcessTaskExecutor, MultiProcessTaskExecutor

def _get_options_parser():
  """Gets an options parser for the given args."""
  parser = argparse.ArgumentParser(prog='manage.py build')
  parser.add_argument('targets',
                      nargs='+',
                      metavar='target',
                      help='Target build rule (such as :a or foo/bar:a)')
  return parser

@manage_command('build')
def build(args, cwd):
  parser = _get_options_parser()
  parsed_args = parser.parse_args(args)

  build_env = BuildEnvironment(root_path=cwd)

  module_resolver = FileModuleResolver(cwd)
  project = Project(module_resolver=module_resolver)

  # TODO(benvanik): -j
  task_executor = InProcessTaskExecutor()
  #task_executor = MultiProcessTaskExecutor(worker_count=None)

  # TODO(benvanik): good logging/info - resolve rules in project and print
  #     info?
  print 'building %s' % (parsed_args.targets)

  # TODO(benvanik): take additional args from command line
  with BuildContext(build_env, project,
                    task_executor=task_executor,
                    force=False,
                    stop_on_error=False,
                    raise_on_error=False) as build_ctx:
    result = build_ctx.execute_sync(parsed_args.targets)

  return result == True
<commit_msg>Adding -j<commit_after># Copyright 2012 Google Inc. All Rights Reserved.

"""Management shell 'build' command.
"""

__author__ = 'benvanik@google.com (Ben Vanik)'

import argparse
import os
import sys

from build.context import BuildEnvironment, BuildContext
from build.manage import manage_command
from build.project import FileModuleResolver, Project
from build.task import InProcessTaskExecutor, MultiProcessTaskExecutor

def _get_options_parser():
  """Gets an options parser for the given args."""
  parser = argparse.ArgumentParser(prog='manage.py build')

  # Threading/execution control
  parser.add_argument('-j', '--jobs',
                      dest='jobs',
                      type=int,
                      default=None,
                      help=('Specifies the number of tasks to run '
                            'simultaneously. If omitted then all processors '
                            'will be used.'))

  # 'build' specific
  parser.add_argument('targets',
                      nargs='+',
                      metavar='target',
                      help='Target build rule (such as :a or foo/bar:a)')

  return parser

@manage_command('build')
def build(args, cwd):
  parser = _get_options_parser()
  parsed_args = parser.parse_args(args)

  build_env = BuildEnvironment(root_path=cwd)

  module_resolver = FileModuleResolver(cwd)
  project = Project(module_resolver=module_resolver)

  # -j/--jobs switch to change execution mode
  # TODO(benvanik): force -j 1 on Cygwin?
  if parsed_args.jobs == 1:
    task_executor = InProcessTaskExecutor()
  else:
    task_executor = MultiProcessTaskExecutor(worker_count=parsed_args.jobs)

  # TODO(benvanik): good logging/info - resolve rules in project and print
  #     info?
  print 'building %s' % (parsed_args.targets)

  # TODO(benvanik): take additional args from command line
  with BuildContext(build_env, project,
                    task_executor=task_executor,
                    force=False,
                    stop_on_error=False,
                    raise_on_error=False) as build_ctx:
    result = build_ctx.execute_sync(parsed_args.targets)

  return result == True
<|endoftext|>


<commit_before>import datetime

from django.db import models
from django.contrib.contenttypes import generic
from django.utils.translation import ugettext_lazy as _
from django.contrib.sites.models import Site
from django.core.exceptions import ValidationError

from filebrowser.fields import FileBrowseField

from tagging.models import TaggedItem

from credit.models import OrderedCredit
from credit.utils import credit_list, credit_length
from enhancedtext.fields import EnhancedTextField

from copyright.models import Copyright

MONTH_CHOICES = (
    ('01', _('January'),),
    ('02', _('February'),),
    ('03', _('March'),),
    ('04', _('April'),),
    ('05', _('May'),),
    ('06', _('June'),),
    ('07', _('July'),),
    ('08', _('August'),),
    ('09', _('September'),),
    ('10', _('October'),),
    ('11', _('November'),),
    ('12', _('December'),),
)

CITATION_FORMATS = (
    ('DEF', _('Default'),),
)

class Document(models.Model):
    title = models.CharField(max_length=200)
    file = FileBrowseField(max_length=200, directory="documents/", blank=True, null=True)
    url = models.URLField(blank=True,
            verify_exists=False,
            verbose_name='External URL',
            help_text= _('Use this field as an alternative to uploading a file'))
    content = EnhancedTextField(blank=True,
            help_text = _('Use this field as an alternative to uploading a file or specifying a URL.'),
            default=("\W"))
    description = EnhancedTextField(blank=True,
            help_text = _('Describe the document.'),
            default=("\W"))

    source = models.CharField(max_length=200, blank=True)
    publisher = models.CharField(max_length=200, blank=True)

    year_published = models.PositiveSmallIntegerField(blank=True, null=True)
    month_published = models.CharField(blank=True, max_length=2, choices=MONTH_CHOICES)
    day_published = models.PositiveSmallIntegerField(blank=True, null=True)

    recommended_citation = models.CharField(max_length=300, blank=True,
            help_text=_("Leave blank for system to automatically generate a citation."))
    citation_format = models.CharField(max_length=3, choices=CITATION_FORMATS,
                                       default='DEF')

    pmid = models.IntegerField(blank=True, null=True,
            help_text=_("Enter a Public Library of Medicine identifier if there is one."))
    doi = models.CharField(max_length=50, blank=True,
            help_text=_("Enter a Digital Object Identifier if there is one. E.g. 10.1021/ac0354342"))
    credits = generic.GenericRelation(OrderedCredit, verbose_name=_('credit',),
                                      blank=True, null=True)
    copyright = models.ForeignKey(Copyright, blank=True, null=True)
    tags = generic.GenericRelation(TaggedItem, verbose_name=_('tags'),
                                      blank=True, null=True)
    last_modified = models.DateTimeField(auto_now=True, editable=False)
    date_added = models.DateTimeField(auto_now_add=True, editable=False)

    def describe(self):
        return self.description

    def get_count_authors(self):
        return credit_length(self.credits)

    def get_authors(self):
        return credit_list(self.credits)

    def get_date_published(self):
        if not self.year_published:
            return ""

        date_published= unicode(abs(self.year_published))

        if self.month_published:
            date_published += u' ' + self.get_month_published_display()

            if self.day_published:
                date_published += u' ' + unicode(self.day_published)

        return date_published

    def get_citation(self):
        """Generates a citation for the document.

        Currently only default citation is implemented.
        """
        if self.recommended_citation:
            return self.recommended_citation

        citation = ""

        if self.citation_format == 'DEF':

            # Authors, title, date, source, PMID, DOI, URL
            authors = self.get_authors()
            if authors:
                citation += self.get_authors() + u'. '

            citation += self.title + u'. '

            date_published = self.get_date_published()

            if date_published:
                citation += date_published + u'. '

            if self.source:
                citation += self.source + u'. '
            if self.publisher:
                citation += self.publisher + u'. '

            if self.pmid:
                citation += 'PMID: ' + unicode(self.pmid) + '. '

            if self.doi:
                citation += 'DOI:' + self.doi + '. '

            if self.url:
                citation += self.url + u'. '
            elif self.file:
                citation += "http://" + unicode(Site.objects.get_current()) + '/static/' + unicode(self.file)
            else:
                citation += "http://" + unicode(Site.objects.get_current()) + self.get_absolute_url()

        return citation

    def clean(self):
        '''Validates the year/month/day combination is valid. Users can omit all
        three, but if they enter a month, they must enter a year and if they
        enter a day, they must enter a month.
        '''

        # Don't allow draft entries to have a pub_date.
        if self.year_published:
            year = self.year_published
            if self.month_published:
                month = int(self.month_published)
            elif self.day_published:
                raise ValidationError(_('You must enter a month if you enter a day'))
            else:
                month = 1 # For purposes of validating the year
            if self.day_published:
                day = self.day_published
            else:
                day = 1 # For purposes of validating the year/month combination
            try:
                datetime.date(year,month,day)
            except (TypeError, ValueError):
                raise ValidationError(_('The date is invalid'))
        elif self.month_published or self.day_published:
            raise ValidationError(_('You must enter a year if you enter a month or day'))

    @models.permalink
    def get_absolute_url(self):
        return ('document-detail', [str(self.id)])

    def __unicode__(self):
        return self.title

    class Meta:
        verbose_name = _('document')
        verbose_name_plural = _('documents')
        ordering = ['-year_published','-month_published', '-day_published']

class Catalogue(models.Model):
    title = models.CharField(max_length=200)
    description = EnhancedTextField(blank=True, default="\W")
    documents = models.ManyToManyField(Document, blank=True, null=True,
                help_text=_('Documents in this archive.'))
    tags = generic.GenericRelation(TaggedItem, verbose_name=_('tags'),
                                      blank=True, null=True)
    copyright = models.ForeignKey(Copyright, blank=True, null=True)
    last_modified = models.DateTimeField(auto_now=True, editable=False)
    date_added = models.DateTimeField(auto_now_add=True, editable=False)

    def describe(self):
        return self.description

    @models.permalink
    def get_absolute_url(self):
        return ('calalogue_view', [str(self.id)])

    def __unicode__(self):
        return self.title

    class Meta:
        verbose_name = _('catalogue')
        verbose_name_plural = _('catalogues')
        ordering = ['title',]

    <commit_msg>Fixed issue with wrong citation url<commit_after>import datetime

from django.db import models
from django.contrib.contenttypes import generic
from django.utils.translation import ugettext_lazy as _
from django.contrib.sites.models import Site
from django.core.exceptions import ValidationError

from filebrowser.fields import FileBrowseField

from tagging.models import TaggedItem

from credit.models import OrderedCredit
from credit.utils import credit_list, credit_length
from enhancedtext.fields import EnhancedTextField

from copyright.models import Copyright

MONTH_CHOICES = (
    ('01', _('January'),),
    ('02', _('February'),),
    ('03', _('March'),),
    ('04', _('April'),),
    ('05', _('May'),),
    ('06', _('June'),),
    ('07', _('July'),),
    ('08', _('August'),),
    ('09', _('September'),),
    ('10', _('October'),),
    ('11', _('November'),),
    ('12', _('December'),),
)

CITATION_FORMATS = (
    ('DEF', _('Default'),),
)

class Document(models.Model):
    title = models.CharField(max_length=200)
    file = FileBrowseField(max_length=200, directory="documents/", blank=True, null=True)
    url = models.URLField(blank=True,
            verify_exists=False,
            verbose_name='External URL',
            help_text= _('Use this field as an alternative to uploading a file'))
    content = EnhancedTextField(blank=True,
            help_text = _('Use this field as an alternative to uploading a file or specifying a URL.'),
            default=("\W"))
    description = EnhancedTextField(blank=True,
            help_text = _('Describe the document.'),
            default=("\W"))

    source = models.CharField(max_length=200, blank=True)
    publisher = models.CharField(max_length=200, blank=True)

    year_published = models.PositiveSmallIntegerField(blank=True, null=True)
    month_published = models.CharField(blank=True, max_length=2, choices=MONTH_CHOICES)
    day_published = models.PositiveSmallIntegerField(blank=True, null=True)

    recommended_citation = models.CharField(max_length=300, blank=True,
            help_text=_("Leave blank for system to automatically generate a citation."))
    citation_format = models.CharField(max_length=3, choices=CITATION_FORMATS,
                                       default='DEF')

    pmid = models.IntegerField(blank=True, null=True,
            help_text=_("Enter a Public Library of Medicine identifier if there is one."))
    doi = models.CharField(max_length=50, blank=True,
            help_text=_("Enter a Digital Object Identifier if there is one. E.g. 10.1021/ac0354342"))
    credits = generic.GenericRelation(OrderedCredit, verbose_name=_('credit',),
                                      blank=True, null=True)
    copyright = models.ForeignKey(Copyright, blank=True, null=True)
    tags = generic.GenericRelation(TaggedItem, verbose_name=_('tags'),
                                      blank=True, null=True)
    last_modified = models.DateTimeField(auto_now=True, editable=False)
    date_added = models.DateTimeField(auto_now_add=True, editable=False)

    def describe(self):
        return self.description

    def get_count_authors(self):
        return credit_length(self.credits)

    def get_authors(self):
        return credit_list(self.credits)

    def get_date_published(self):
        if not self.year_published:
            return ""

        date_published= unicode(abs(self.year_published))

        if self.month_published:
            date_published += u' ' + self.get_month_published_display()

            if self.day_published:
                date_published += u' ' + unicode(self.day_published)

        return date_published

    def get_citation(self):
        """Generates a citation for the document.

        Currently only default citation is implemented.
        """
        if self.recommended_citation:
            return self.recommended_citation

        citation = ""

        if self.citation_format == 'DEF':

            # Authors, title, date, source, PMID, DOI, URL
            authors = self.get_authors()
            if authors:
                citation += self.get_authors() + u'. '

            citation += self.title + u'. '

            date_published = self.get_date_published()

            if date_published:
                citation += date_published + u'. '

            if self.source:
                citation += self.source + u'. '
            if self.publisher:
                citation += self.publisher + u'. '

            if self.pmid:
                citation += 'PMID: ' + unicode(self.pmid) + '. '

            if self.doi:
                citation += 'DOI:' + self.doi + '. '

            if self.url:
                citation += self.url + u'. '
            elif self.file:
                citation += "http://" + unicode(Site.objects.get_current()) + '/media/' + unicode(self.file)
            else:
                citation += "http://" + unicode(Site.objects.get_current()) + self.get_absolute_url()

        return citation

    def clean(self):
        '''Validates the year/month/day combination is valid. Users can omit all
        three, but if they enter a month, they must enter a year and if they
        enter a day, they must enter a month.
        '''

        # Don't allow draft entries to have a pub_date.
        if self.year_published:
            year = self.year_published
            if self.month_published:
                month = int(self.month_published)
            elif self.day_published:
                raise ValidationError(_('You must enter a month if you enter a day'))
            else:
                month = 1 # For purposes of validating the year
            if self.day_published:
                day = self.day_published
            else:
                day = 1 # For purposes of validating the year/month combination
            try:
                datetime.date(year,month,day)
            except (TypeError, ValueError):
                raise ValidationError(_('The date is invalid'))
        elif self.month_published or self.day_published:
            raise ValidationError(_('You must enter a year if you enter a month or day'))

    @models.permalink
    def get_absolute_url(self):
        return ('document-detail', [str(self.id)])

    def __unicode__(self):
        return self.title

    class Meta:
        verbose_name = _('document')
        verbose_name_plural = _('documents')
        ordering = ['-year_published','-month_published', '-day_published']

class Catalogue(models.Model):
    title = models.CharField(max_length=200)
    description = EnhancedTextField(blank=True, default="\W")
    documents = models.ManyToManyField(Document, blank=True, null=True,
                help_text=_('Documents in this archive.'))
    tags = generic.GenericRelation(TaggedItem, verbose_name=_('tags'),
                                      blank=True, null=True)
    copyright = models.ForeignKey(Copyright, blank=True, null=True)
    last_modified = models.DateTimeField(auto_now=True, editable=False)
    date_added = models.DateTimeField(auto_now_add=True, editable=False)

    def describe(self):
        return self.description

    @models.permalink
    def get_absolute_url(self):
        return ('calalogue_view', [str(self.id)])

    def __unicode__(self):
        return self.title

    class Meta:
        verbose_name = _('catalogue')
        verbose_name_plural = _('catalogues')
        ordering = ['title',]

    <|endoftext|>


<commit_before>import os
import sys
from optparse import make_option, OptionParser

import django
from django.core.exceptions import ImproperlyConfigured
from django.core.management.color import color_style

class CommandError(Exception):
    pass

def handle_default_options(options):
    """
    Include any default options that all commands should accept
    here so that ManagementUtility can handle them before searching
    for user commands.
    """
    if options.settings:
        os.environ['DJANGO_SETTINGS_MODULE'] = options.settings
    if options.pythonpath:
        sys.path.insert(0, options.pythonpath)

class BaseCommand(object):
    # Metadata about this command.
    option_list = (
        make_option('--settings',
            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.'),
        make_option('--pythonpath',
            help='A directory to add to the Python path, e.g. "/home/djangoprojects/myproject".'),
    )
    help = ''
    args = ''

    # Configuration shortcuts that alter various logic.
    can_import_settings = True
    requires_model_validation = True
    output_transaction = False # Whether to wrap the output in a "BEGIN; COMMIT;"

    def __init__(self):
        self.style = color_style()

    def get_version(self):
        """
        Returns the Django version, which should be correct for all built-in
        Django commands. User-supplied commands should override this method.
        """
        return django.get_version()

    def usage(self, subcommand):
        usage = '%%prog %s [options] %s' % (subcommand, self.args)
        if self.help:
            return '%s\n\n%s' % (usage, self.help)
        else:
            return usage

    def create_parser(self, prog_name, subcommand):
        return OptionParser(prog=prog_name,
                            usage=self.usage(subcommand),
                            version=self.get_version(),
                            option_list=self.option_list)

    def print_help(self, prog_name, subcommand):
        parser = self.create_parser(prog_name, subcommand)
        parser.print_help()

    def run_from_argv(self, argv):
        parser = self.create_parser(argv[0], argv[1])
        options, args = parser.parse_args(argv[2:])
        handle_default_options(options)
        self.execute(*args, **options.__dict__)

    def execute(self, *args, **options):
        # Switch to English, because django-admin.py creates database content
        # like permissions, and those shouldn't contain any translations.
        # But only do this if we can assume we have a working settings file,
        # because django.utils.translation requires settings.
        if self.can_import_settings:
            from django.utils import translation
            translation.activate('en-us')

        try:
            if self.requires_model_validation:
                self.validate()
            output = self.handle(*args, **options)
            if output:
                if self.output_transaction:
                    # This needs to be imported here, because it relies on settings.
                    from django.db import connection
                    if connection.ops.start_transaction_sql():
                        print self.style.SQL_KEYWORD(connection.ops.start_transaction_sql())
                print output
                if self.output_transaction:
                    print self.style.SQL_KEYWORD("COMMIT;")
        except CommandError, e:
            sys.stderr.write(self.style.ERROR(str('Error: %s\n' % e)))
            sys.exit(1)

    def validate(self, app=None, display_num_errors=False):
        """
        Validates the given app, raising CommandError for any errors.

        If app is None, then this will validate all installed apps.
        """
        from django.core.management.validation import get_validation_errors
        try:
            from cStringIO import StringIO
        except ImportError:
            from StringIO import StringIO
        s = StringIO()
        num_errors = get_validation_errors(s, app)
        if num_errors:
            s.seek(0)
            error_text = s.read()
            raise CommandError("One or more models did not validate:\n%s" % error_text)
        if display_num_errors:
            print "%s error%s found" % (num_errors, num_errors != 1 and 's' or '')

    def handle(self, *args, **options):
        raise NotImplementedError()

class AppCommand(BaseCommand):
    args = '<appname appname ...>'

    def handle(self, *app_labels, **options):
        from django.db import models
        if not app_labels:
            raise CommandError('Enter at least one appname.')
        try:
            app_list = [models.get_app(app_label) for app_label in app_labels]
        except (ImproperlyConfigured, ImportError), e:
            raise CommandError("%s. Are you sure your INSTALLED_APPS setting is correct?" % e)
        output = []
        for app in app_list:
            app_output = self.handle_app(app, **options)
            if app_output:
                output.append(app_output)
        return '\n'.join(output)

    def handle_app(self, app, **options):
        raise NotImplementedError()

class LabelCommand(BaseCommand):
    args = '<label label ...>'
    label = 'label'

    def handle(self, *labels, **options):
        if not labels:
            raise CommandError('Enter at least one %s.' % self.label)

        output = []
        for label in labels:
            label_output = self.handle_label(label, **options)
            if label_output:
                output.append(label_output)
        return '\n'.join(output)

    def handle_label(self, label, **options):
        raise NotImplementedError()

class NoArgsCommand(BaseCommand):
    args = ''

    def handle(self, *args, **options):
        from django.db import models
        if len(args) != 0:
            raise CommandError("Command doesn't accept any arguments")

        return self.handle_noargs(**options)

    def handle_noargs(self, **options):
        raise NotImplementedError()

def copy_helper(style, app_or_project, name, directory, other_name=''):
    """
    Copies either a Django application layout template or a Django project
    layout template into the specified directory.

    * style - A color style object (see django.core.management.color).
    * app_or_project - The string 'app' or 'project'.
    * name - The name of the application or project.
    * directory - The directory to copy the layout template to.
    * other_name - When copying an application layout, this should be the name
                   of the project.
    """
    import django
    import re
    import shutil
    other = {'project': 'app', 'app': 'project'}[app_or_project]
    if not re.search(r'^\w+$', name): # If it's not a valid directory name.
        raise CommandError("%r is not a valid %s name. Please use only numbers, letters and underscores." % (name, app_or_project))
    top_dir = os.path.join(directory, name)
    try:
        os.mkdir(top_dir)
    except OSError, e:
        raise CommandError(e)

    # Determine where the app or project templates are. Use
    # django.__path__[0] because we don't know into which directory
    # django has been installed.
    template_dir = os.path.join(django.__path__[0], 'conf', '%s_template' % app_or_project)

    for d, subdirs, files in os.walk(template_dir):
        relative_dir = d[len(template_dir)+1:].replace('%s_name' % app_or_project, name)
        if relative_dir:
            os.mkdir(os.path.join(top_dir, relative_dir))
        for i, subdir in enumerate(subdirs):
            if subdir.startswith('.'):
                del subdirs[i]
        for f in files:
            if f.endswith('.pyc'):
                continue
            path_old = os.path.join(d, f)
            path_new = os.path.join(top_dir, relative_dir, f.replace('%s_name' % app_or_project, name))
            fp_old = open(path_old, 'r')
            fp_new = open(path_new, 'w')
            fp_new.write(fp_old.read().replace('{{ %s_name }}' % app_or_project, name).replace('{{ %s_name }}' % other, other_name))
            fp_old.close()
            fp_new.close()
            try:
                shutil.copymode(path_old, path_new)
                _make_writeable(path_new)
            except OSError:
                sys.stderr.write(style.NOTICE("Notice: Couldn't set permission bits on %s. You're probably using an uncommon filesystem setup. No problem.\n" % path_new))

def _make_writeable(filename):
    "Makes sure that the file is writeable. Useful if our source is read-only."
    import stat
    if sys.platform.startswith('java'):
        # On Jython there is no os.access()
        return
    if not os.access(filename, os.W_OK):
        st = os.stat(filename)
        new_permissions = stat.S_IMODE(st.st_mode) | stat.S_IWUSR
        os.chmod(filename, new_permissions)
<commit_msg>Removed an unused import and a duplicate import.<commit_after>import os
import sys
from optparse import make_option, OptionParser

import django
from django.core.exceptions import ImproperlyConfigured
from django.core.management.color import color_style

class CommandError(Exception):
    pass

def handle_default_options(options):
    """
    Include any default options that all commands should accept
    here so that ManagementUtility can handle them before searching
    for user commands.
    """
    if options.settings:
        os.environ['DJANGO_SETTINGS_MODULE'] = options.settings
    if options.pythonpath:
        sys.path.insert(0, options.pythonpath)

class BaseCommand(object):
    # Metadata about this command.
    option_list = (
        make_option('--settings',
            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.'),
        make_option('--pythonpath',
            help='A directory to add to the Python path, e.g. "/home/djangoprojects/myproject".'),
    )
    help = ''
    args = ''

    # Configuration shortcuts that alter various logic.
    can_import_settings = True
    requires_model_validation = True
    output_transaction = False # Whether to wrap the output in a "BEGIN; COMMIT;"

    def __init__(self):
        self.style = color_style()

    def get_version(self):
        """
        Returns the Django version, which should be correct for all built-in
        Django commands. User-supplied commands should override this method.
        """
        return django.get_version()

    def usage(self, subcommand):
        usage = '%%prog %s [options] %s' % (subcommand, self.args)
        if self.help:
            return '%s\n\n%s' % (usage, self.help)
        else:
            return usage

    def create_parser(self, prog_name, subcommand):
        return OptionParser(prog=prog_name,
                            usage=self.usage(subcommand),
                            version=self.get_version(),
                            option_list=self.option_list)

    def print_help(self, prog_name, subcommand):
        parser = self.create_parser(prog_name, subcommand)
        parser.print_help()

    def run_from_argv(self, argv):
        parser = self.create_parser(argv[0], argv[1])
        options, args = parser.parse_args(argv[2:])
        handle_default_options(options)
        self.execute(*args, **options.__dict__)

    def execute(self, *args, **options):
        # Switch to English, because django-admin.py creates database content
        # like permissions, and those shouldn't contain any translations.
        # But only do this if we can assume we have a working settings file,
        # because django.utils.translation requires settings.
        if self.can_import_settings:
            from django.utils import translation
            translation.activate('en-us')

        try:
            if self.requires_model_validation:
                self.validate()
            output = self.handle(*args, **options)
            if output:
                if self.output_transaction:
                    # This needs to be imported here, because it relies on settings.
                    from django.db import connection
                    if connection.ops.start_transaction_sql():
                        print self.style.SQL_KEYWORD(connection.ops.start_transaction_sql())
                print output
                if self.output_transaction:
                    print self.style.SQL_KEYWORD("COMMIT;")
        except CommandError, e:
            sys.stderr.write(self.style.ERROR(str('Error: %s\n' % e)))
            sys.exit(1)

    def validate(self, app=None, display_num_errors=False):
        """
        Validates the given app, raising CommandError for any errors.

        If app is None, then this will validate all installed apps.
        """
        from django.core.management.validation import get_validation_errors
        try:
            from cStringIO import StringIO
        except ImportError:
            from StringIO import StringIO
        s = StringIO()
        num_errors = get_validation_errors(s, app)
        if num_errors:
            s.seek(0)
            error_text = s.read()
            raise CommandError("One or more models did not validate:\n%s" % error_text)
        if display_num_errors:
            print "%s error%s found" % (num_errors, num_errors != 1 and 's' or '')

    def handle(self, *args, **options):
        raise NotImplementedError()

class AppCommand(BaseCommand):
    args = '<appname appname ...>'

    def handle(self, *app_labels, **options):
        from django.db import models
        if not app_labels:
            raise CommandError('Enter at least one appname.')
        try:
            app_list = [models.get_app(app_label) for app_label in app_labels]
        except (ImproperlyConfigured, ImportError), e:
            raise CommandError("%s. Are you sure your INSTALLED_APPS setting is correct?" % e)
        output = []
        for app in app_list:
            app_output = self.handle_app(app, **options)
            if app_output:
                output.append(app_output)
        return '\n'.join(output)

    def handle_app(self, app, **options):
        raise NotImplementedError()

class LabelCommand(BaseCommand):
    args = '<label label ...>'
    label = 'label'

    def handle(self, *labels, **options):
        if not labels:
            raise CommandError('Enter at least one %s.' % self.label)

        output = []
        for label in labels:
            label_output = self.handle_label(label, **options)
            if label_output:
                output.append(label_output)
        return '\n'.join(output)

    def handle_label(self, label, **options):
        raise NotImplementedError()

class NoArgsCommand(BaseCommand):
    args = ''

    def handle(self, *args, **options):
        if len(args) != 0:
            raise CommandError("Command doesn't accept any arguments")
        return self.handle_noargs(**options)

    def handle_noargs(self, **options):
        raise NotImplementedError()

def copy_helper(style, app_or_project, name, directory, other_name=''):
    """
    Copies either a Django application layout template or a Django project
    layout template into the specified directory.

    * style - A color style object (see django.core.management.color).
    * app_or_project - The string 'app' or 'project'.
    * name - The name of the application or project.
    * directory - The directory to copy the layout template to.
    * other_name - When copying an application layout, this should be the name
                   of the project.
    """
    import re
    import shutil
    other = {'project': 'app', 'app': 'project'}[app_or_project]
    if not re.search(r'^\w+$', name): # If it's not a valid directory name.
        raise CommandError("%r is not a valid %s name. Please use only numbers, letters and underscores." % (name, app_or_project))
    top_dir = os.path.join(directory, name)
    try:
        os.mkdir(top_dir)
    except OSError, e:
        raise CommandError(e)

    # Determine where the app or project templates are. Use
    # django.__path__[0] because we don't know into which directory
    # django has been installed.
    template_dir = os.path.join(django.__path__[0], 'conf', '%s_template' % app_or_project)

    for d, subdirs, files in os.walk(template_dir):
        relative_dir = d[len(template_dir)+1:].replace('%s_name' % app_or_project, name)
        if relative_dir:
            os.mkdir(os.path.join(top_dir, relative_dir))
        for i, subdir in enumerate(subdirs):
            if subdir.startswith('.'):
                del subdirs[i]
        for f in files:
            if f.endswith('.pyc'):
                continue
            path_old = os.path.join(d, f)
            path_new = os.path.join(top_dir, relative_dir, f.replace('%s_name' % app_or_project, name))
            fp_old = open(path_old, 'r')
            fp_new = open(path_new, 'w')
            fp_new.write(fp_old.read().replace('{{ %s_name }}' % app_or_project, name).replace('{{ %s_name }}' % other, other_name))
            fp_old.close()
            fp_new.close()
            try:
                shutil.copymode(path_old, path_new)
                _make_writeable(path_new)
            except OSError:
                sys.stderr.write(style.NOTICE("Notice: Couldn't set permission bits on %s. You're probably using an uncommon filesystem setup. No problem.\n" % path_new))

def _make_writeable(filename):
    "Makes sure that the file is writeable. Useful if our source is read-only."
    import stat
    if sys.platform.startswith('java'):
        # On Jython there is no os.access()
        return
    if not os.access(filename, os.W_OK):
        st = os.stat(filename)
        new_permissions = stat.S_IMODE(st.st_mode) | stat.S_IWUSR
        os.chmod(filename, new_permissions)
<|endoftext|>


<commit_before># 2015.6.6 create by david.yi
# add function get_md5()
# 2015.6.7 add def input_field(info, field_default) 提示用户输入指定解释信息的字段名称
# 2015.6.14 r2 项目开始使用 fpytools
#   增加 对象序列化函数 serialize_instance
# 2015.8.1 加入 auto_add_file_ext() ablist_minus() format_list_on_head()
# 2016.2.22 修改名称为 fish_base.py, 继续作为 e2at 项目的底层支持

import os

fish_base_ver = '1.0.0'

# 返回fish_base 版本号,
# 2016.2.22 create by david.yi, e2at v1.0.0 #10006
def get_fish_base_ver():
    return fish_base_ver

# md5 函数
# 2015.5.27. create by david.yi
# 2015.6.6. edit, 转移到这里，作为基本工具函数
# 输入: s: str 字符串
# 输出: 经过md5计算的值
def get_md5(s):
    import hashlib

    m = hashlib.md5()
    m.update(s.encode('utf-8'))
    return m.hexdigest()

# 提示用户输入指定解释信息的字段名称
# 2015.6.7. create by david.yi
# 输入: info: 要显示的字段解释，field_default：默认的字段名称
# 输出: 字段名称
def input_field(info, field_default):
    field = input('Please input the ' + info +
                  ' field name (return for use default ' +
                  field_default + '): ')

    if len(field) <= 0:
        field = field_default

    print('The ' + info + ' field: ' + field + '\n')

    return field

# 对象序列化
# 2015.6.14. edit by david.yi
# 输入: info: 要显示的字段解释，field_default：默认的字段名称
# 输出: 字段名称
def serialize_instance(obj):
    d = {'__classname__': type(obj).__name__}
    d.update(vars(obj))
    return d

# 判断文件名是否没有输入后缀，加上后缀
# create 2015.8.1. by david.yi
def auto_add_file_ext(short_filename, ext):

    temp_filename = short_filename
    if os.path.splitext(temp_filename)[1] == '':
        temp_filename += ext

    return temp_filename

# 列表A-B计算， A: 1 2 3 4 5 B: 1 2 7 结果为 1 2
# create 2015.8.1 by david.yi
def ablist_minus(list_a, list_b):
    list_temp = []
    for i in range(len(list_a)):
        for j in range(len(list_b)):
            if list_a[i] == list_b[j]:
                list_temp.append(list_a[i])

    return list_temp

# 将列表按照列标头进行筛选
# create 2015.8.1. by david.yi
def format_list_on_head(list_source, list_head):
    # 整理 list 数据
    l1 = []  # 单行数据
    l2 = []  # 整体数据

    # 整理要输出的具体list内容
    for i in range(len(list_source)):
        for j in range(len(list_head)):
            l1.append(list_source[i][list_head[j]])
        l2.append(l1)
        l1 = []

    return l2

# r2c1 v1.0.1 #12089
# 通过conf文件。eg ini，读取值，通过字典缓存来提高读取速度
class FpyCache:
    __cache = {}

    def get_cache(self, cf, section, key):
        # 生成 key，用于 dict
        temp_key = section + '_' + key

        if not (temp_key in self.__cache):
            self.__cache[temp_key] = cf[section][key]

        return self.__cache[temp_key]

# 检查指定类型的文件名是否在指定的路径下, 主要用户检查 conf 路径下的配置文件等
# 2016.2.22 create by david.yi , e2at v1.0.0 #10005
def check_kind_path_file(kind_name, file_name):

    # 文件路径
    kind_path = os.path.join(os.path.abspath(''), kind_name)

    # 完整文件名，包含路径
    long_filename = os.path.join(kind_path, file_name)

    # 文件如果不存在，返回错误信息
    if not os.path.isfile(long_filename):
        return False
    else:
        return True, long_filename
<commit_msg>2016.4.1 delete 'build' directory<commit_after><|endoftext|>


<commit_before>"Wrapper for loading templates from storage of some sort (e.g. files or db)"
import template
from template_file import load_template_source

class ExtendsError(Exception):
    pass

def get_template(template_name):
    """
    Returns a compiled template.Template object for the given template name,
    handling template inheritance recursively.
    """
    return get_template_from_string(load_template_source(template_name))

def get_template_from_string(source):
    """
    Returns a compiled template.Template object for the given template code,
    handling template inheritance recursively.
    """
    return template.Template(source)

def render_to_string(template_name, dictionary=None, context_instance=None):
    """
    Loads the given template_name and renders it with the given dictionary as
    context. Returns a string.
    """
    dictionary = dictionary or {}
    t = get_template(template_name)
    if context_instance:
        context_instance.update(dictionary)
    else:
        context_instance = template.Context(dictionary)
    return t.render(context_instance)

def select_template(template_name_list):
    "Given a list of template names, returns the first that can be loaded."
    for template_name in template_name_list:
        try:
            return get_template(template_name)
        except template.TemplateDoesNotExist:
            continue
    # If we get here, none of the templates could be loaded
    raise template.TemplateDoesNotExist, ', '.join(template_name_list)

class BlockNode(template.Node):
    def __init__(self, name, nodelist, parent=None):
        self.name, self.nodelist, self.parent = name, nodelist, parent

    def __repr__(self):
        return "<Block Node: %s. Contents: %r>" % (self.name, self.nodelist)

    def render(self, context):
        context.push()
        # Save context in case of block.super().
        self.context = context
        context['block'] = self
        result = self.nodelist.render(context)
        context.pop()
        return result

    def super(self):
        if self.parent:
            return self.parent.render(self.context)
        return ''

    def add_parent(self, nodelist):
        if self.parent:
            self.parent.add_parent(nodelist)
        else:
            self.parent = BlockNode(self.name, nodelist)

class ExtendsNode(template.Node):
    def __init__(self, nodelist, parent_name, parent_name_var, template_dirs=None):
        self.nodelist = nodelist
        self.parent_name, self.parent_name_var = parent_name, parent_name_var
        self.template_dirs = template_dirs

    def get_parent(self, context):
        if self.parent_name_var:
            self.parent_name = template.resolve_variable_with_filters(self.parent_name_var, context)
        parent = self.parent_name
        if not parent:
            error_msg = "Invalid template name in 'extends' tag: %r." % parent
            if self.parent_name_var:
                error_msg += " Got this from the %r variable." % self.parent_name_var
            raise template.TemplateSyntaxError, error_msg
        try:
            return get_template_from_string(load_template_source(parent, self.template_dirs))
        except template.TemplateDoesNotExist:
            raise template.TemplateSyntaxError, "Template %r cannot be extended, because it doesn't exist" % parent

    def render(self, context):
        compiled_parent = self.get_parent(context)
        parent_is_child = isinstance(compiled_parent.nodelist[0], ExtendsNode)
        parent_blocks = dict([(n.name, n) for n in compiled_parent.nodelist.get_nodes_by_type(BlockNode)])
        for block_node in self.nodelist.get_nodes_by_type(BlockNode):
            # Check for a BlockNode with this node's name, and replace it if found.
            try:
                parent_block = parent_blocks[block_node.name]
            except KeyError:
                # This BlockNode wasn't found in the parent template, but the
                # parent block might be defined in the parent's *parent*, so we
                # add this BlockNode to the parent's ExtendsNode nodelist, so
                # it'll be checked when the parent node's render() is called.
                if parent_is_child:
                    compiled_parent.nodelist[0].nodelist.append(block_node)
            else:
                # Keep any existing parents and add a new one. Used by BlockNode.
                parent_block.parent = block_node.parent
                parent_block.add_parent(parent_block.nodelist)
                parent_block.nodelist = block_node.nodelist
        return compiled_parent.render(context)

def do_block(parser, token):
    """
    Define a block that can be overridden by child templates.
    """
    bits = token.contents.split()
    if len(bits) != 2:
        raise template.TemplateSyntaxError, "'%s' tag takes only one argument" % bits[0]
    block_name = bits[1]
    # Keep track of the names of BlockNodes found in this template, so we can
    # check for duplication.
    try:
        if block_name in parser.__loaded_blocks:
            raise template.TemplateSyntaxError, "'%s' tag with name '%s' appears more than once" % (bits[0], block_name)
        parser.__loaded_blocks.append(block_name)
    except AttributeError: # parser._loaded_blocks isn't a list yet
        parser.__loaded_blocks = [block_name]
    nodelist = parser.parse(('endblock',))
    parser.delete_first_token()
    return BlockNode(block_name, nodelist)

def do_extends(parser, token):
    """
    Signal that this template extends a parent template.

    This tag may be used in two ways: ``{% extends "base" %}`` (with quotes)
    uses the literal value "base" as the name of the parent template to extend,
    or ``{% entends variable %}`` uses the value of ``variable`` as the name
    of the parent template to extend.
    """
    bits = token.contents.split()
    if len(bits) != 2:
        raise template.TemplateSyntaxError, "'%s' takes one argument" % bits[0]
    parent_name, parent_name_var = None, None
    if (bits[1].startswith('"') and bits[1].endswith('"')) or (bits[1].startswith("'") and bits[1].endswith("'")):
        parent_name = bits[1][1:-1]
    else:
        parent_name_var = bits[1]
    nodelist = parser.parse()
    if nodelist.get_nodes_by_type(ExtendsNode):
        raise template.TemplateSyntaxError, "'%s' cannot appear more than once in the same template" % bits[0]
    return ExtendsNode(nodelist, parent_name, parent_name_var)

template.register_tag('block', do_block)
template.register_tag('extends', do_extends)
<commit_msg>Fixed #546 - render_to_string and render_to_response may now take lists of templates and use select_template instead of get_template.  Thanks, hugo<commit_after>"Wrapper for loading templates from storage of some sort (e.g. files or db)"
import template
from template_file import load_template_source

class ExtendsError(Exception):
    pass

def get_template(template_name):
    """
    Returns a compiled template.Template object for the given template name,
    handling template inheritance recursively.
    """
    return get_template_from_string(load_template_source(template_name))

def get_template_from_string(source):
    """
    Returns a compiled template.Template object for the given template code,
    handling template inheritance recursively.
    """
    return template.Template(source)

def render_to_string(template_name, dictionary=None, context_instance=None):
    """
    Loads the given template_name and renders it with the given dictionary as
    context. The template_name may be a string to load a single template using
    get_template, or it may be a tuple to use select_template to find one of
    the templates in the list.  Returns a string.
    """
    dictionary = dictionary or {}
    if isinstance(template_name, (list, tuple)):
        t = select_template(template_name)
    else:
        t = get_template(template_name)
    if context_instance:
        context_instance.update(dictionary)
    else:
        context_instance = template.Context(dictionary)
    return t.render(context_instance)

def select_template(template_name_list):
    "Given a list of template names, returns the first that can be loaded."
    for template_name in template_name_list:
        try:
            return get_template(template_name)
        except template.TemplateDoesNotExist:
            continue
    # If we get here, none of the templates could be loaded
    raise template.TemplateDoesNotExist, ', '.join(template_name_list)

class BlockNode(template.Node):
    def __init__(self, name, nodelist, parent=None):
        self.name, self.nodelist, self.parent = name, nodelist, parent

    def __repr__(self):
        return "<Block Node: %s. Contents: %r>" % (self.name, self.nodelist)

    def render(self, context):
        context.push()
        # Save context in case of block.super().
        self.context = context
        context['block'] = self
        result = self.nodelist.render(context)
        context.pop()
        return result

    def super(self):
        if self.parent:
            return self.parent.render(self.context)
        return ''

    def add_parent(self, nodelist):
        if self.parent:
            self.parent.add_parent(nodelist)
        else:
            self.parent = BlockNode(self.name, nodelist)

class ExtendsNode(template.Node):
    def __init__(self, nodelist, parent_name, parent_name_var, template_dirs=None):
        self.nodelist = nodelist
        self.parent_name, self.parent_name_var = parent_name, parent_name_var
        self.template_dirs = template_dirs

    def get_parent(self, context):
        if self.parent_name_var:
            self.parent_name = template.resolve_variable_with_filters(self.parent_name_var, context)
        parent = self.parent_name
        if not parent:
            error_msg = "Invalid template name in 'extends' tag: %r." % parent
            if self.parent_name_var:
                error_msg += " Got this from the %r variable." % self.parent_name_var
            raise template.TemplateSyntaxError, error_msg
        try:
            return get_template_from_string(load_template_source(parent, self.template_dirs))
        except template.TemplateDoesNotExist:
            raise template.TemplateSyntaxError, "Template %r cannot be extended, because it doesn't exist" % parent

    def render(self, context):
        compiled_parent = self.get_parent(context)
        parent_is_child = isinstance(compiled_parent.nodelist[0], ExtendsNode)
        parent_blocks = dict([(n.name, n) for n in compiled_parent.nodelist.get_nodes_by_type(BlockNode)])
        for block_node in self.nodelist.get_nodes_by_type(BlockNode):
            # Check for a BlockNode with this node's name, and replace it if found.
            try:
                parent_block = parent_blocks[block_node.name]
            except KeyError:
                # This BlockNode wasn't found in the parent template, but the
                # parent block might be defined in the parent's *parent*, so we
                # add this BlockNode to the parent's ExtendsNode nodelist, so
                # it'll be checked when the parent node's render() is called.
                if parent_is_child:
                    compiled_parent.nodelist[0].nodelist.append(block_node)
            else:
                # Keep any existing parents and add a new one. Used by BlockNode.
                parent_block.parent = block_node.parent
                parent_block.add_parent(parent_block.nodelist)
                parent_block.nodelist = block_node.nodelist
        return compiled_parent.render(context)

def do_block(parser, token):
    """
    Define a block that can be overridden by child templates.
    """
    bits = token.contents.split()
    if len(bits) != 2:
        raise template.TemplateSyntaxError, "'%s' tag takes only one argument" % bits[0]
    block_name = bits[1]
    # Keep track of the names of BlockNodes found in this template, so we can
    # check for duplication.
    try:
        if block_name in parser.__loaded_blocks:
            raise template.TemplateSyntaxError, "'%s' tag with name '%s' appears more than once" % (bits[0], block_name)
        parser.__loaded_blocks.append(block_name)
    except AttributeError: # parser._loaded_blocks isn't a list yet
        parser.__loaded_blocks = [block_name]
    nodelist = parser.parse(('endblock',))
    parser.delete_first_token()
    return BlockNode(block_name, nodelist)

def do_extends(parser, token):
    """
    Signal that this template extends a parent template.

    This tag may be used in two ways: ``{% extends "base" %}`` (with quotes)
    uses the literal value "base" as the name of the parent template to extend,
    or ``{% entends variable %}`` uses the value of ``variable`` as the name
    of the parent template to extend.
    """
    bits = token.contents.split()
    if len(bits) != 2:
        raise template.TemplateSyntaxError, "'%s' takes one argument" % bits[0]
    parent_name, parent_name_var = None, None
    if (bits[1].startswith('"') and bits[1].endswith('"')) or (bits[1].startswith("'") and bits[1].endswith("'")):
        parent_name = bits[1][1:-1]
    else:
        parent_name_var = bits[1]
    nodelist = parser.parse()
    if nodelist.get_nodes_by_type(ExtendsNode):
        raise template.TemplateSyntaxError, "'%s' cannot appear more than once in the same template" % bits[0]
    return ExtendsNode(nodelist, parent_name, parent_name_var)

template.register_tag('block', do_block)
template.register_tag('extends', do_extends)
<|endoftext|>