calibre/src/calibre/constants.py
2013-11-22 08:50:51 +05:30

296 lines
9.0 KiB
Python

from future_builtins import map
__license__ = 'GPL v3'
__copyright__ = '2008, Kovid Goyal kovid@kovidgoyal.net'
__docformat__ = 'restructuredtext en'
__appname__ = u'calibre'
numeric_version = (1, 12, 0)
__version__ = u'.'.join(map(unicode, numeric_version))
__author__ = u"Kovid Goyal <kovid@kovidgoyal.net>"
'''
Various run time constants.
'''
import sys, locale, codecs, os, importlib, collections
_plat = sys.platform.lower()
iswindows = 'win32' in _plat or 'win64' in _plat
isosx = 'darwin' in _plat
isnewosx = isosx and getattr(sys, 'new_app_bundle', False)
isfreebsd = 'freebsd' in _plat
isnetbsd = 'netbsd' in _plat
isdragonflybsd = 'dragonfly' in _plat
isbsd = isfreebsd or isnetbsd or isdragonflybsd
islinux = not(iswindows or isosx or isbsd)
isfrozen = hasattr(sys, 'frozen')
isunix = isosx or islinux
isportable = os.environ.get('CALIBRE_PORTABLE_BUILD', None) is not None
ispy3 = sys.version_info.major > 2
isxp = iswindows and sys.getwindowsversion().major < 6
is64bit = sys.maxsize > (1 << 32)
isworker = 'CALIBRE_WORKER' in os.environ or 'CALIBRE_SIMPLE_WORKER' in os.environ
if isworker:
os.environ.pop('CALIBRE_FORCE_ANSI', None)
try:
preferred_encoding = locale.getpreferredencoding()
codecs.lookup(preferred_encoding)
except:
preferred_encoding = 'utf-8'
win32event = importlib.import_module('win32event') if iswindows else None
winerror = importlib.import_module('winerror') if iswindows else None
win32api = importlib.import_module('win32api') if iswindows else None
fcntl = None if iswindows else importlib.import_module('fcntl')
_osx_ver = None
def get_osx_version():
global _osx_ver
if _osx_ver is None:
import platform
from collections import namedtuple
OSX = namedtuple('OSX', 'major minor tertiary')
try:
ver = platform.mac_ver()[0].split('.')
if len(ver) == 2:
ver.append(0)
_osx_ver = OSX(*(map(int, ver)))
except:
_osx_ver = OSX(0, 0, 0)
return _osx_ver
filesystem_encoding = sys.getfilesystemencoding()
if filesystem_encoding is None:
filesystem_encoding = 'utf-8'
else:
try:
if codecs.lookup(filesystem_encoding).name == 'ascii':
filesystem_encoding = 'utf-8'
# On linux, unicode arguments to os file functions are coerced to an ascii
# bytestring if sys.getfilesystemencoding() == 'ascii', which is
# just plain dumb. This is fixed by the icu.py module which, when
# imported changes ascii to utf-8
except:
filesystem_encoding = 'utf-8'
DEBUG = False
def debug():
global DEBUG
DEBUG = True
_cache_dir = None
def _get_cache_dir():
confcache = os.path.join(config_dir, u'caches')
if isportable:
return confcache
if 'CALIBRE_CACHE_DIRECTORY' in os.environ:
return os.path.abspath(os.environ['CALIBRE_CACHE_DIRECTORY'])
if iswindows:
w = plugins['winutil'][0]
candidate = os.path.join(w.special_folder_path(w.CSIDL_LOCAL_APPDATA), u'%s-cache'%__appname__)
elif isosx:
candidate = os.path.join(os.path.expanduser(u'~/Library/Caches'), __appname__)
else:
candidate = os.environ.get('XDG_CACHE_HOME', u'~/.cache')
candidate = os.path.join(os.path.expanduser(candidate),
__appname__)
if isinstance(candidate, bytes):
try:
candidate = candidate.decode(filesystem_encoding)
except ValueError:
candidate = confcache
if not os.path.exists(candidate):
try:
os.makedirs(candidate)
except:
candidate = confcache
return candidate
def cache_dir():
global _cache_dir
if _cache_dir is None:
_cache_dir = _get_cache_dir()
return _cache_dir
# plugins {{{
class Plugins(collections.Mapping):
def __init__(self):
self._plugins = {}
plugins = [
'pictureflow',
'lzx',
'msdes',
'magick',
'podofo',
'cPalmdoc',
'progress_indicator',
'chmlib',
'chm_extra',
'icu',
'speedup',
'freetype',
'woff',
'unrar',
'qt_hack',
'_regex'
]
if iswindows:
plugins.extend(['winutil', 'wpd', 'winfonts'])
if isosx:
plugins.append('usbobserver')
if islinux or isosx:
plugins.append('libusb')
plugins.append('libmtp')
self.plugins = frozenset(plugins)
def load_plugin(self, name):
if name in self._plugins:
return
sys.path.insert(0, sys.extensions_location)
try:
p, err = importlib.import_module(name), ''
except Exception as err:
p = None
err = str(err)
self._plugins[name] = (p, err)
sys.path.remove(sys.extensions_location)
def __iter__(self):
return iter(self.plugins)
def __len__(self):
return len(self.plugins)
def __contains__(self, name):
return name in self.plugins
def __getitem__(self, name):
if name not in self.plugins:
raise KeyError('No plugin named %r'%name)
self.load_plugin(name)
return self._plugins[name]
plugins = None
if plugins is None:
plugins = Plugins()
# }}}
# config_dir {{{
CONFIG_DIR_MODE = 0700
if 'CALIBRE_CONFIG_DIRECTORY' in os.environ:
config_dir = os.path.abspath(os.environ['CALIBRE_CONFIG_DIRECTORY'])
elif iswindows:
if plugins['winutil'][0] is None:
raise Exception(plugins['winutil'][1])
config_dir = plugins['winutil'][0].special_folder_path(plugins['winutil'][0].CSIDL_APPDATA)
if not os.access(config_dir, os.W_OK|os.X_OK):
config_dir = os.path.expanduser('~')
config_dir = os.path.join(config_dir, 'calibre')
elif isosx:
config_dir = os.path.expanduser('~/Library/Preferences/calibre')
else:
bdir = os.path.abspath(os.path.expanduser(os.environ.get('XDG_CONFIG_HOME', '~/.config')))
config_dir = os.path.join(bdir, 'calibre')
try:
os.makedirs(config_dir, mode=CONFIG_DIR_MODE)
except:
pass
if not os.path.exists(config_dir) or \
not os.access(config_dir, os.W_OK) or not \
os.access(config_dir, os.X_OK):
print 'No write acces to', config_dir, 'using a temporary dir instead'
import tempfile, atexit
config_dir = tempfile.mkdtemp(prefix='calibre-config-')
def cleanup_cdir():
try:
import shutil
shutil.rmtree(config_dir)
except:
pass
atexit.register(cleanup_cdir)
# }}}
def get_version():
'''Return version string for display to user '''
dv = os.environ.get('CALIBRE_DEVELOP_FROM', None)
v = __version__
if numeric_version[-1] == 0:
v = v[:-2]
if getattr(sys, 'frozen', False) and dv and os.path.abspath(dv) in sys.path:
v += '*'
if iswindows and is64bit:
v += ' [64bit]'
return v
def get_portable_base():
'Return path to the directory that contains calibre-portable.exe or None'
if isportable:
return os.path.dirname(os.path.dirname(os.environ['CALIBRE_PORTABLE_BUILD']))
def get_unicode_windows_env_var(name):
import ctypes
name = unicode(name)
n = ctypes.windll.kernel32.GetEnvironmentVariableW(name, None, 0)
if n == 0:
return None
buf = ctypes.create_unicode_buffer(u'\0'*n)
ctypes.windll.kernel32.GetEnvironmentVariableW(name, buf, n)
return buf.value
def get_windows_username():
'''
Return the user name of the currently loggen in user as a unicode string.
Note that usernames on windows are case insensitive, the case of the value
returned depends on what the user typed into the login box at login time.
'''
import ctypes
try:
advapi32 = ctypes.windll.advapi32
GetUserName = getattr(advapi32, u'GetUserNameW')
except AttributeError:
pass
else:
buf = ctypes.create_unicode_buffer(257)
n = ctypes.c_int(257)
if GetUserName(buf, ctypes.byref(n)):
return buf.value
return get_unicode_windows_env_var(u'USERNAME')
def get_windows_temp_path():
import ctypes
n = ctypes.windll.kernel32.GetTempPathW(0, None)
if n == 0:
return None
buf = ctypes.create_unicode_buffer(u'\0'*n)
ctypes.windll.kernel32.GetTempPathW(n, buf)
ans = buf.value
return ans if ans else None
def get_windows_user_locale_name():
import ctypes
k32 = ctypes.windll.kernel32
n = 200
buf = ctypes.create_unicode_buffer(u'\0'*n)
n = k32.GetUserDefaultLocaleName(buf, n)
if n == 0:
return None
return u'_'.join(buf.value.split(u'-')[:2])
def is_modern_webkit():
# Check if we are using QtWebKit >= 2.3
from PyQt4.QtWebKit import qWebKitMajorVersion
return qWebKitMajorVersion() >= 537