<commit_before>#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
    wger.main
    ~~~~~~~~~

    Main script to start and set up wger Workout Manager.

    :copyright: 2011, 2012 by OpenSlides team, see AUTHORS.
    :license: GNU GPL, see LICENSE for more details.
"""

# for python 2.5 support
from __future__ import with_statement

import base64
import ctypes
import optparse
import os
import socket
import sys
import tempfile
import threading
import time
import webbrowser
import inspect

import django.conf
from django.core.management import execute_from_command_line
from django.core.management import call_command

from wger import get_version


CONFIG_TEMPLATE = """#!/usr/bin/env python
# -*- coding: utf-8 -*-

from wger.settings_global import *

# Use 'DEBUG = True' to get more details for server errors
# (Default for releases: 'False')
DEBUG = True
TEMPLATE_DEBUG = DEBUG

ADMINS = (
    ('Your name', '<EMAIL>'),
)


DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.%(dbengine)s',
        'NAME': %(dbname)s,
        'USER': '%(dbuser)s',
        'PASSWORD': '%(db<PASSWORD>',
        'HOST': '%(dbhost)s',
        'PORT': '%(dbport)s',
    }
}

SOUTH_TESTS_MIGRATE = False

# Make this unique, and don't share it with anybody.
SECRET_KEY = %(default_key)r

# Your reCaptcha keys
RECAPTCHA_PUBLIC_KEY = '%(recaptcha_public_key)s'
RECAPTCHA_PRIVATE_KEY = '%(recaptcha_private_key)s'

# The site's URL (e.g. http://www.my-local-gym.com or http://localhost:8000)
# This is needed for Mozilla's BrowserID to work
SITE_URL = '%(siteurl)s'

# This might be a good idea if you setup memcached
#SESSION_ENGINE = "django.contrib.sessions.backends.cache"


# Path to uploaded files
MEDIA_ROOT = '%(media_folder_path)s'
MEDIA_URL = SITE_URL + '/static/'
if DEBUG:
    # Serve the uploaded files like this only during development
    STATICFILES_DIRS = (MEDIA_ROOT, )
