a1ad1e4c49
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.
158 lines
4.9 KiB
Python
158 lines
4.9 KiB
Python
#!/usr/bin/env python
|
||
# -*- coding: utf-8 -*-
|
||
"""
|
||
openslides.utils.main
|
||
~~~~~~~~~~~~~~~~~~~~~
|
||
|
||
Some functions for OpenSlides.
|
||
|
||
:copyright: 2011–2013 by OpenSlides team, see AUTHORS.
|
||
:license: GNU GPL, see LICENSE for more details.
|
||
"""
|
||
|
||
import ctypes
|
||
import os
|
||
import socket
|
||
import sys
|
||
import tempfile
|
||
|
||
|
||
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.
|
||
"""
|
||
# TODO: Delete this function after switch to Python 3.
|
||
if not isinstance(path, unicode):
|
||
filesystem_encoding = sys.getfilesystemencoding() or sys.getdefaultencoding()
|
||
path = path.decode(filesystem_encoding)
|
||
return path
|
||
|
||
|
||
def detect_openslides_type():
|
||
"""
|
||
Returns the type of this OpenSlides version.
|
||
"""
|
||
if sys.platform == 'win32':
|
||
if os.path.basename(sys.executable).lower() == 'openslides.exe':
|
||
# Note: sys.executable is the path of the *interpreter*
|
||
# the portable version embeds python so it *is* the interpreter.
|
||
# The wrappers generated by pip and co. will spawn the usual
|
||
# python(w).exe, so there is no danger of mistaking them
|
||
# for the portable even though they may also be called
|
||
# openslides.exe
|
||
openslides_type = WINDOWS_PORTABLE_VERSION
|
||
else:
|
||
openslides_type = WINDOWS_VERSION
|
||
else:
|
||
openslides_type = UNIX_VERSION
|
||
return openslides_type
|
||
|
||
|
||
def get_default_user_data_path(openslides_type):
|
||
"""
|
||
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.
|
||
"""
|
||
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():
|
||
"""
|
||
Returns the path to Windows' AppData directory.
|
||
"""
|
||
shell32 = ctypes.WinDLL("shell32.dll")
|
||
SHGetFolderPath = shell32.SHGetFolderPathW
|
||
SHGetFolderPath.argtypes = (
|
||
ctypes.c_void_p, ctypes.c_int, ctypes.c_void_p, ctypes.c_uint32,
|
||
ctypes.c_wchar_p)
|
||
SHGetFolderPath.restype = ctypes.c_uint32
|
||
|
||
CSIDL_LOCAL_APPDATA = 0x001c
|
||
MAX_PATH = 260
|
||
|
||
buf = ctypes.create_unicode_buffer(MAX_PATH)
|
||
res = SHGetFolderPath(0, CSIDL_LOCAL_APPDATA, 0, 0, buf)
|
||
if res != 0:
|
||
raise Exception("Could not determine Windows' APPDATA path")
|
||
|
||
return buf.value
|
||
|
||
|
||
def get_win32_portable_path():
|
||
"""
|
||
Returns the path to the Windows portable version.
|
||
"""
|
||
# NOTE: sys.executable will be the path to openslides.exe
|
||
# since it is essentially a small wrapper that embeds the
|
||
# python interpreter
|
||
portable_path = filesystem2unicode(os.path.dirname(os.path.abspath(sys.executable)))
|
||
try:
|
||
fd, test_file = tempfile.mkstemp(dir=portable_path)
|
||
except OSError:
|
||
raise PortableDirNotWritable(
|
||
'Portable directory is not writeable. '
|
||
'Please choose another directory for settings and data files.')
|
||
else:
|
||
os.close(fd)
|
||
os.unlink(test_file)
|
||
return portable_path
|
||
|
||
|
||
def get_portable_paths(name):
|
||
"""
|
||
Returns the paths for the Windows portable version on runtime for the
|
||
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('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
|