New command create-dev-settings. Clean up main script. Fix wrong path for Windows version.
This commit is contained in:
parent
cca201d446
commit
3ec18194fa
8
.gitignore
vendored
8
.gitignore
vendored
@ -7,10 +7,12 @@
|
|||||||
.virtualenv/*
|
.virtualenv/*
|
||||||
.venv/*
|
.venv/*
|
||||||
|
|
||||||
# Development settings and database
|
# Development user data (settings, database, media, search index)
|
||||||
settings.py
|
settings.py
|
||||||
database.sqlite
|
|
||||||
!tests/settings.py
|
!tests/settings.py
|
||||||
|
database.sqlite
|
||||||
|
media/*
|
||||||
|
whoosh_index/*
|
||||||
|
|
||||||
# Package building
|
# Package building
|
||||||
docs/_build/*
|
docs/_build/*
|
||||||
@ -21,4 +23,4 @@ dist/*
|
|||||||
|
|
||||||
# Unit test and coverage reports
|
# Unit test and coverage reports
|
||||||
.coverage
|
.coverage
|
||||||
htmlcov
|
htmlcov/*
|
||||||
|
@ -1,15 +0,0 @@
|
|||||||
#!/usr/bin/env python
|
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
|
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
|
|
||||||
script_path = os.path.realpath(os.path.dirname(__file__))
|
|
||||||
sys.path.append(os.path.join(script_path, '..', '..'))
|
|
||||||
|
|
||||||
from openslides.main import create_settings
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
cwd = os.getcwd()
|
|
||||||
create_settings(os.path.join(cwd, 'settings.py'),
|
|
||||||
os.path.join(cwd, 'database.sqlite'))
|
|
@ -11,77 +11,30 @@
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
import base64
|
|
||||||
import os
|
import os
|
||||||
import shutil
|
import shutil
|
||||||
import sys
|
import sys
|
||||||
import time
|
|
||||||
import threading
|
|
||||||
import webbrowser
|
|
||||||
|
|
||||||
from django.conf import ENVIRONMENT_VARIABLE
|
from django.conf import ENVIRONMENT_VARIABLE
|
||||||
from django.core.exceptions import ImproperlyConfigured
|
|
||||||
from django.core.management import execute_from_command_line
|
from django.core.management import execute_from_command_line
|
||||||
|
|
||||||
from openslides import get_version
|
from openslides import get_version
|
||||||
from openslides.utils.main import (
|
from openslides.utils.main import (
|
||||||
filesystem2unicode,
|
|
||||||
detect_openslides_type,
|
detect_openslides_type,
|
||||||
|
ensure_settings,
|
||||||
|
filesystem2unicode,
|
||||||
|
get_browser_url,
|
||||||
|
get_database_path_from_settings,
|
||||||
|
get_default_settings_path,
|
||||||
get_default_user_data_path,
|
get_default_user_data_path,
|
||||||
get_port,
|
get_port,
|
||||||
get_win32_app_data_path,
|
get_user_data_path_values_with_path,
|
||||||
get_win32_portable_path,
|
setup_django_settings_module,
|
||||||
UNIX_VERSION,
|
start_browser,
|
||||||
WINDOWS_VERSION,
|
write_settings)
|
||||||
WINDOWS_PORTABLE_VERSION)
|
|
||||||
from openslides.utils.tornado_webserver import run_tornado
|
from openslides.utils.tornado_webserver import run_tornado
|
||||||
|
|
||||||
|
|
||||||
SETTINGS_TEMPLATE = """# -*- coding: utf-8 -*-
|
|
||||||
#
|
|
||||||
# Settings file for OpenSlides
|
|
||||||
#
|
|
||||||
|
|
||||||
%(import_function)s
|
|
||||||
from openslides.global_settings import *
|
|
||||||
|
|
||||||
# Use 'DEBUG = True' to get more details for server errors. Default for releases: False
|
|
||||||
DEBUG = False
|
|
||||||
TEMPLATE_DEBUG = DEBUG
|
|
||||||
|
|
||||||
DATABASES = {
|
|
||||||
'default': {
|
|
||||||
'ENGINE': 'django.db.backends.sqlite3',
|
|
||||||
'NAME': %(database_path_value)s,
|
|
||||||
'USER': '',
|
|
||||||
'PASSWORD': '',
|
|
||||||
'HOST': '',
|
|
||||||
'PORT': '',
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# Set timezone
|
|
||||||
TIME_ZONE = 'Europe/Berlin'
|
|
||||||
|
|
||||||
# Make this unique, and don't share it with anybody.
|
|
||||||
SECRET_KEY = %(secret_key)r
|
|
||||||
|
|
||||||
# Add OpenSlides plugins to this list (see example entry in comment)
|
|
||||||
INSTALLED_PLUGINS = (
|
|
||||||
# 'pluginname',
|
|
||||||
)
|
|
||||||
|
|
||||||
INSTALLED_APPS += INSTALLED_PLUGINS
|
|
||||||
|
|
||||||
# Absolute path to the directory that holds media.
|
|
||||||
# Example: "/home/media/media.lawrence.com/"
|
|
||||||
MEDIA_ROOT = %(media_path_value)s
|
|
||||||
|
|
||||||
# Path to Whoosh search index
|
|
||||||
HAYSTACK_CONNECTIONS['default']['PATH'] = %(whoosh_index_path_value)s
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
"""
|
"""
|
||||||
Main entrance to OpenSlides.
|
Main entrance to OpenSlides.
|
||||||
@ -103,25 +56,8 @@ def main():
|
|||||||
# anything more here.
|
# anything more here.
|
||||||
settings = None
|
settings = None
|
||||||
|
|
||||||
# Create settings if if still does not exist.
|
|
||||||
if settings and not os.path.exists(settings):
|
|
||||||
# Setup path for user specific data (SQLite3 database, media, search index, ...):
|
|
||||||
# Take it either from command line or get default path
|
|
||||||
if hasattr(args, 'user_data_path') and args.user_data_path:
|
|
||||||
user_data_path_values = get_user_data_path_values(
|
|
||||||
user_data_path=args.user_data_path,
|
|
||||||
default=False)
|
|
||||||
else:
|
|
||||||
openslides_type = detect_openslides_type()
|
|
||||||
args.user_data_path = get_default_user_data_path(openslides_type)
|
|
||||||
user_data_path_values = get_user_data_path_values(
|
|
||||||
user_data_path=args.user_data_path,
|
|
||||||
default=True,
|
|
||||||
openslides_type=openslides_type)
|
|
||||||
create_settings(settings, user_data_path_values)
|
|
||||||
|
|
||||||
# Process the subcommand's callback
|
# Process the subcommand's callback
|
||||||
return args.callback(args)
|
return args.callback(settings, args)
|
||||||
|
|
||||||
|
|
||||||
def parse_args():
|
def parse_args():
|
||||||
@ -215,6 +151,12 @@ def parse_args():
|
|||||||
add_general_arguments(subcommand_deletedb, ('settings', 'user_data_path'))
|
add_general_arguments(subcommand_deletedb, ('settings', 'user_data_path'))
|
||||||
subcommand_deletedb.set_defaults(callback=deletedb)
|
subcommand_deletedb.set_defaults(callback=deletedb)
|
||||||
|
|
||||||
|
# Subcommand create-dev-settings
|
||||||
|
subcommand_create_dev_settings = subparsers.add_parser(
|
||||||
|
'create-dev-settings',
|
||||||
|
help='Create a settings file at current working directory for development use.')
|
||||||
|
subcommand_create_dev_settings.set_defaults(callback=create_dev_settings)
|
||||||
|
|
||||||
# Subcommand django
|
# Subcommand django
|
||||||
subcommand_django_command_line_utility = subparsers.add_parser(
|
subcommand_django_command_line_utility = subparsers.add_parser(
|
||||||
'django',
|
'django',
|
||||||
@ -277,107 +219,23 @@ def add_general_arguments(subcommand, arguments):
|
|||||||
subcommand.add_argument(*args, **kwargs)
|
subcommand.add_argument(*args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
def get_default_settings_path(openslides_type):
|
def start(settings, args):
|
||||||
"""
|
|
||||||
Returns the default settings path according to the OpenSlides type.
|
|
||||||
|
|
||||||
The argument 'openslides_type' has to be one of the three types mentioned in
|
|
||||||
openslides.utils.main.
|
|
||||||
"""
|
|
||||||
if openslides_type == UNIX_VERSION:
|
|
||||||
parent_directory = filesystem2unicode(os.environ.get(
|
|
||||||
'XDG_CONFIG_HOME', os.path.join(os.path.expanduser('~'), '.config')))
|
|
||||||
elif openslides_type == WINDOWS_VERSION:
|
|
||||||
parent_directory = get_win32_app_data_path()
|
|
||||||
elif openslides_type == WINDOWS_PORTABLE_VERSION:
|
|
||||||
parent_directory = get_win32_portable_path()
|
|
||||||
else:
|
|
||||||
raise TypeError('%s is not a valid OpenSlides type.' % openslides_type)
|
|
||||||
return os.path.join(parent_directory, 'openslides', 'settings.py')
|
|
||||||
|
|
||||||
|
|
||||||
def get_user_data_path_values(user_data_path, default=False, openslides_type=None):
|
|
||||||
"""
|
|
||||||
Returns a dictionary of the user specific data path values for the new
|
|
||||||
settings file.
|
|
||||||
|
|
||||||
The argument 'user_data_path' is a path to the directory where OpenSlides
|
|
||||||
should store the user specific data like SQLite3 database, media and search
|
|
||||||
index.
|
|
||||||
|
|
||||||
The argument 'default' is a simple flag. If it is True and the OpenSlides
|
|
||||||
type is the Windows portable version, the returned dictionary contains
|
|
||||||
strings of callable functions for the settings file, else it contains
|
|
||||||
string paths.
|
|
||||||
|
|
||||||
The argument 'openslides_type' can to be one of the three types mentioned in
|
|
||||||
openslides.utils.main.
|
|
||||||
"""
|
|
||||||
user_data_path_values = {}
|
|
||||||
if default and openslides_type == WINDOWS_PORTABLE_VERSION:
|
|
||||||
user_data_path_values['import_function'] = 'from openslides.utils.main import get_portable_paths'
|
|
||||||
user_data_path_values['database_path_value'] = "get_portable_paths('database')"
|
|
||||||
user_data_path_values['media_path_value'] = "get_portable_paths('media')"
|
|
||||||
user_data_path_values['whoosh_index_path_value'] = "get_portable_paths('whoosh_index')"
|
|
||||||
else:
|
|
||||||
user_data_path_values['import_function'] = ''
|
|
||||||
# TODO: Decide whether to use only absolute paths here.
|
|
||||||
user_data_path_values['database_path_value'] = "'%s'" % os.path.join(
|
|
||||||
user_data_path, 'openslides', 'database.sqlite')
|
|
||||||
# TODO: Decide whether to use only absolute paths here.
|
|
||||||
user_data_path_values['media_path_value'] = "'%s'" % os.path.join(
|
|
||||||
user_data_path, 'openslides', 'media', '')
|
|
||||||
# TODO: Decide whether to use only absolute paths here.
|
|
||||||
user_data_path_values['whoosh_index_path_value'] = "'%s'" % os.path.join(
|
|
||||||
user_data_path, 'openslides', 'whoosh_index', '')
|
|
||||||
return user_data_path_values
|
|
||||||
|
|
||||||
|
|
||||||
def create_settings(settings_path, user_data_path_values):
|
|
||||||
"""
|
|
||||||
Creates the settings file at the given path using the given values for the
|
|
||||||
file template.
|
|
||||||
"""
|
|
||||||
settings_module = os.path.realpath(os.path.dirname(settings_path))
|
|
||||||
if not os.path.exists(settings_module):
|
|
||||||
os.makedirs(settings_module)
|
|
||||||
context = {'secret_key': base64.b64encode(os.urandom(30))}
|
|
||||||
context.update(user_data_path_values)
|
|
||||||
settings_content = SETTINGS_TEMPLATE % context
|
|
||||||
with open(settings_path, 'w') as settings_file:
|
|
||||||
settings_file.write(settings_content)
|
|
||||||
print('Settings file at %s successfully created.' % settings_path)
|
|
||||||
|
|
||||||
|
|
||||||
def setup_django_settings_module(settings_path):
|
|
||||||
"""
|
|
||||||
Sets the environment variable ENVIRONMENT_VARIABLE, that means
|
|
||||||
'DJANGO_SETTINGS_MODULE', to the given settings.
|
|
||||||
"""
|
|
||||||
settings_file = os.path.basename(settings_path)
|
|
||||||
settings_module_name = ".".join(settings_file.split('.')[:-1])
|
|
||||||
if '.' in settings_module_name:
|
|
||||||
raise ImproperlyConfigured("'.' is not an allowed character in the settings-file")
|
|
||||||
settings_module_dir = os.path.dirname(settings_path) # TODO: Use absolute path here or not?
|
|
||||||
sys.path.insert(0, settings_module_dir)
|
|
||||||
os.environ[ENVIRONMENT_VARIABLE] = '%s' % settings_module_name
|
|
||||||
|
|
||||||
|
|
||||||
def start(args):
|
|
||||||
"""
|
"""
|
||||||
Starts OpenSlides: Runs syncdb and runs runserver (tornado webserver).
|
Starts OpenSlides: Runs syncdb and runs runserver (tornado webserver).
|
||||||
"""
|
"""
|
||||||
syncdb(args)
|
ensure_settings(settings, args)
|
||||||
|
syncdb(settings, args)
|
||||||
args.start_browser = not args.no_browser
|
args.start_browser = not args.no_browser
|
||||||
args.no_reload = False
|
args.no_reload = False
|
||||||
runserver(args)
|
runserver(settings, args)
|
||||||
|
|
||||||
|
|
||||||
def runserver(args):
|
def runserver(settings, args):
|
||||||
"""
|
"""
|
||||||
Runs tornado webserver. Runs the function start_browser if the respective
|
Runs tornado webserver. Runs the function start_browser if the respective
|
||||||
argument is given.
|
argument is given.
|
||||||
"""
|
"""
|
||||||
|
ensure_settings(settings, args)
|
||||||
port = get_port(address=args.address, port=args.port)
|
port = get_port(address=args.address, port=args.port)
|
||||||
if args.start_browser:
|
if args.start_browser:
|
||||||
browser_url = get_browser_url(address=args.address, port=port)
|
browser_url = get_browser_url(address=args.address, port=port)
|
||||||
@ -385,42 +243,11 @@ def runserver(args):
|
|||||||
run_tornado(args.address, port, not args.no_reload)
|
run_tornado(args.address, port, not args.no_reload)
|
||||||
|
|
||||||
|
|
||||||
def get_browser_url(address, port):
|
def syncdb(settings, args):
|
||||||
"""
|
|
||||||
Returns the url to open the web browser.
|
|
||||||
|
|
||||||
The argument 'address' should be an IP address. The argument 'port' should
|
|
||||||
be an integer.
|
|
||||||
"""
|
|
||||||
browser_url = 'http://'
|
|
||||||
if address == '0.0.0.0':
|
|
||||||
browser_url += 'localhost'
|
|
||||||
else:
|
|
||||||
browser_url += address
|
|
||||||
if not port == 80:
|
|
||||||
browser_url += ":%d" % port
|
|
||||||
return browser_url
|
|
||||||
|
|
||||||
|
|
||||||
def start_browser(browser_url):
|
|
||||||
"""
|
|
||||||
Launches the default web browser at the given url and opens the
|
|
||||||
webinterface.
|
|
||||||
"""
|
|
||||||
browser = webbrowser.get()
|
|
||||||
|
|
||||||
def function():
|
|
||||||
time.sleep(1)
|
|
||||||
browser.open(browser_url)
|
|
||||||
|
|
||||||
thread = threading.Thread(target=function)
|
|
||||||
thread.start()
|
|
||||||
|
|
||||||
|
|
||||||
def syncdb(args):
|
|
||||||
"""
|
"""
|
||||||
Run syncdb to create or update the database.
|
Run syncdb to create or update the database.
|
||||||
"""
|
"""
|
||||||
|
ensure_settings(settings, args)
|
||||||
# TODO: Check use of filesystem2unicode here.
|
# TODO: Check use of filesystem2unicode here.
|
||||||
path = filesystem2unicode(os.path.dirname(get_database_path_from_settings()))
|
path = filesystem2unicode(os.path.dirname(get_database_path_from_settings()))
|
||||||
if not os.path.exists(path):
|
if not os.path.exists(path):
|
||||||
@ -429,30 +256,11 @@ def syncdb(args):
|
|||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
|
||||||
def get_database_path_from_settings():
|
def createsuperuser(settings, args):
|
||||||
"""
|
|
||||||
Retrieves the database path out of the settings file. Returns None,
|
|
||||||
if it is not a SQLite3 database.
|
|
||||||
"""
|
|
||||||
from django.conf import settings as django_settings
|
|
||||||
from django.db import DEFAULT_DB_ALIAS
|
|
||||||
|
|
||||||
db_settings = django_settings.DATABASES
|
|
||||||
default = db_settings.get(DEFAULT_DB_ALIAS)
|
|
||||||
if not default:
|
|
||||||
raise Exception("Default databases is not configured")
|
|
||||||
database_path = default.get('NAME')
|
|
||||||
if not database_path:
|
|
||||||
raise Exception('No path specified for default database.')
|
|
||||||
if default.get('ENGINE') != 'django.db.backends.sqlite3':
|
|
||||||
database_path = None
|
|
||||||
return database_path
|
|
||||||
|
|
||||||
|
|
||||||
def createsuperuser(args):
|
|
||||||
"""
|
"""
|
||||||
Creates or resets the admin user. Returns 0 to show success.
|
Creates or resets the admin user. Returns 0 to show success.
|
||||||
"""
|
"""
|
||||||
|
ensure_settings(settings, args)
|
||||||
# can't be imported in global scope as it already requires
|
# can't be imported in global scope as it already requires
|
||||||
# the settings module during import
|
# the settings module during import
|
||||||
from openslides.participant.api import create_or_reset_admin_user
|
from openslides.participant.api import create_or_reset_admin_user
|
||||||
@ -463,10 +271,12 @@ def createsuperuser(args):
|
|||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
|
||||||
def backupdb(args):
|
def backupdb(settings, args):
|
||||||
"""
|
"""
|
||||||
Stores a backup copy of the SQlite3 database. Returns 0 on success, else 1.
|
Stores a backup copy of the SQlite3 database. Returns 0 on success, else 1.
|
||||||
"""
|
"""
|
||||||
|
ensure_settings(settings, args)
|
||||||
|
|
||||||
from django.db import connection, transaction
|
from django.db import connection, transaction
|
||||||
|
|
||||||
@transaction.commit_manually
|
@transaction.commit_manually
|
||||||
@ -496,10 +306,11 @@ def backupdb(args):
|
|||||||
return return_value
|
return return_value
|
||||||
|
|
||||||
|
|
||||||
def deletedb(args):
|
def deletedb(settings, args):
|
||||||
"""
|
"""
|
||||||
Deletes the sqlite3 database. Returns 0 on success, else 1.
|
Deletes the sqlite3 database. Returns 0 on success, else 1.
|
||||||
"""
|
"""
|
||||||
|
ensure_settings(settings, args)
|
||||||
database_path = get_database_path_from_settings()
|
database_path = get_database_path_from_settings()
|
||||||
if database_path and os.path.exists(database_path):
|
if database_path and os.path.exists(database_path):
|
||||||
os.remove(database_path)
|
os.remove(database_path)
|
||||||
@ -511,7 +322,24 @@ def deletedb(args):
|
|||||||
return return_value
|
return return_value
|
||||||
|
|
||||||
|
|
||||||
def django_command_line_utility(args):
|
def create_dev_settings(settings, args):
|
||||||
|
"""
|
||||||
|
Creates a settings file at the currect working directory for development use.
|
||||||
|
"""
|
||||||
|
settings = os.path.join(os.getcwd(), 'settings.py')
|
||||||
|
if not os.path.exists(settings):
|
||||||
|
context = get_user_data_path_values_with_path(os.getcwd())
|
||||||
|
context['debug'] = 'True'
|
||||||
|
write_settings(settings, **context)
|
||||||
|
print('Settings file at %s successfully created.' % settings)
|
||||||
|
return_value = 0
|
||||||
|
else:
|
||||||
|
print('Error: Settings file %s already exists.' % settings)
|
||||||
|
return_value = 1
|
||||||
|
return return_value
|
||||||
|
|
||||||
|
|
||||||
|
def django_command_line_utility(settings, args):
|
||||||
"""
|
"""
|
||||||
Runs Django's command line utility. Returns 0 on success, else 1.
|
Runs Django's command line utility. Returns 0 on success, else 1.
|
||||||
"""
|
"""
|
||||||
@ -528,6 +356,7 @@ def django_command_line_utility(args):
|
|||||||
"command line utility." % command)
|
"command line utility." % command)
|
||||||
return_value = 1
|
return_value = 1
|
||||||
else:
|
else:
|
||||||
|
ensure_settings(settings, args)
|
||||||
execute_from_command_line(args.django_args)
|
execute_from_command_line(args.django_args)
|
||||||
return_value = 0
|
return_value = 0
|
||||||
return return_value
|
return return_value
|
||||||
|
@ -15,6 +15,13 @@ import os
|
|||||||
import socket
|
import socket
|
||||||
import sys
|
import sys
|
||||||
import tempfile
|
import tempfile
|
||||||
|
import threading
|
||||||
|
import time
|
||||||
|
import webbrowser
|
||||||
|
|
||||||
|
from base64 import b64encode
|
||||||
|
from django.core.exceptions import ImproperlyConfigured
|
||||||
|
from django.conf import ENVIRONMENT_VARIABLE
|
||||||
|
|
||||||
|
|
||||||
UNIX_VERSION = 'Unix Version'
|
UNIX_VERSION = 'Unix Version'
|
||||||
@ -26,6 +33,10 @@ class PortableDirNotWritable(Exception):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class DatabaseInSettingsError(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
def filesystem2unicode(path):
|
def filesystem2unicode(path):
|
||||||
"""
|
"""
|
||||||
Transforms a path string to unicode according to the filesystem's encoding.
|
Transforms a path string to unicode according to the filesystem's encoding.
|
||||||
@ -57,6 +68,75 @@ def detect_openslides_type():
|
|||||||
return openslides_type
|
return openslides_type
|
||||||
|
|
||||||
|
|
||||||
|
def get_default_settings_path(openslides_type):
|
||||||
|
"""
|
||||||
|
Returns the default settings path according to the OpenSlides type.
|
||||||
|
|
||||||
|
The argument 'openslides_type' has to be one of the three types mentioned in
|
||||||
|
openslides.utils.main.
|
||||||
|
"""
|
||||||
|
if openslides_type == UNIX_VERSION:
|
||||||
|
parent_directory = filesystem2unicode(os.environ.get(
|
||||||
|
'XDG_CONFIG_HOME', os.path.join(os.path.expanduser('~'), '.config')))
|
||||||
|
elif openslides_type == WINDOWS_VERSION:
|
||||||
|
parent_directory = get_win32_app_data_path()
|
||||||
|
elif openslides_type == WINDOWS_PORTABLE_VERSION:
|
||||||
|
parent_directory = get_win32_portable_path()
|
||||||
|
else:
|
||||||
|
raise TypeError('%s is not a valid OpenSlides type.' % openslides_type)
|
||||||
|
return os.path.join(parent_directory, 'openslides', 'settings.py')
|
||||||
|
|
||||||
|
|
||||||
|
def setup_django_settings_module(settings_path):
|
||||||
|
"""
|
||||||
|
Sets the environment variable ENVIRONMENT_VARIABLE, that means
|
||||||
|
'DJANGO_SETTINGS_MODULE', to the given settings.
|
||||||
|
"""
|
||||||
|
settings_file = os.path.basename(settings_path)
|
||||||
|
settings_module_name = ".".join(settings_file.split('.')[:-1])
|
||||||
|
if '.' in settings_module_name:
|
||||||
|
raise ImproperlyConfigured("'.' is not an allowed character in the settings-file")
|
||||||
|
settings_module_dir = os.path.dirname(settings_path) # TODO: Use absolute path here or not?
|
||||||
|
sys.path.insert(0, settings_module_dir)
|
||||||
|
os.environ[ENVIRONMENT_VARIABLE] = '%s' % settings_module_name
|
||||||
|
|
||||||
|
|
||||||
|
def ensure_settings(settings, args):
|
||||||
|
"""
|
||||||
|
Create settings if a settings path is given and this file still does not exist.
|
||||||
|
"""
|
||||||
|
if settings and not os.path.exists(settings):
|
||||||
|
if not hasattr(args, 'user_data_path'):
|
||||||
|
context = get_default_settings_context()
|
||||||
|
else:
|
||||||
|
context = get_default_settings_context(args.user_data_path)
|
||||||
|
write_settings(settings, **context)
|
||||||
|
print('Settings file at %s successfully created.' % settings)
|
||||||
|
|
||||||
|
|
||||||
|
def get_default_settings_context(user_data_path=None):
|
||||||
|
"""
|
||||||
|
Returns the default context values for the settings template.
|
||||||
|
|
||||||
|
The argument 'user_data_path' is a given path for user specific data or None.
|
||||||
|
"""
|
||||||
|
# Setup path for user specific data (SQLite3 database, media, search index, ...):
|
||||||
|
# Take it either from command line or get default path
|
||||||
|
if user_data_path:
|
||||||
|
default_context = get_user_data_path_values(
|
||||||
|
user_data_path=user_data_path,
|
||||||
|
default=False)
|
||||||
|
else:
|
||||||
|
openslides_type = detect_openslides_type()
|
||||||
|
user_data_path = get_default_user_data_path(openslides_type)
|
||||||
|
default_context = get_user_data_path_values(
|
||||||
|
user_data_path=user_data_path,
|
||||||
|
default=True,
|
||||||
|
openslides_type=openslides_type)
|
||||||
|
default_context['debug'] = 'False'
|
||||||
|
return default_context
|
||||||
|
|
||||||
|
|
||||||
def get_default_user_data_path(openslides_type):
|
def get_default_user_data_path(openslides_type):
|
||||||
"""
|
"""
|
||||||
Returns the default path for user specific data according to the OpenSlides
|
Returns the default path for user specific data according to the OpenSlides
|
||||||
@ -119,6 +199,71 @@ def get_win32_portable_path():
|
|||||||
return portable_path
|
return portable_path
|
||||||
|
|
||||||
|
|
||||||
|
def get_user_data_path_values(user_data_path, default=False, openslides_type=None):
|
||||||
|
"""
|
||||||
|
Returns a dictionary of the user specific data path values for the new
|
||||||
|
settings file.
|
||||||
|
|
||||||
|
The argument 'user_data_path' is a path to the directory where OpenSlides
|
||||||
|
should store the user specific data like SQLite3 database, media and search
|
||||||
|
index.
|
||||||
|
|
||||||
|
The argument 'default' is a simple flag. If it is True and the OpenSlides
|
||||||
|
type is the Windows portable version, the returned dictionary contains
|
||||||
|
strings of callable functions for the settings file, else it contains
|
||||||
|
string paths.
|
||||||
|
|
||||||
|
The argument 'openslides_type' can to be one of the three types mentioned in
|
||||||
|
openslides.utils.main.
|
||||||
|
"""
|
||||||
|
if default and openslides_type == WINDOWS_PORTABLE_VERSION:
|
||||||
|
user_data_path_values = {}
|
||||||
|
user_data_path_values['import_function'] = 'from openslides.utils.main import get_portable_paths'
|
||||||
|
user_data_path_values['database_path_value'] = "get_portable_paths('database')"
|
||||||
|
user_data_path_values['media_path_value'] = "get_portable_paths('media')"
|
||||||
|
user_data_path_values['whoosh_index_path_value'] = "get_portable_paths('whoosh_index')"
|
||||||
|
else:
|
||||||
|
user_data_path_values = get_user_data_path_values_with_path(user_data_path, 'openslides')
|
||||||
|
return user_data_path_values
|
||||||
|
|
||||||
|
|
||||||
|
def get_user_data_path_values_with_path(*paths):
|
||||||
|
"""
|
||||||
|
Returns a dictionary of the user specific data path values for the new
|
||||||
|
settings file. Therefor it uses the given arguments as parts of the path.
|
||||||
|
"""
|
||||||
|
final_path = os.path.abspath(os.path.join(*paths))
|
||||||
|
user_data_path_values = {}
|
||||||
|
user_data_path_values['import_function'] = ''
|
||||||
|
variables = (('database_path_value', 'database.sqlite'),
|
||||||
|
('media_path_value', 'media'),
|
||||||
|
('whoosh_index_path_value', 'whoosh_index'))
|
||||||
|
for key, value in variables:
|
||||||
|
path_list = [final_path, value]
|
||||||
|
if '.' not in value:
|
||||||
|
path_list.append('')
|
||||||
|
user_data_path_values[key] = repr(
|
||||||
|
filesystem2unicode(os.path.join(*path_list)))
|
||||||
|
return user_data_path_values
|
||||||
|
|
||||||
|
|
||||||
|
def write_settings(settings_path, template=None, **context):
|
||||||
|
"""
|
||||||
|
Creates the settings file at the given path using the given values for the
|
||||||
|
file template.
|
||||||
|
"""
|
||||||
|
if template is None:
|
||||||
|
with open(os.path.join(os.path.dirname(__file__), 'settings.py.tpl')) as template_file:
|
||||||
|
template = template_file.read()
|
||||||
|
context.setdefault('secret_key', b64encode(os.urandom(30)))
|
||||||
|
content = template % context
|
||||||
|
settings_module = os.path.realpath(os.path.dirname(settings_path))
|
||||||
|
if not os.path.exists(settings_module):
|
||||||
|
os.makedirs(settings_module)
|
||||||
|
with open(settings_path, 'w') as settings_file:
|
||||||
|
settings_file.write(content)
|
||||||
|
|
||||||
|
|
||||||
def get_portable_paths(name):
|
def get_portable_paths(name):
|
||||||
"""
|
"""
|
||||||
Returns the paths for the Windows portable version on runtime for the
|
Returns the paths for the Windows portable version on runtime for the
|
||||||
@ -155,3 +300,56 @@ def get_port(address, port):
|
|||||||
finally:
|
finally:
|
||||||
s.close()
|
s.close()
|
||||||
return port
|
return port
|
||||||
|
|
||||||
|
|
||||||
|
def get_browser_url(address, port):
|
||||||
|
"""
|
||||||
|
Returns the url to open the web browser.
|
||||||
|
|
||||||
|
The argument 'address' should be an IP address. The argument 'port' should
|
||||||
|
be an integer.
|
||||||
|
"""
|
||||||
|
browser_url = 'http://'
|
||||||
|
if address == '0.0.0.0':
|
||||||
|
browser_url += 'localhost'
|
||||||
|
else:
|
||||||
|
browser_url += address
|
||||||
|
if not port == 80:
|
||||||
|
browser_url += ":%d" % port
|
||||||
|
return browser_url
|
||||||
|
|
||||||
|
|
||||||
|
def start_browser(browser_url):
|
||||||
|
"""
|
||||||
|
Launches the default web browser at the given url and opens the
|
||||||
|
webinterface.
|
||||||
|
"""
|
||||||
|
browser = webbrowser.get()
|
||||||
|
|
||||||
|
def function():
|
||||||
|
# TODO: Use a nonblocking sleep event here. Tornado has such features.
|
||||||
|
time.sleep(1)
|
||||||
|
browser.open(browser_url)
|
||||||
|
|
||||||
|
thread = threading.Thread(target=function)
|
||||||
|
thread.start()
|
||||||
|
|
||||||
|
|
||||||
|
def get_database_path_from_settings():
|
||||||
|
"""
|
||||||
|
Retrieves the database path out of the settings file. Returns None,
|
||||||
|
if it is not a SQLite3 database.
|
||||||
|
"""
|
||||||
|
from django.conf import settings as django_settings
|
||||||
|
from django.db import DEFAULT_DB_ALIAS
|
||||||
|
|
||||||
|
db_settings = django_settings.DATABASES
|
||||||
|
default = db_settings.get(DEFAULT_DB_ALIAS)
|
||||||
|
if not default:
|
||||||
|
raise DatabaseInSettingsError("Default databases is not configured")
|
||||||
|
database_path = default.get('NAME')
|
||||||
|
if not database_path:
|
||||||
|
raise DatabaseInSettingsError('No path specified for default database.')
|
||||||
|
if default.get('ENGINE') != 'django.db.backends.sqlite3':
|
||||||
|
database_path = None
|
||||||
|
return database_path
|
||||||
|
42
openslides/utils/settings.py.tpl
Normal file
42
openslides/utils/settings.py.tpl
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# Settings file for OpenSlides
|
||||||
|
#
|
||||||
|
|
||||||
|
%(import_function)s
|
||||||
|
from openslides.global_settings import *
|
||||||
|
|
||||||
|
# Use 'DEBUG = True' to get more details for server errors. Default for releases: False
|
||||||
|
DEBUG = %(debug)s
|
||||||
|
TEMPLATE_DEBUG = DEBUG
|
||||||
|
|
||||||
|
DATABASES = {
|
||||||
|
'default': {
|
||||||
|
'ENGINE': 'django.db.backends.sqlite3',
|
||||||
|
'NAME': %(database_path_value)s,
|
||||||
|
'USER': '',
|
||||||
|
'PASSWORD': '',
|
||||||
|
'HOST': '',
|
||||||
|
'PORT': '',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Set timezone
|
||||||
|
TIME_ZONE = 'Europe/Berlin'
|
||||||
|
|
||||||
|
# Make this unique, and don't share it with anybody.
|
||||||
|
SECRET_KEY = %(secret_key)r
|
||||||
|
|
||||||
|
# Add OpenSlides plugins to this list (see example entry in comment)
|
||||||
|
INSTALLED_PLUGINS = (
|
||||||
|
# 'pluginname',
|
||||||
|
)
|
||||||
|
|
||||||
|
INSTALLED_APPS += INSTALLED_PLUGINS
|
||||||
|
|
||||||
|
# Absolute path to the directory that holds media.
|
||||||
|
# Example: "/home/media/media.lawrence.com/"
|
||||||
|
MEDIA_ROOT = %(media_path_value)s
|
||||||
|
|
||||||
|
# Path to Whoosh search index
|
||||||
|
HAYSTACK_CONNECTIONS['default']['PATH'] = %(whoosh_index_path_value)s
|
@ -6,6 +6,7 @@ Fabric==1.8.0
|
|||||||
coverage==3.7
|
coverage==3.7
|
||||||
django-discover-runner==1.0
|
django-discover-runner==1.0
|
||||||
flake8==2.0
|
flake8==2.0
|
||||||
|
mock==1.0.1
|
||||||
|
|
||||||
# Requirements for OpenSlides handbook/documentation
|
# Requirements for OpenSlides handbook/documentation
|
||||||
Sphinx==1.2b3
|
Sphinx==1.2b3
|
||||||
|
@ -1,21 +1,19 @@
|
|||||||
#!/usr/bin/env python
|
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# Settings file for OpenSlides' tests
|
||||||
|
#
|
||||||
|
|
||||||
import os
|
|
||||||
|
|
||||||
from openslides.global_settings import * # noqa
|
from openslides.global_settings import * # noqa
|
||||||
|
|
||||||
# Use 'DEBUG = True' to get more details for server errors
|
# Use 'DEBUG = True' to get more details for server errors. Default for releases: False
|
||||||
# (Default for releases: 'False')
|
|
||||||
DEBUG = True
|
DEBUG = True
|
||||||
TEMPLATE_DEBUG = DEBUG
|
TEMPLATE_DEBUG = DEBUG
|
||||||
|
|
||||||
DBPATH = ''
|
|
||||||
|
|
||||||
DATABASES = {
|
DATABASES = {
|
||||||
'default': {
|
'default': {
|
||||||
'ENGINE': 'django.db.backends.sqlite3',
|
'ENGINE': 'django.db.backends.sqlite3',
|
||||||
'NAME': DBPATH,
|
'NAME': '',
|
||||||
'USER': '',
|
'USER': '',
|
||||||
'PASSWORD': '',
|
'PASSWORD': '',
|
||||||
'HOST': '',
|
'HOST': '',
|
||||||
@ -40,5 +38,6 @@ INSTALLED_APPS += INSTALLED_PLUGINS
|
|||||||
# Example: "/home/media/media.lawrence.com/"
|
# Example: "/home/media/media.lawrence.com/"
|
||||||
MEDIA_ROOT = os.path.realpath(os.path.dirname(__file__))
|
MEDIA_ROOT = os.path.realpath(os.path.dirname(__file__))
|
||||||
|
|
||||||
# Use RAM storage for whoosh index
|
# Path to Whoosh search index
|
||||||
|
# Use RAM storage
|
||||||
HAYSTACK_CONNECTIONS['default']['STORAGE'] = 'ram'
|
HAYSTACK_CONNECTIONS['default']['STORAGE'] = 'ram'
|
||||||
|
@ -13,32 +13,31 @@ import sys
|
|||||||
|
|
||||||
from django.core.exceptions import ImproperlyConfigured
|
from django.core.exceptions import ImproperlyConfigured
|
||||||
|
|
||||||
from openslides.__main__ import (
|
|
||||||
get_default_settings_path,
|
|
||||||
get_browser_url,
|
|
||||||
get_user_data_path_values,
|
|
||||||
setup_django_settings_module)
|
|
||||||
from openslides.utils.test import TestCase
|
|
||||||
from openslides.utils.main import (
|
from openslides.utils.main import (
|
||||||
|
get_browser_url,
|
||||||
|
get_default_settings_path,
|
||||||
get_default_user_data_path,
|
get_default_user_data_path,
|
||||||
|
get_user_data_path_values,
|
||||||
|
setup_django_settings_module,
|
||||||
UNIX_VERSION,
|
UNIX_VERSION,
|
||||||
WINDOWS_PORTABLE_VERSION)
|
WINDOWS_PORTABLE_VERSION)
|
||||||
|
from openslides.utils.test import TestCase
|
||||||
|
|
||||||
|
|
||||||
class TestFunctions(TestCase):
|
class TestFunctions(TestCase):
|
||||||
def test_get_default_user_data_path(self):
|
def test_get_default_user_data_path(self):
|
||||||
self.assertTrue('.local/share' in get_default_user_data_path(UNIX_VERSION))
|
self.assertIn(os.path.join('.local', 'share'), get_default_user_data_path(UNIX_VERSION))
|
||||||
|
|
||||||
def test_get_default_settings_path(self):
|
def test_get_default_settings_path(self):
|
||||||
self.assertTrue('.config/openslides/settings.py' in get_default_settings_path(UNIX_VERSION))
|
self.assertIn(
|
||||||
|
os.path.join('.config', 'openslides', 'settings.py'), get_default_settings_path(UNIX_VERSION))
|
||||||
|
|
||||||
def test_get_user_data_path_values_case_one(self):
|
def test_get_user_data_path_values_case_one(self):
|
||||||
self.assertEqual(
|
values = get_user_data_path_values('/test_path_dfhvndshfgsef', default=False)
|
||||||
get_user_data_path_values('test_path_dfhvndshfgsef', default=False),
|
self.assertEqual(values['import_function'], '')
|
||||||
{'import_function': '',
|
self.assertIn('database.sqlite', values['database_path_value'])
|
||||||
'database_path_value': "'test_path_dfhvndshfgsef/openslides/database.sqlite'",
|
self.assertIn('media', values['media_path_value'])
|
||||||
'media_path_value': "'test_path_dfhvndshfgsef/openslides/media/'",
|
self.assertIn('whoosh_index', values['whoosh_index_path_value'])
|
||||||
'whoosh_index_path_value': "'test_path_dfhvndshfgsef/openslides/whoosh_index/'"})
|
|
||||||
|
|
||||||
def test_get_user_data_path_values_case_two(self):
|
def test_get_user_data_path_values_case_two(self):
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
|
Loading…
Reference in New Issue
Block a user