"""

KEY_LENGTH = 30

# sentinel used to signal that the database ought to be stored
# relative to the portable's directory
_portable_db_path = object()


def process_options(argv=None):
    if argv is None:
        argv = sys.argv[1:]

    parser = optparse.OptionParser(
        description="Run wger Workout Manager using django's builtin server")
    parser.add_option("-a", "--address", help="IP Address to listen on.")
    parser.add_option("-p", "--port", type="int", help="Port to listen on.")
    parser.add_option(
        "--syncdb", action="store_true",
        help="Update/create database before starting the server.")
    parser.add_option(
        "--reset-admin", action="store_true",
        help="Make sure the user 'admin' exists and uses '<PASSWORD>' as password.")
    parser.add_option(
        "-s", "--settings", help="Path to the wger configuration file.")
    parser.add_option(
        "--no-reload", action="store_true",
        help="Do not reload the development server.")
    parser.add_option(
        "--migrate-db", action="store_true",
        help="Runs all database migrations (safe operation).")
    parser.add_option(
        "--version", action="store_true",
        help="Show version and exit.")
    parser.add_option(
        "--show-config", action="store_true",
        help="Show configuration paths and exit.")

    opts, args = parser.parse_args(argv)
    if opts.version:
        print get_version()
        exit(0)
    if opts.show_config:
        print "Settings file: %s" % get_user_config_path('wger', 'settings.py')
        print "Database file: %s" % get_user_data_path('wger', 'database.sqlite')
        exit(0)
    if args:
        sys.stderr.write("This command does not take arguments!\n\n")
        parser.print_help()
        sys.exit(1)

    return opts


def main(argv=None):
    opts = process_options(argv)
    _main(opts)


def win32_portable_main(argv=None):
    """special entry point for the win32 portable version"""

    opts = process_options(argv)

    database_path = None

    if opts.settings is None:
        portable_dir = get_portable_path()
        try:
            fd, test_file = tempfile.mkstemp(dir=portable_dir)
        except OSError:
            portable_dir_writeable = False
        else:
            portable_dir_writeable = True
            os.close(fd)
            os.unlink(test_file)

        if portable_dir_writeable:
            opts.settings = os.path.join(
                portable_dir, "wger", "settings.py")
            database_path = _portable_db_path

    _main(opts, database_path=database_path)


def _main(opts, database_path=None):
    # Find the path to the settings
    settings_path = opts.settings
    if settings_path is None:
        settings_path = get_user_config_path('wger', 'settings.py')

    # Find url to wger
    addr, port = detect_listen_opts(opts.address, opts.port)
    if port == 80:
        url = "http://{0}".format(addr)
    else:
        url = "http://{0}:{1}".format(addr, port)

    # Create settings if necessary
    if not os.path.exists(settings_path):
        create_settings(settings_path, database_path, url)

    # Set the django environment to the settings
    setup_django_environment(settings_path)

    # Check for south tables, this is only Only needed for the
    # update 1.1.1 > 1.2, when south was introduced
    from south.models import MigrationHistory
    from django.db.utils import DatabaseError
    try:
        if database_exists() and not opts.syncdb:
            history = MigrationHistory.objects.count()
    except DatabaseError:
        print("Manual database upgrade needed")
        print("------------------------------")
        print("The database schema changed after the 1.1.1 release. Run this script")
        print("with the --syncdb option. This will upgrade the database, but will")
        print("overwrite any changes you made to exercises and ingredients")
        sys.exit()

    # Create Database if necessary
    if not database_exists() or opts.syncdb:
        run_syncdb()
        create_or_reset_admin_user()

    # Only run the south migrations
    elif opts.migrate_db:
        run_south()

    # Reset Admin
    elif opts.reset_admin:
        create_or_reset_admin_user()

    # Start wger
    if opts.no_reload:
        extra_args = ['--noreload']
    else:
        extra_args = []
    start_wger(addr, port, start_browser_url=url, extra_args=extra_args)


def create_settings(settings_path, database_path=None, url=None):
    settings_module = os.path.dirname(settings_path)
    print "* No settings file found. Creating one at %s" % settings_module

    if database_path is _portable_db_path:
        database_path = get_portable_db_path()
        dbpath_value = 'wger.main.get_portable_db_path()'
    else:
        if database_path is None:
            database_path = get_user_data_path('wger', 'database.sqlite')
        dbpath_value = repr(fs2unicode(database_path))

    media_folder_path = get_user_data_path('wger', 'media')
    print "Please edit your settings file and enter the values for the reCaptcha keys "
    print "You can leave this empty, but won't be able to register new users"
    recaptcha_public_key = ''
    recaptcha_private_key = ''

    # Fill in the config file template

    # The environment variable is set by travis during testing
    if os.environ.get('DB') == 'postgresql':
        dbengine = 'postgresql_psycopg2'
        dbname = "'test_wger'"
        dbuser = 'postgres'
        dbpassword = ''
        dbhost = '127.0.0.1'
        dbport = ''
    elif os.environ.get('DB') == 'mysql':
        dbengine = 'mysql'
        dbname = "'test_wger'"
        dbuser = 'root'
        dbpassword = ''
        dbhost = '127.0.0.1'
        dbport = ''
    else:
        dbengine = 'sqlite3'
        dbname = dbpath_value
        dbuser = ''
        dbpassword = ''
        dbhost = ''
        dbport = ''

    settings_content = CONFIG_TEMPLATE % dict(
        default_key=base64.b64encode(os.urandom(KEY_LENGTH)),
        dbpath=dbpath_value,
        dbengine=dbengine,
        dbname=dbname,
        dbuser=dbuser,
        dbpassword=<PASSWORD>,
        dbhost=dbhost,
        dbport=dbport,
        siteurl=url,
        recaptcha_public_key=recaptcha_public_key,
        recaptcha_private_key=recaptcha_private_key,
        media_folder_path=media_folder_path)

    if not os.path.exists(settings_module):
        os.makedirs(settings_module)

    if not os.path.exists(os.path.dirname(database_path)):
        os.makedirs(os.path.dirname(database_path))

    with open(settings_path, 'w') as settings_file:
        settings_file.write(settings_content)


def setup_django_environment(settings_path):
    settings_file = os.path.basename(settings_path)
    settings_module_name = "".join(settings_file.split('.')[:-1])
    if '.' in settings_module_name:
        print "'.' is not an allowed character in the settings-file"
        sys.exit(1)
    settings_module_dir = os.path.dirname(settings_path)
    sys.path.append(settings_module_dir)
    os.environ[django.conf.ENVIRONMENT_VARIABLE] = '%s' % settings_module_name


def detect_listen_opts(address, port):
    if address is None:
        try:
            address = socket.gethostbyname(socket.gethostname())
        except socket.error:
            address = "12172.16.17.32"

    if port is None:
        # test if we can use port 80
        s = socket.socket()
        port = 80
        try:
            s.bind((address, port))
            s.listen(-1)
        except socket.error:
            port = 8000
        finally:
            s.close()

    return address, port


def database_exists():
    """Detect if database exists"""

    # can't be imported in global scope as they already require
    # the settings module during import
    from django.db import DatabaseError
    from django.core.exceptions import ImproperlyConfigured
    from wger.manager.models import User

    try:
        # TODO: Use another model, the User could be deactivated
        User.objects.count()
    except DatabaseError:
        return False
    except ImproperlyConfigured:
        print "Your settings file seems broken"
        sys.exit(0)
    else:
        return True


def init_south():
    '''
    Only perform the south initialisation
    '''
    print("* Initialising south")
    execute_from_command_line(["", "migrate", "wger.core", "0001"])
    execute_from_command_line(["", "migrate", "wger.exercises", "0001", "--fake"])
    execute_from_command_line(["", "migrate", "wger.config", "0001", "--fake"])
    execute_from_command_line(["", "migrate", "wger.manager", "0001", "--fake"])
    execute_from_command_line(["", "migrate", "wger.nutrition", "0001", "--fake"])
    execute_from_command_line(["", "migrate", "wger.weight", "0001", "--fake"])


def run_south():
    '''
    Run all south migrations
    '''
    execute_from_command_line(["", "migrate", "wger.core"])
    execute_from_command_line(["", "migrate", "wger.config"])
    execute_from_command_line(["", "migrate", "wger.manager"])
    execute_from_command_line(["", "migrate", "wger.exercises"])
    execute_from_command_line(["", "migrate", "wger.nutrition"])
    execute_from_command_line(["", "migrate", "wger.weight"])

    # Other apps
    execute_from_command_line(["", "migrate", "easy_thumbnails"])
    execute_from_command_line(["", "migrate", "tastypie"])


def load_fixtures():
    '''
    Loads all fixtures
    '''
    os.chdir(os.path.dirname(inspect.stack()[0][1]))
    current_dir = os.getcwd()

    # Core
    path = os.path.join(current_dir, 'core', 'fixtures/')
    call_command("loaddata", path + "languages.json")
    call_command("loaddata", path + "users.json")
    call_command("loaddata", path + "licenses.json")
    call_command("loaddata", path + "days_of_week.json")

    # Config
    path = os.path.join(current_dir, 'config', 'fixtures/')
    call_command("loaddata", path + "language_config.json")
    call_command("loaddata", path + "gym_config.json")

    # Manager
    # path = os.path.join(current_dir, 'manager', 'fixtures/')

    # Exercises
    path = os.path.join(current_dir, 'exercises', 'fixtures/')<commit_msg>Load default permission groups during installation<commit_after>#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
    wger.main
    ~~~~~~~~~

    Main script to start and set up wger Workout Manager.

    :copyright: 2011, 2012 by OpenSlides team, see AUTHORS.
    :license: GNU GPL, see LICENSE for more details.
"""

