Source

django-environments / scripts / djenvlib

#
# django-environments environment initialization script
#
# Instead of editing the file, it's better to set the following
# variable in your own initenv script or virtualenv bin/postactivate,
# and source this file (order does not matter).
#
# PROJECT_ROOT is the path to the root of the entire project, i.e.
# the directory containing the one or more 'Django projects'.
#
# PROJECT_ROOT=/Users/joe/projects/myproject

# Not to be called directly, see djenv below
function initenv() {
    DJANGO_PROJECT=$1
    DJANGO_SETTINGS=$2

    # The root of the project should exist, of course
    [ -z "$PROJECT_ROOT" ] && \
        echo "Variable \$PROJECT_ROOT not set or empty" 1>&2 && return 1
    [ ! -d "$PROJECT_ROOT" ] && \
         echo "Variable \$PROJECT_ROOT does not point to a readable directory" 1>&2 && return 1

    # Check Django project as well
    [ -z "$DJANGO_PROJECT" ] && \
        echo "Argument \$DJANGO_PROJECT not set or empty" 1>&2 && return 1
    [ ! -d "$PROJECT_ROOT/$DJANGO_PROJECT" ] && \
        echo "Argument \$DJANGO_PROJECT does not identify a readable directory within $PROJECT_ROOT" 1>&2 && \
        return 1

    # If no particular settings are defined, just use the "base" settings
    _OLD_DJANGO_SETTINGS_MODULE=$DJANGO_SETTINGS_MODULE
    if [ ! -z "$DJANGO_SETTINGS" ]; then
        DJANGO_SETTINGS_MODULE=$DJANGO_PROJECT.$DJANGO_SETTINGS
    else
        DJANGO_SETTINGS_MODULE=$DJANGO_PROJECT.settings
    fi

    # Set the PYTHONPATH to include PROJECT_ROOT
    _OLD_PYTHONPATH=$PYTHONPATH
    PYTHONPATH=$PROJECT_ROOT:$PYTHONPATH

    export PROJECT_ROOT DJANGO_PROJECT PYTHONPATH DJANGO_SETTINGS_MODULE

    # Test settings import
    python -c "import $DJANGO_SETTINGS_MODULE" > /dev/null 2>&1
    if [ ! "$?" -eq 0 ]; then
        echo "Error importing settings $DJANGO_SETTINGS_MODULE (PYTHONPATH: $PYTHONPATH)" 1>&2
        python -c "import $DJANGO_SETTINGS_MODULE"
        return 1
    fi

    # Test if the definitions in the settings match ours
    [ "$PROJECT_ROOT" != "`get_django_setting PROJECT_ROOT`" ] && \
        echo "\$PROJECT_ROOT in Django settings is different from shell" 1>&2 && \
        return 1
    [ "$DJANGO_PROJECT" != "`get_django_setting DJANGO_PROJECT`" ] && \
        echo "\$DJANGO_PROJECT in Django settings is different from shell" 1>&2 && \
        return 1
    [ "$PROJECT_ROOT/$DJANGO_PROJECT" != "`get_django_setting DJANGO_PROJECT_DIR`" ] && \
        echo "\$DJANGO_PROJECT_DIR in Django settings is different from \$PROJECT_ROOT/\$DJANGO_PROJECT" 1>&2 && 
        return 1

    # We're good - let's set the prompt
    _OLD_DJANGO_ENV_PS1=$PS1
    PS1=[$DJANGO_PROJECT]$PS1

    # Show environment info
    if [ ! -z "$SHOW_DJANGO_ENVIRONMENT" ]; then
        if [ "$SHOW_DJANGO_ENVIRONMENT" = "yes" ]; then
            echo Welcome to $DJANGO_PROJECT. Environment info:
            djenv
            echo
            if [ "$SHOW_DJANGO_ENVIRONMENT" = "settings" ]; then
                echo Django settings:
                PAGER=cat python -c "import $DJANGO_SETTINGS_MODULE; help($DJANGO_SETTINGS_MODULE)" | grep -v "^$"
                echo
            fi
        fi
    fi

    # Check settings
    for dirs in TEMPLATE_DIRS FIXTURE_DIRS; do
        eval `import_django_settings $dirs`
        envname=DJANGO_$dirs
        for dir in ${!envname}; do
            [ ! -d $dir ] && echo "Warning: \"$dir\" in settings.$dirs is not a valid directory"
        done
    done

    return 0
}

# Some useful functions

# Exit current project
function djexit() {
    [ -z "$DJANGO_PROJECT" ] && return 1

    PS1=$_OLD_DJANGO_ENV_PS1

    if [ ! -z "$_OLD_DJANGO_SETTINGS_MODULE" ]; then
        DJANGO_SETTINGS_MODULE=$_OLD_DJANGO_SETTINGS_MODULE
    else
        unset DJANGO_SETTINGS_MODULE
    fi

    if [ ! -z "$_OLD_PYTHONPATH" ]; then
        PYTHONPATH=$_OLD_PYTHONPATH
    else
        unset PYTHONPATH
    fi

    unset _OLD_DJANGO_SETTINGS_MODULE _OLD_PYTHONPATH \
        DJANGO_PROJECT DJANGO_SETTINGS
}

