From a1ad1e4c491671a289d4b1e4d3623af30c66730e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Norman=20J=C3=A4ckel?= Date: Sun, 13 Oct 2013 17:17:56 +0200 Subject: [PATCH] Some changes in __main__.py and utils.main and other. Reinsert --no-browser option. Move some code to utils.main. Some other small style changes. Fix merge conflict misstakes. Change settings behavior. Add tests. Fix rebase problems. --- extras/openslides_gui/gui.py | 25 ++-- manage.py | 1 - openslides/__main__.py | 267 +++++++++++++++++----------------- openslides/global_settings.py | 4 +- openslides/utils/main.py | 62 ++++++-- tests/utils/test_main.py | 67 +++++++++ 6 files changed, 267 insertions(+), 159 deletions(-) create mode 100644 tests/utils/test_main.py diff --git a/extras/openslides_gui/gui.py b/extras/openslides_gui/gui.py index a934865e0..4d46233c3 100755 --- a/extras/openslides_gui/gui.py +++ b/extras/openslides_gui/gui.py @@ -15,17 +15,15 @@ import threading import wx import openslides + from openslides.utils.main import ( - filesystem2unicode, - is_portable, detect_openslides_type, + filesystem2unicode, + get_default_user_data_path, + get_port, get_win32_portable_path, ) -from openslides.__main__ import ( - get_port, - get_default_settings_path -) # NOTE: djangos translation module can't be used here since it requires # a defined settings module @@ -346,12 +344,14 @@ class MainWindow(wx.Frame): self.SetIcons(icons) self.server_running = False + + # Set path for gui settings to default user data according to the + # OpenSlides type. This does not depend on any argument the user might + # type in. openslides_type = detect_openslides_type() - # XXX: this works, but I'd prefer keeping get_user_config_path - # it was much clearer what path was intended IMHO ... + default_user_data_path = get_default_user_data_path(openslides_type) self.gui_settings_path = os.path.join( - os.path.dirname(get_default_settings_path(openslides_type)), - "gui_settings.json") + default_user_data_path, 'openslides', 'gui_settings.json') self.backupdb_enabled = False self.backupdb_destination = "" @@ -633,9 +633,8 @@ class MainWindow(wx.Frame): else: args = ["--address", self._host, "--port", self._port] - # XXX: --no-browser is missing - #if not self.cb_start_browser.GetValue(): - # args.append("--no-browser") + if not self.cb_start_browser.GetValue(): + args.append("--no-browser") self.server_running = True self.cmd_run_ctrl.run_command("start", *args) diff --git a/manage.py b/manage.py index 281159766..5dd79adc8 100644 --- a/manage.py +++ b/manage.py @@ -9,7 +9,6 @@ import sys - from openslides.__main__ import main diff --git a/openslides/__main__.py b/openslides/__main__.py index 6296d3688..74c1af3c4 100644 --- a/openslides/__main__.py +++ b/openslides/__main__.py @@ -12,28 +12,29 @@ import argparse import base64 -import imp import os import shutil -import socket import sys import time import threading import webbrowser from django.conf import ENVIRONMENT_VARIABLE +from django.core.exceptions import ImproperlyConfigured from django.core.management import execute_from_command_line from openslides import get_version -from openslides.utils.tornado_webserver import run_tornado from openslides.utils.main import ( filesystem2unicode, detect_openslides_type, + get_default_user_data_path, + get_port, get_win32_app_data_path, get_win32_portable_path, UNIX_VERSION, WINDOWS_VERSION, WINDOWS_PORTABLE_VERSION) +from openslides.utils.tornado_webserver import run_tornado SETTINGS_TEMPLATE = """# -*- coding: utf-8 -*- @@ -75,6 +76,9 @@ 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 """ @@ -86,25 +90,35 @@ def main(): args = parse_args() # Setup settings path: Take it either from command line or get default path - if not hasattr(args, 'settings') or not args.settings: - openslides_type = detect_openslides_type() - args.settings = get_default_settings_path(openslides_type) + if hasattr(args, 'settings') and args.settings: + settings = args.settings + setup_django_settings_module(settings) + else: + if ENVIRONMENT_VARIABLE not in os.environ: + openslides_type = detect_openslides_type() + settings = get_default_settings_path(openslides_type) + setup_django_settings_module(settings) + else: + # The environment variable is set, so we do not need to process + # anything more here. + settings = None # Create settings if if still does not exist. - if not os.path.exists(args.settings): - # Setup path for local data (SQLite3 database, media, search index, ...): + 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 not hasattr(args, 'localpath') or not args.localpath: - openslides_type = detect_openslides_type() - args.localpath = get_default_local_path(openslides_type) - localpath_values = get_localpath_values(localpath=args.localpath, default=True, openslides_type=openslides_type) + 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: - localpath_values = get_localpath_values(localpath=args.localpath, default=False) - create_settings(args.settings, localpath_values) - - # Setup DJANGO_SETTINGS_MODULE environment variable - if 'DJANGO_SETTINGS_MODULE' not in os.environ: - setup_django_settings_module(args.settings) + 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 return args.callback(args) @@ -118,62 +132,48 @@ def parse_args(): if len(sys.argv) == 1: sys.argv.append('start') + # Init parser description = 'Start script for OpenSlides.' if 'manage.py' not in sys.argv[0]: description += (' If it is called without any argument, this will be ' 'treated as if it is called with the "start" subcommand. ' - 'That means OpenSlides will setup settings and database, ' - 'start the tornado webserver, launch the default web ' - 'browser and open the webinterface.') - + 'That means OpenSlides will setup default settings and ' + 'database, start the tornado webserver, launch the ' + 'default web browser and open the webinterface.') parser = argparse.ArgumentParser(description=description) + # Add version argument parser.add_argument( '--version', action='version', version=get_version(), help='Show version number and exit.') + # Init subparsers subparsers = parser.add_subparsers( dest='subcommand', title='Available subcommands', - description="Type 'python %s --help' for help on a specific subcommand." % parser.prog, + description="Type 'python %s --help' for help on a " + "specific subcommand." % parser.prog, help='You can choose only one subcommand at once.') - settings_args, settings_kwargs = ( - ('-s', '--settings'), - dict(help='Path to settings file.')) - localpath_args, localpath_kwargs = ( - ('-l', '--localpath'), - dict(help='Path to the directory for local files like SQLite3 database, ' - 'uploaded media and search index. This is only used, when a new ' - 'settings file is created.')) - address_args, address_kwargs = ( - ('-a', '--address',), - dict(default='0.0.0.0', help='IP address to listen on. Default is %(default)s.')) - port_args, port_kwargs = ( - ('-p', '--port'), - dict(type=int, default=80, help='Port to listen on. Default as admin or root is %(default)d, else 8000.')) - # Subcommand start subcommand_start = subparsers.add_parser( 'start', help='Setup settings and database, start tornado webserver, launch the ' 'default web browser and open the webinterface.') - subcommand_start.add_argument(*settings_args, **settings_kwargs) - subcommand_start.add_argument(*localpath_args, **localpath_kwargs) - subcommand_start.add_argument(*address_args, **address_kwargs) - subcommand_start.add_argument(*port_args, **port_kwargs) + add_general_arguments(subcommand_start, ('settings', 'user_data_path', 'address', 'port')) + subcommand_start.add_argument( + '--no-browser', + action='store_true', + help='Do not launch the default web browser.') subcommand_start.set_defaults(callback=start) # Subcommand runserver subcommand_runserver = subparsers.add_parser( 'runserver', help='Run OpenSlides using tornado webserver.') - subcommand_runserver.add_argument(*settings_args, **settings_kwargs) - subcommand_runserver.add_argument(*localpath_args, **localpath_kwargs) - subcommand_runserver.add_argument(*address_args, **address_kwargs) - subcommand_runserver.add_argument(*port_args, **port_kwargs) + add_general_arguments(subcommand_runserver, ('settings', 'user_data_path', 'address', 'port')) subcommand_runserver.add_argument( '--start-browser', action='store_true', @@ -188,24 +188,21 @@ def parse_args(): subcommand_syncdb = subparsers.add_parser( 'syncdb', help='Create or update database tables.') - subcommand_syncdb.add_argument(*settings_args, **settings_kwargs) - subcommand_syncdb.add_argument(*localpath_args, **localpath_kwargs) + add_general_arguments(subcommand_syncdb, ('settings', 'user_data_path')) subcommand_syncdb.set_defaults(callback=syncdb) # Subcommand createsuperuser subcommand_createsuperuser = subparsers.add_parser( 'createsuperuser', help="Make sure the user 'admin' exists and uses 'admin' as password.") - subcommand_createsuperuser.add_argument(*settings_args, **settings_kwargs) - subcommand_createsuperuser.add_argument(*localpath_args, **localpath_kwargs) + add_general_arguments(subcommand_createsuperuser, ('settings', 'user_data_path')) subcommand_createsuperuser.set_defaults(callback=createsuperuser) # Subcommand backupdb subcommand_backupdb = subparsers.add_parser( 'backupdb', - help='Store a backup copy of the SQLite3 database.') - subcommand_backupdb.add_argument(*settings_args, **settings_kwargs) - subcommand_backupdb.add_argument(*localpath_args, **localpath_kwargs) + help='Store a backup copy of the SQLite3 database at the given path.') + add_general_arguments(subcommand_backupdb, ('settings', 'user_data_path')) subcommand_backupdb.add_argument( 'path', help='Path to the backup file. An existing file will be overwritten.') @@ -215,14 +212,14 @@ def parse_args(): subcommand_deletedb = subparsers.add_parser( 'deletedb', help='Delete the SQLite3 database.') - subcommand_deletedb.add_argument(*settings_args, **settings_kwargs) - subcommand_deletedb.add_argument(*localpath_args, **localpath_kwargs) + add_general_arguments(subcommand_deletedb, ('settings', 'user_data_path')) subcommand_deletedb.set_defaults(callback=deletedb) # Subcommand django subcommand_django_command_line_utility = subparsers.add_parser( 'django', - description="Link to Django's command-line utility. Type 'python %s django help' for more help on this." % parser.prog, + description="Link to Django's command-line utility. Type " + "'python %s django help' for more help on this." % parser.prog, help="Call Django's command-line utility.") subcommand_django_command_line_utility.set_defaults( callback=django_command_line_utility, @@ -241,6 +238,45 @@ def parse_args(): return known_args +def add_general_arguments(subcommand, arguments): + """ + Adds the named arguments to the subcommand. + """ + general_arguments = {} + openslides_type = detect_openslides_type() + + general_arguments['settings'] = ( + ('-s', '--settings'), + dict(help="Path to settings file. If this isn't provided, the " + "%s environment variable will be used. " + "If this isn't provided too, a default path according to the " + "OpenSlides type will be used. At the moment it is %s" % ( + ENVIRONMENT_VARIABLE, + get_default_settings_path(openslides_type)))) + general_arguments['user_data_path'] = ( + ('-d', '--user-data-path'), + dict(help='Path to the directory for user specific data files like SQLite3 ' + 'database, uploaded media and search index. This is only used, ' + 'when a new settings file is created. The given path is only ' + 'written into the new settings file. Default according to the ' + 'OpenSlides is at the moment %s' % get_default_user_data_path(openslides_type))) + general_arguments['address'] = ( + ('-a', '--address',), + dict(default='0.0.0.0', help='IP address to listen on. Default is %(default)s.')) + general_arguments['port'] = ( + ('-p', '--port'), + dict(type=int, + default=80, + help='Port to listen on. Default as admin or root is %(default)d, else 8000.')) + + for argument in arguments: + try: + args, kwargs = general_arguments[argument] + except KeyError: + raise TypeError('The argument %s is not a valid general argument.' % argument) + subcommand.add_argument(*args, **kwargs) + + def get_default_settings_path(openslides_type): """ Returns the default settings path according to the OpenSlides type. @@ -260,54 +296,44 @@ def get_default_settings_path(openslides_type): return os.path.join(parent_directory, 'openslides', 'settings.py') -def get_default_local_path(openslides_type): +def get_user_data_path_values(user_data_path, default=False, openslides_type=None): """ - Returns the default local path according to the OpenSlides type. + Returns a dictionary of the user specific data path values for the new + settings file. - The argument 'openslides_type' has to be one of the three types mentioned in - openslides.utils.main. - """ - if openslides_type == UNIX_VERSION: - default_local_path = filesystem2unicode(os.environ.get( - 'XDG_DATA_HOME', os.path.join(os.path.expanduser('~'), '.local', 'share'))) - elif openslides_type == WINDOWS_VERSION: - default_local_path = get_win32_app_data_path() - elif openslides_type == WINDOWS_PORTABLE_VERSION: - default_local_path = get_win32_portable_path() - else: - raise TypeError('%s is not a valid OpenSlides type.' % openslides_type) - return default_local_path - - -def get_localpath_values(localpath, default=False, openslides_type=None): - """ - Returns the local path values for the new settings file. - - The argument 'localpath' is a path to the directory where OpenSlides should - store the local data like SQLite3 database, media and search index. + 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, this function returns callable - functions for the settings file, else it returns string paths. + 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. """ - localpath_values = {} + user_data_path_values = {} if default and openslides_type == WINDOWS_PORTABLE_VERSION: - localpath_values['import_function'] = 'from openslides.utils.main import get_portable_paths' - localpath_values['database_path_value'] = "get_portable_paths('database')" - localpath_values['media_path_value'] = "get_portable_paths('media')" + 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: - localpath_values['import_function'] = '' + user_data_path_values['import_function'] = '' # TODO: Decide whether to use only absolute paths here. - localpath_values['database_path_value'] = "'%s'" % os.path.join(localpath, 'openslides', 'database.sqlite') + 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. - localpath_values['media_path_value'] = "'%s'" % os.path.join(localpath, 'openslides', 'media', '') - return localpath_values + 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, local_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. @@ -316,7 +342,7 @@ def create_settings(settings_path, local_path_values): if not os.path.exists(settings_module): os.makedirs(settings_module) context = {'secret_key': base64.b64encode(os.urandom(30))} - context.update(local_path_values) + context.update(user_data_path_values) settings_content = SETTINGS_TEMPLATE % context with open(settings_path, 'w') as settings_file: settings_file.write(settings_content) @@ -325,25 +351,24 @@ def create_settings(settings_path, local_path_values): def setup_django_settings_module(settings_path): """ - Sets the environment variable DJANGO_SETTINGS_MODULE to the given settings. + 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]) + 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) + 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) with - the flag 'start_browser'. + Starts OpenSlides: Runs syncdb and runs runserver (tornado webserver). """ syncdb(args) - args.start_browser = True + args.start_browser = not args.no_browser args.no_reload = False runserver(args) @@ -360,27 +385,6 @@ def runserver(args): run_tornado(args.address, port, not args.no_reload) -def get_port(address, port): - """ - Returns the port for the server. If port 80 is given, checks if it is - available. If not returns port 8000. - - The argument 'address' should be an IP address. The argument 'port' should - be an integer. - """ - if port == 80: - # test if we can use port 80 - s = socket.socket() - try: - s.bind((address, port)) - s.listen(-1) - except socket.error: - port = 8000 - finally: - s.close() - return port - - def get_browser_url(address, port): """ Returns the url to open the web browser. @@ -418,15 +422,16 @@ def syncdb(args): Run syncdb to create or update the database. """ # TODO: Check use of filesystem2unicode here. - path = filesystem2unicode(os.path.dirname(get_database_path_from_settings(args.settings))) + path = filesystem2unicode(os.path.dirname(get_database_path_from_settings())) if not os.path.exists(path): os.makedirs(path) execute_from_command_line(["", "syncdb", "--noinput"]) + return 0 -def get_database_path_from_settings(settings_path): +def get_database_path_from_settings(): """ - Retrieves the database path out of the given settings file. Returns None, + 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 @@ -460,7 +465,7 @@ def createsuperuser(args): def backupdb(args): """ - Stores a backup copy of the SQlite3 database. + Stores a backup copy of the SQlite3 database. Returns 0 on success, else 1. """ from django.db import connection, transaction @@ -474,18 +479,19 @@ def backupdb(args): # now copy the file try: shutil.copy(src_path, dest_path) - except IOError as e: + except IOError: raise Exception("Database backup failed.") # and release the lock again transaction.commit() - database_path = get_database_path_from_settings(args.settings) + database_path = get_database_path_from_settings() if database_path: do_backup(database_path, args.path) print('Database %s successfully stored at %s.' % (database_path, args.path)) return_value = 0 else: - print('Error: Default database is not SQLite3. Only SQLite3 databases can currently be backuped.') + print('Error: Default database is not SQLite3. Only SQLite3 databases ' + 'can currently be backuped.') return_value = 1 return return_value @@ -494,7 +500,7 @@ def deletedb(args): """ Deletes the sqlite3 database. Returns 0 on success, else 1. """ - database_path = get_database_path_from_settings(args.settings) + database_path = get_database_path_from_settings() if database_path and os.path.exists(database_path): os.remove(database_path) print('SQLite3 database file %s successfully deleted.' % database_path) @@ -518,7 +524,8 @@ def django_command_line_utility(args): else: command = None if command: - print("Error: The command '%s' is disabled for use via Django's command line utility." % command) + print("Error: The command '%s' is disabled in OpenSlides for use via Django's " + "command line utility." % command) return_value = 1 else: execute_from_command_line(args.django_args) diff --git a/openslides/global_settings.py b/openslides/global_settings.py index f3e3b806b..b1d533af0 100644 --- a/openslides/global_settings.py +++ b/openslides/global_settings.py @@ -67,11 +67,9 @@ STATICFILES_DIRS = ( filesystem2unicode(os.path.join(SITE_ROOT, 'static')), ) -#XXX: Note this setting (as well as our workaround finder) -# can be removed again once django-bug-#18404 has been resolved STATICFILES_FINDERS = ( 'django.contrib.staticfiles.finders.FileSystemFinder', - 'openslides.utils.staticfiles.AppDirectoriesFinder', + 'django.contrib.staticfiles.finders.AppDirectoriesFinder', ) MESSAGE_STORAGE = 'django.contrib.messages.storage.cookie.CookieStorage' diff --git a/openslides/utils/main.py b/openslides/utils/main.py index c258257af..2a2c7dfe9 100644 --- a/openslides/utils/main.py +++ b/openslides/utils/main.py @@ -10,9 +10,10 @@ :license: GNU GPL, see LICENSE for more details. """ -import os -import sys import ctypes +import os +import socket +import sys import tempfile @@ -20,9 +21,11 @@ UNIX_VERSION = 'Unix Version' WINDOWS_VERSION = 'Windows Version' WINDOWS_PORTABLE_VERSION = 'Windows Portable Version' + class PortableDirNotWritable(Exception): pass + def filesystem2unicode(path): """ Transforms a path string to unicode according to the filesystem's encoding. @@ -36,7 +39,7 @@ def filesystem2unicode(path): def detect_openslides_type(): """ - Returns the type of this version. + Returns the type of this OpenSlides version. """ if sys.platform == 'win32': if os.path.basename(sys.executable).lower() == 'openslides.exe': @@ -54,12 +57,24 @@ def detect_openslides_type(): return openslides_type -def is_portable(): +def get_default_user_data_path(openslides_type): """ - Helper function just for the GUI. + Returns the default path for user specific data according to the OpenSlides + type. + + The argument 'openslides_type' has to be one of the three types mentioned + in openslides.utils.main. """ - # TODO: Remove this function. - return detect_openslides_type() == WINDOWS_PORTABLE_VERSION + if openslides_type == UNIX_VERSION: + default_user_data_path = filesystem2unicode(os.environ.get( + 'XDG_DATA_HOME', os.path.join(os.path.expanduser('~'), '.local', 'share'))) + elif openslides_type == WINDOWS_VERSION: + default_user_data_path = get_win32_app_data_path() + elif openslides_type == WINDOWS_PORTABLE_VERSION: + default_user_data_path = get_win32_portable_path() + else: + raise TypeError('%s is not a valid OpenSlides type.' % openslides_type) + return default_user_data_path def get_win32_app_data_path(): @@ -79,7 +94,7 @@ def get_win32_app_data_path(): buf = ctypes.create_unicode_buffer(MAX_PATH) res = SHGetFolderPath(0, CSIDL_LOCAL_APPDATA, 0, 0, buf) if res != 0: - raise Exception("Could not deterime APPDATA path") + raise Exception("Could not determine Windows' APPDATA path") return buf.value @@ -97,7 +112,7 @@ def get_win32_portable_path(): except OSError: raise PortableDirNotWritable( 'Portable directory is not writeable. ' - 'Please choose another directory for settings and local files.') + 'Please choose another directory for settings and data files.') else: os.close(fd) os.unlink(test_file) @@ -107,13 +122,36 @@ def get_win32_portable_path(): def get_portable_paths(name): """ Returns the paths for the Windows portable version on runtime for the - SQLite3 database and the media directory. The argument 'name' can be - 'database' or 'media'. + SQLite3 database, the media directory and the search index. The argument + 'name' can be 'database', 'media' or 'whoosh_index'. """ if name == 'database': path = os.path.join(get_win32_portable_path(), 'openslides', 'database.sqlite') elif name == 'media': path = os.path.join(get_win32_portable_path(), 'openslides', 'media', '') + elif name == 'whoosh_index': + path = os.path.join(get_win32_portable_path(), 'openslides', 'whoosh_index', '') else: - raise TypeError('Unknow type %s' % name) + raise TypeError('Unknown type %s' % name) return path + + +def get_port(address, port): + """ + Returns the port for the server. If port 80 is given, checks if it is + available. If not returns port 8000. + + The argument 'address' should be an IP address. The argument 'port' should + be an integer. + """ + if port == 80: + # test if we can use port 80 + s = socket.socket() + try: + s.bind((address, port)) + s.listen(-1) + except socket.error: + port = 8000 + finally: + s.close() + return port diff --git a/tests/utils/test_main.py b/tests/utils/test_main.py new file mode 100644 index 000000000..2361b10b3 --- /dev/null +++ b/tests/utils/test_main.py @@ -0,0 +1,67 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +""" + Tests for openslides.utils.main + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + :copyright: 2011–2013 by OpenSlides team, see AUTHORS. + :license: GNU GPL, see LICENSE for more details. +""" + +import os +import sys + +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 ( + get_default_user_data_path, + UNIX_VERSION, + WINDOWS_PORTABLE_VERSION) + + +class TestFunctions(TestCase): + def test_get_default_user_data_path(self): + self.assertTrue('.local/share' in get_default_user_data_path(UNIX_VERSION)) + + def test_get_default_settings_path(self): + self.assertTrue('.config/openslides/settings.py' in get_default_settings_path(UNIX_VERSION)) + + def test_get_user_data_path_values_case_one(self): + self.assertEqual( + get_user_data_path_values('test_path_dfhvndshfgsef', default=False), + {'import_function': '', + 'database_path_value': "'test_path_dfhvndshfgsef/openslides/database.sqlite'", + 'media_path_value': "'test_path_dfhvndshfgsef/openslides/media/'", + 'whoosh_index_path_value': "'test_path_dfhvndshfgsef/openslides/whoosh_index/'"}) + + def test_get_user_data_path_values_case_two(self): + self.assertEqual( + get_user_data_path_values('test_path_dfhvndshfgsef', default=True, openslides_type=WINDOWS_PORTABLE_VERSION), + {'import_function': 'from openslides.utils.main import get_portable_paths', + 'database_path_value': "get_portable_paths('database')", + 'media_path_value': "get_portable_paths('media')", + 'whoosh_index_path_value': "get_portable_paths('whoosh_index')"}) + + def test_setup_django_settings_module(self): + setup_django_settings_module('test_dir_dhvnghfjdh456fzheg2f/test_path_bngjdhc756dzwncshdfnx.py') + self.assertEqual(os.environ['DJANGO_SETTINGS_MODULE'], 'test_path_bngjdhc756dzwncshdfnx') + self.assertEqual(sys.path[0], 'test_dir_dhvnghfjdh456fzheg2f') + + def test_setup_django_settings_module_error(self): + self.assertRaisesMessage( + ImproperlyConfigured, + "'.' is not an allowed character in the settings-file", + setup_django_settings_module, + 'wrong.file.py') + + def test_get_browser_url(self): + self.assertEqual(get_browser_url('123.456.789.365', 6789), 'http://123.456.789.365:6789') + self.assertEqual(get_browser_url('123.456.789.365', 80), 'http://123.456.789.365') + self.assertEqual(get_browser_url('0.0.0.0', 6789), 'http://localhost:6789') + self.assertEqual(get_browser_url('0.0.0.0', 80), 'http://localhost')