# for python 2.5 support
from __future__ import with_statement

import base64
import ctypes
import optparse
import os
import socket
import sys
import tempfile
import threading
import time
import webbrowser
import inspect

import django.conf
from django.core.management import execute_from_command_line
from django.core.management import call_command

from wger import get_version


CONFIG_TEMPLATE = """#!/usr/bin/env python
# -*- coding: utf-8 -*-

from wger.settings_global import *

# Use 'DEBUG = True' to get more details for server errors
# (Default for releases: 'False')
DEBUG = True
TEMPLATE_DEBUG = DEBUG

ADMINS = (
    ('Your name', '<EMAIL>'),
)


DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.%(dbengine)s',
        'NAME': %(dbname)s,
        'USER': '%(dbuser)s',
        'PASSWORD': '%(<PASSWORD>',
        'HOST': '%(dbhost)s',
        'PORT': '%(dbport)s',
    }
}

SOUTH_TESTS_MIGRATE = False

# Make this unique, and don't share it with anybody.
SECRET_KEY = %(default_key)r

# Your reCaptcha keys
RECAPTCHA_PUBLIC_KEY = '%(recaptcha_public_key)s'
RECAPTCHA_PRIVATE_KEY = '%(recaptcha_private_key)s'

# The site's URL (e.g. http://www.my-local-gym.com or http://localhost:8000)
# This is needed for Mozilla's BrowserID to work
SITE_URL = '%(siteurl)s'

# This might be a good idea if you setup memcached
#SESSION_ENGINE = "django.contrib.sessions.backends.cache"


# Path to uploaded files
MEDIA_ROOT = '%(media_folder_path)s'
MEDIA_URL = SITE_URL + '/static/'
if DEBUG:
    # Serve the uploaded files like this only during development
    STATICFILES_DIRS = (MEDIA_ROOT, )
"""