# Change django project
# Example:
# djenv # Print current environment settings
# or
# djenv mysite # Use default settings
# or
# djenv mysite settings.env.local # Use specific settins
function djenv() {
    # Environment info
    if [ -z "$1" ]; then
        echo PROJECT_ROOT: \'$PROJECT_ROOT\'
        echo DJANGO_PROJECT: \'$DJANGO_PROJECT\'
        echo DJANGO_SETTINGS_MODULE: \'$DJANGO_SETTINGS_MODULE\'
        echo PYTHONPATH: \'$PYTHONPATH\'
        return
    fi

    # Help
    if [ "$1" = "-h" -o "$1" = "--help" ]; then
        echo "Usage: djenv [DJANGO_PROJECT [DJANGO_SETTINGS]]"
        return
    fi

    # Check $PROJECT_ROOT
    if [ -z "$PROJECT_ROOT" ]; then
        echo "Variable \$PROJECT_ROOT not set or empty" 1>&2
        return 1
    fi

    djexit

    initenv $*
    [ $? -eq 1 ] && djexit && return 1

    cdjango

    return 0
}

# Get a django setting from the current settings module
# Experimental.
#
# Example:
# LC=`get_django_setting LANGUAGE_CODE` && echo $LC
#
# Returns nothing if setting cannot be found
function get_django_setting() {
    [ -z "$1" ] && echo "Usage: get_django_setting <setting-name>" 1>&2 && return 1

    python << EOF
import $DJANGO_SETTINGS_MODULE as settings

try:
    print settings.__dict__['$1']
except KeyError:
    pass
EOF
}

# Import django settings into the shell environment
# Experimental.
#
# When using, set $IFS to empty (this is needed because we eval
# the output of the python-generated shell script code):
# IFS=''
#
# Then use the function as follows:
# eval `import_django_settings` # all settings
# or
# eval `import_django_settings ADMIN` # all settings starting with 'ADMIN'
#
# Tuples and lists items are separated with newlines, so set $IFS
# to newline to get to those:
# IFS='
# '
# Note that all variables are prefixed with value of $prefix, 'DJANGO_'.
function import_django_settings() {
    prefix=DJANGO_
    python << EOF
import $DJANGO_SETTINGS_MODULE as settings
from types import TupleType, ListType, DictType

def escape(value):
    return str(value).replace('"', '\\\\"')

settings = settings.__dict__.items()
settings.sort()
for name, value in settings:
    if name.find('__') == -1 and name.find('$1') == 0:
        if type(value) in (TupleType, ListType):
            print '$prefix%s="' % name
            for item in value:
                print escape(item)
            print '"'
        elif type(value) == DictType:
            print '$prefix%s="' % name
            for name, value in value.items():
                print '%s:%s' % (name, escape(value))
            print '"'
        else:
            print '$prefix%s="%s"' % (name, escape(value))
EOF
}

# Change directory to project root
function cdroot() {
    [ -z "$PROJECT_ROOT" ] && echo "No \$PROJECT_ROOT" 1>&2 && return 1
    cd $PROJECT_ROOT/$1
}

# Install dependencies for an environment (first argument); the file
# with the dependencies should be in the requirements directory and
# should have the format 'libs-<environment>.txt'
function pipup() {
    [ -z "$PROJECT_ROOT" ] && echo "No \$PROJECT_ROOT" 1>&2 && return 1
    [ -z "$1" ] && echo "Usage: pipup <requirements-identifier>" 1>&2 && return 1
    pip install --requirement=$PROJECT_ROOT/requirements/libs-$1.txt
}

# Use compileall to compile all .py files - handy for web server
# environments where the server user often has no write access to the
# .pyc files / directories
function pycompile() {
    [ -z "$PROJECT_ROOT" ] && echo "No \$PROJECT_ROOT" 1>&2 && return 1
    python -c "import compileall; compileall.compile_dir('$PROJECT_ROOT')"
    removeorphanpycs
}

# Remove .pyc files without a corresponding .py
function removeorphanpycs() {
    [ -z "$PROJECT_ROOT" ] && echo "No \$PROJECT_ROOT" 1>&2 && return 1
    for pyc in `find $PROJECT_ROOT -name \*.pyc`; do
        [ -f  `echo $pyc | sed 's/c$//'` ] || rm -v $pyc
    done
}

# Change directory to Django project
function cdjango () {
    [ -z "$PROJECT_ROOT" ] && echo "No \$PROJECT_ROOT" 1>&2 && return 1
    [ -z "$DJANGO_PROJECT" ] && echo "No \$DJANGO_PROJECT" 1>&2 && return 1
    cd $PROJECT_ROOT/$DJANGO_PROJECT/$1
}

# Forget manage.py, django-admin.py respects our settings!
function djadmin() {
    [ -z "$PROJECT_ROOT" ] && echo "No \$PROJECT_ROOT" 1>&2 && return 1
    [ -z "$DJANGO_PROJECT" ] && echo "No \$DJANGO_PROJECT" 1>&2 && return 1
    django-admin.py $*
}

# Run development server on settings.LOCAL_SERVER_PORT
function runserver() {
    [ -z "$PROJECT_ROOT" ] && echo "No \$PROJECT_ROOT" 1>&2 && return 1
    [ -z "$DJANGO_PROJECT" ] && echo "No \$DJANGO_PROJECT" 1>&2 && return 1
    django-admin.py runserver `get_django_setting LOCAL_SERVER_PORT`
}

# Export functions that are not solely intended for interactive use
export -f get_django_setting import_django_settings