#!/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 os import sys import ctypes 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 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 is_portable(): """ Helper function just for the GUI. """ # TODO: Remove this function. return detect_openslides_type() == WINDOWS_PORTABLE_VERSION 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 deterime 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 local 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 and the media directory. The argument 'name' can be 'database' or 'media'. """ 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', '') else: raise TypeError('Unknow type %s' % name) return path