KEY_LENGTH = 30

# sentinel used to signal that the database ought to be stored
# relative to the portable's directory
_portable_db_path = object()


def process_options(argv=None):
    if argv is None:
        argv = sys.argv[1:]

    parser = optparse.OptionParser(
        description="Run wger Workout Manager using django's builtin server")
    parser.add_option("-a", "--address", help="IP Address to listen on.")
    parser.add_option("-p", "--port", type="int", help="Port to listen on.")
    parser.add_option(
        "--syncdb", action="store_true",
        help="Update/create database before starting the server.")
    parser.add_option(
        "--reset-admin", action="store_true",
        help="Make sure the user 'admin' exists and uses '<PASSWORD>' as password.")
    parser.add_option(
        "-s", "--settings", help="Path to the wger configuration file.")
    parser.add_option(
        "--no-reload", action="store_true",
        help="Do not reload the development server.")
    parser.add_option(
        "--migrate-db", action="store_true",
        help="Runs all database migrations (safe operation).")
    parser.add_option(
        "--version", action="store_true",
        help="Show version and exit.")
    parser.add_option(
        "--show-config", action="store_true",
        help="Show configuration paths and exit.")

    opts, args = parser.parse_args(argv)
    if opts.version:
        print get_version()
        exit(0)
    if opts.show_config:
        print "Settings file: %s" % get_user_config_path('wger', 'settings.py')
        print "Database file: %s" % get_user_data_path('wger', 'database.sqlite')
        exit(0)
    if args:
        sys.stderr.write("This command does not take arguments!\n\n")
        parser.print_help()
        sys.exit(1)

    return opts


def main(argv=None):
    opts = process_options(argv)
    _main(opts)


def win32_portable_main(argv=None):
    """special entry point for the win32 portable version"""

    opts = process_options(argv)

    database_path = None

    if opts.settings is None:
        portable_dir = get_portable_path()
        try:
            fd, test_file = tempfile.mkstemp(dir=portable_dir)
        except OSError:
            portable_dir_writeable = False
        else:
            portable_dir_writeable = True
            os.close(fd)
            os.unlink(test_file)

        if portable_dir_writeable:
            opts.settings = os.path.join(
                portable_dir, "wger", "settings.py")
            database_path = _portable_db_path

    _main(opts, database_path=database_path)


def _main(opts, database_path=None):
    # Find the path to the settings
    settings_path = opts.settings
    if settings_path is None:
        settings_path = get_user_config_path('wger', 'settings.py')

    # Find url to wger
    addr, port = detect_listen_opts(opts.address, opts.port)
    if port == 80:
        url = "http://{0}".format(addr)
    else:
        url = "http://{0}:{1}".format(addr, port)

    # Create settings if necessary
    if not os.path.exists(settings_path):
        create_settings(settings_path, database_path, url)

    # Set the django environment to the settings
    setup_django_environment(settings_path)

    # Check for south tables, this is only Only needed for the
    # update 1.1.1 > 1.2, when south was introduced
    from south.models import MigrationHistory
    from django.db.utils import DatabaseError
    try:
        if database_exists() and not opts.syncdb:
            history = MigrationHistory.objects.count()
    except DatabaseError:
        print("Manual database upgrade needed")
        print("------------------------------")
        print("The database schema changed after the 1.1.1 release. Run this script")
        print("with the --syncdb option. This will upgrade the database, but will")
        print("overwrite any changes you made to exercises and ingredients")
        sys.exit()

    # Create Database if necessary
    if not database_exists() or opts.syncdb:
        run_syncdb()
        create_or_reset_admin_user()

    # Only run the south migrations
    elif opts.migrate_db:
        run_south()

    # Reset Admin
    elif opts.reset_admin:
        create_or_reset_admin_user()

    # Start wger
    if opts.no_reload:
        extra_args = ['--noreload']
    else:
        extra_args = []
    start_wger(addr, port, start_browser_url=url, extra_args=extra_args)


def create_settings(settings_path, database_path=None, url=None):
    settings_module = os.path.dirname(settings_path)
    print "* No settings file found. Creating one at %s" % settings_module

    if database_path is _portable_db_path:
        database_path = get_portable_db_path()
        dbpath_value = 'wger.main.get_portable_db_path()'
    else:
        if database_path is None:
            database_path = get_user_data_path('wger', 'database.sqlite')
        dbpath_value = repr(fs2unicode(database_path))

    media_folder_path = get_user_data_path('wger', 'media')
    print "Please edit your settings file and enter the values for the reCaptcha keys "
    print "You can leave this empty, but won't be able to register new users"
    recaptcha_public_key = ''
    recaptcha_private_key = ''

    # Fill in the config file template

    # The environment variable is set by travis during testing
    if os.environ.get('DB') == 'postgresql':
        dbengine = 'postgresql_psycopg2'
        dbname = "'test_wger'"
        dbuser = 'postgres'
        dbpassword = ''
        dbhost = '127.0.0.1'
        dbport = ''
    elif os.environ.get('DB') == 'mysql':
        dbengine = 'mysql'
        dbname = "'test_wger'"
        dbuser = 'root'
        dbpassword = ''
        dbhost = '127.0.0.1'
        dbport = ''
    else:
        dbengine = 'sqlite3'
        dbname = dbpath_value
        dbuser = ''
        dbpassword = ''
        dbhost = ''
        dbport = ''

    settings_content = CONFIG_TEMPLATE % dict(
        default_key=base64.b64encode(os.urandom(KEY_LENGTH)),
        dbpath=dbpath_value,
        dbengine=dbengine,
        dbname=dbname,
        dbuser=dbuser,
        dbpassword=<PASSWORD>,
        dbhost=dbhost,
        dbport=dbport,
        siteurl=url,
        recaptcha_public_key=recaptcha_public_key,
        recaptcha_private_key=recaptcha_private_key,
        media_folder_path=media_folder_path)

    if not os.path.exists(settings_module):
        os.makedirs(settings_module)

    if not os.path.exists(os.path.dirname(database_path)):
        os.makedirs(os.path.dirname(database_path))

    with open(settings_path, 'w') as settings_file:
        settings_file.write(settings_content)


def setup_django_environment(settings_path):
    settings_file = os.path.basename(settings_path)
    settings_module_name = "".join(settings_file.split('.')[:-1])
    if '.' in settings_module_name:
        print "'.' is not an allowed character in the settings-file"
        sys.exit(1)
    settings_module_dir = os.path.dirname(settings_path)
    sys.path.append(settings_module_dir)
    os.environ[django.conf.ENVIRONMENT_VARIABLE] = '%s' % settings_module_name


def detect_listen_opts(address, port):
    if address is None:
        try:
            address = socket.gethostbyname(socket.gethostname())
        except socket.error:
            address = "127.0.0.1"

    if port is None:
        # test if we can use port 80
        s = socket.socket()
        port = 80
        try:
            s.bind((address, port))
            s.listen(-1)
        except socket.error:
            port = 8000
        finally:
            s.close()

    return address, port


def database_exists():
    """Detect if database exists"""

    # can't be imported in global scope as they already require
    # the settings module during import
    from django.db import DatabaseError
    from django.core.exceptions import ImproperlyConfigured
    from wger.manager.models import User

    try:
        # TODO: Use another model, the User could be deactivated
        User.objects.count()
    except DatabaseError:
        return False
    except ImproperlyConfigured:
        print "Your settings file seems broken"
        sys.exit(0)
    else:
        return True


def init_south():
    '''
    Only perform the south initialisation
    '''
    print("* Initialising south")
    execute_from_command_line(["", "migrate", "wger.core", "0001"])
    execute_from_command_line(["", "migrate", "wger.exercises", "0001", "--fake"])
    execute_from_command_line(["", "migrate", "wger.config", "0001", "--fake"])
    execute_from_command_line(["", "migrate", "wger.manager", "0001", "--fake"])
    execute_from_command_line(["", "migrate", "wger.nutrition", "0001", "--fake"])
    execute_from_command_line(["", "migrate", "wger.weight", "0001", "--fake"])


def run_south():
    '''
    Run all south migrations
    '''
    execute_from_command_line(["", "migrate", "wger.core"])
    execute_from_command_line(["", "migrate", "wger.config"])
    execute_from_command_line(["", "migrate", "wger.manager"])
    execute_from_command_line(["", "migrate", "wger.exercises"])
    execute_from_command_line(["", "migrate", "wger.nutrition"])
    execute_from_command_line(["", "migrate", "wger.weight"])

    # Other apps
    execute_from_command_line(["", "migrate", "easy_thumbnails"])
    execute_from_command_line(["", "migrate", "tastypie"])


def load_fixtures():
    '''
    Loads all fixtures
    '''
    os.chdir(os.path.dirname(inspect.stack()[0][1]))
    current_dir = os.getcwd()

    # Core
    path = os.path.join(current_dir, 'core', 'fixtures/')
    call_command("loaddata", path + "languages.json")
    call_command("loaddata", path + "groups.json")
    call_command("loaddata", path + "users.json")
    call_command("loaddata", path + "licenses.json")
    call_command("loaddata", path + "days_of_week.json")

    # Config
    path = os.path.join(current_dir, 'config', 'fixtures/')
    call_command("loaddata", path + "language_config.json")
    call_command("loaddata", path + "gym_config.json")

    # Manager
    # path = os.path.join(current_dir, 'manager', 'fixtures/')

    # Exercises
    path = os.path.join(current_dir, 'exercises', 'fixtures/')
{'fraction_non_alphanumeric': 0.12175813301447244, 'fraction_numerical': 0.008782418669855276, 'mean_word_length': 2.962424440450907, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 13, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 6, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3337828', 'n_tokens_mistral': 7761, 'n_tokens_neox': 7528, 'n_words': 1893}