Refactor configpaths

- init configpaths earlier so logging can access it to store debug logs
- First step for more consistency across Gajim when looking up paths

  Recommended usage for the future:
  app.configpaths.get()
  configpaths.get()
This commit is contained in:
Philipp Hörist 2018-04-21 12:44:10 +02:00
parent 8e9c040acf
commit 4a26ecb12c
13 changed files with 117 additions and 110 deletions

View File

@ -36,7 +36,6 @@ from distutils.version import LooseVersion as V
from collections import namedtuple
import gi
import nbxmpp
import hashlib
from gi.repository import GLib
@ -63,24 +62,26 @@ glog = logging.getLogger('gajim')
logger = None
# For backwards compatibility needed
# some plugins use that
gajimpaths = configpaths.gajimpaths
VCARD_PATH = gajimpaths['VCARD']
AVATAR_PATH = gajimpaths['AVATAR']
MY_EMOTS_PATH = gajimpaths['MY_EMOTS']
MY_ICONSETS_PATH = gajimpaths['MY_ICONSETS']
MY_MOOD_ICONSETS_PATH = gajimpaths['MY_MOOD_ICONSETS']
MY_ACTIVITY_ICONSETS_PATH = gajimpaths['MY_ACTIVITY_ICONSETS']
MY_CACERTS = gajimpaths['MY_CACERTS']
MY_PEER_CERTS_PATH = gajimpaths['MY_PEER_CERTS']
TMP = gajimpaths['TMP']
DATA_DIR = gajimpaths['DATA']
ICONS_DIR = gajimpaths['ICONS']
HOME_DIR = gajimpaths['HOME']
PLUGINS_DIRS = [gajimpaths['PLUGINS_BASE'],
gajimpaths['PLUGINS_USER']]
PLUGINS_CONFIG_DIR = gajimpaths['PLUGINS_CONFIG_DIR']
MY_CERT_DIR = gajimpaths['MY_CERT']
VCARD_PATH = configpaths.get('VCARD')
AVATAR_PATH = configpaths.get('AVATAR')
MY_EMOTS_PATH = configpaths.get('MY_EMOTS')
MY_ICONSETS_PATH = configpaths.get('MY_ICONSETS')
MY_MOOD_ICONSETS_PATH = configpaths.get('MY_MOOD_ICONSETS')
MY_ACTIVITY_ICONSETS_PATH = configpaths.get('MY_ACTIVITY_ICONSETS')
MY_CACERTS = configpaths.get('MY_CACERTS')
MY_PEER_CERTS_PATH = configpaths.get('MY_PEER_CERTS')
TMP = configpaths.get('TMP')
DATA_DIR = configpaths.get('DATA')
ICONS_DIR = configpaths.get('ICONS')
HOME_DIR = configpaths.get('HOME')
PLUGINS_DIRS = [configpaths.get('PLUGINS_BASE'),
configpaths.get('PLUGINS_USER')]
PLUGINS_CONFIG_DIR = configpaths.get('PLUGINS_CONFIG_DIR')
MY_CERT_DIR = configpaths.get('MY_CERT')
RecentGroupchat = namedtuple('RecentGroupchat', ['room', 'server', 'nickname'])

View File

@ -188,9 +188,8 @@ def check_and_possibly_move_config():
vars['MY_MOOD_ICONSETS_PATH'] = app.MY_MOOD_ICONSETS_PATH
vars['MY_ACTIVITY_ICONSETS_PATH'] = app.MY_ACTIVITY_ICONSETS_PATH
from gajim.common import configpaths
MY_DATA = configpaths.gajimpaths['MY_DATA']
MY_CONFIG = configpaths.gajimpaths['MY_CONFIG']
MY_CACHE = configpaths.gajimpaths['MY_CACHE']
MY_DATA = configpaths.get('MY_DATA')
MY_CONFIG = configpaths.get('MY_CONFIG')
if os.path.exists(LOG_DB_PATH):
# File already exists
@ -273,11 +272,11 @@ def check_and_possibly_create_paths():
VCARD_PATH = app.VCARD_PATH
AVATAR_PATH = app.AVATAR_PATH
from gajim.common import configpaths
MY_DATA = configpaths.gajimpaths['MY_DATA']
MY_CONFIG = configpaths.gajimpaths['MY_CONFIG']
MY_CACHE = configpaths.gajimpaths['MY_CACHE']
XTLS_CERTS = configpaths.gajimpaths['MY_PEER_CERTS']
LOCAL_XTLS_CERTS = configpaths.gajimpaths['MY_CERT']
MY_DATA = configpaths.get('MY_DATA')
MY_CONFIG = configpaths.get('MY_CONFIG')
MY_CACHE = configpaths.get('MY_CACHE')
XTLS_CERTS = configpaths.get('MY_PEER_CERTS')
LOCAL_XTLS_CERTS = configpaths.get('MY_CERT')
PLUGINS_CONFIG_PATH = app.PLUGINS_CONFIG_DIR

View File

@ -27,31 +27,13 @@ import sys
import tempfile
from enum import Enum, unique
@unique
class Type(Enum):
CONFIG = 0
CACHE = 1
DATA = 2
# Note on path and filename encodings:
#
# In general it is very difficult to do this correctly.
# We may pull information from environment variables, and what encoding that is
# in is anyone's guess. Any information we request directly from the file
# system will be in filesystemencoding, and (parts of) paths that we write in
# this source code will be in whatever encoding the source is in. (I hereby
# declare this file to be UTF-8 encoded.)
#
# To make things more complicated, modern Windows filesystems use UTF-16, but
# the API tends to hide this from us.
#
# I tried to minimize problems by passing Unicode strings to OS functions as
# much as possible. Hopefully this makes the function return an Unicode string
# as well. If not, we get an 8-bit string in filesystemencoding, which we can
# happily pass to functions that operate on files and directories, so we can
# just leave it as is. Since these paths are meant to be internal to Gajim and
# not displayed to the user, Unicode is not really necessary here.
def windowsify(s):
if os.name == 'nt':
@ -60,29 +42,41 @@ def windowsify(s):
def get(key):
return gajimpaths[key]
return _paths[key]
def set_separation(active: bool):
_paths.profile_separation = active
def set_profile(profile: str):
_paths.profile = profile
def set_config_root(config_root: str):
_paths.config_root = config_root
def init():
_paths.init()
class ConfigPaths:
def __init__(self):
# {'name': (type, path), } type can be Type.CONFIG, Type.CACHE, Type.DATA
# or None
self.paths = {}
self.profile = ''
self.profile_separation = False
self.config_root = None
if os.name == 'nt':
try:
# Documents and Settings\[User Name]\Application Data\Gajim
# How are we supposed to know what encoding the environment
# variable 'appdata' is in? Assuming it to be in filesystem
# encoding.
self.config_root = self.cache_root = self.data_root = \
os.path.join(os.environ['appdata'], 'Gajim')
except KeyError:
# win9x, in cwd
self.config_root = self.cache_root = self.data_root = '.'
else: # Unices
# Pass in an Unicode string, and hopefully get one back.
else:
expand = os.path.expanduser
base = os.getenv('XDG_CONFIG_HOME')
if base is None or base[0] != '/':
@ -128,40 +122,45 @@ class ConfigPaths:
for key in self.paths.keys():
yield (key, self[key])
def init(self, root=None, profile='', profile_separation=False):
if root is not None:
self.config_root = self.cache_root = self.data_root = root
def init(self):
if self.config_root is not None:
self.cache_root = self.data_root = self.config_root
self.init_profile(profile)
self.add('CONFIG_ROOT', None, self.config_root)
self.add('CACHE_ROOT', None, self.cache_root)
self.add('DATA_ROOT', None, self.data_root)
if len(profile) > 0 and profile_separation:
profile = u'.' + profile
self.init_profile(self.profile)
if len(self.profile) > 0 and self.profile_separation:
self.profile = u'.' + self.profile
else:
profile = ''
self.profile = ''
d = {'LOG_DB': 'logs.db', 'MY_CACERTS': 'cacerts.pem',
'MY_EMOTS': 'emoticons', 'MY_ICONSETS': 'iconsets',
'MY_MOOD_ICONSETS': 'moods', 'MY_ACTIVITY_ICONSETS': 'activities',
'PLUGINS_USER': 'plugins'}
'MY_EMOTS': 'emoticons', 'MY_ICONSETS': 'iconsets',
'MY_MOOD_ICONSETS': 'moods', 'MY_ACTIVITY_ICONSETS': 'activities',
'PLUGINS_USER': 'plugins'}
for name in d:
d[name] += profile
d[name] += self.profile
self.add(name, Type.DATA, windowsify(d[name]))
if len(profile):
if len(self.profile):
self.add('MY_DATA', Type.DATA, 'data.dir')
else:
self.add('MY_DATA', Type.DATA, '')
d = {'CACHE_DB': 'cache.db', 'VCARD': 'vcards',
'AVATAR': 'avatars'}
d = {'CACHE_DB': 'cache.db',
'VCARD': 'vcards',
'AVATAR': 'avatars'}
for name in d:
d[name] += profile
d[name] += self.profile
self.add(name, Type.CACHE, windowsify(d[name]))
if len(profile):
if len(self.profile):
self.add('MY_CACHE', Type.CACHE, 'cache.dir')
else:
self.add('MY_CACHE', Type.CACHE, '')
if len(profile):
if len(self.profile):
self.add('MY_CONFIG', Type.CONFIG, 'config.dir')
else:
self.add('MY_CONFIG', Type.CONFIG, '')
@ -169,8 +168,8 @@ class ConfigPaths:
try:
self.add('TMP', None, tempfile.gettempdir())
except IOError as e:
print('Error opening tmp folder: %s\nUsing %s' % (str(e),
os.path.expanduser('~')), file=sys.stderr)
print('Error opening tmp folder: %s\nUsing %s' % (
str(e), os.path.expanduser('~')), file=sys.stderr)
self.add('TMP', None, os.path.expanduser('~'))
def init_profile(self, profile):
@ -193,4 +192,9 @@ class ConfigPaths:
self.add('PLUGINS_CONFIG_DIR', Type.CONFIG, pluginsconfdir)
self.add('MY_CERT', Type.CONFIG, localcertsdir)
gajimpaths = ConfigPaths()
_paths = ConfigPaths()
# For backwards compatibility needed
# some plugins use that
gajimpaths = _paths

View File

@ -853,8 +853,7 @@ def play_sound(event):
path_to_soundfile = app.config.get_per('soundevents', event, 'path')
play_sound_file(path_to_soundfile)
def check_soundfile_path(file_, dirs=(app.gajimpaths.data_root,
app.DATA_DIR)):
def check_soundfile_path(file_, dirs=None):
"""
Check if the sound file exists
@ -863,6 +862,10 @@ app.DATA_DIR)):
(eg: ~/.gajim/sounds/, DATADIR/sounds...).
:return the path to file or None if it doesn't exists.
"""
if dirs is None:
dirs = [app.configpaths.get('DATA_ROOT'),
app.DATA_DIR]
if not file_:
return None
elif os.path.exists(file_):
@ -874,8 +877,7 @@ app.DATA_DIR)):
return d
return None
def strip_soundfile_path(file_, dirs=(app.gajimpaths.data_root,
app.DATA_DIR), abs=True):
def strip_soundfile_path(file_, dirs=None, abs=True):
"""
Remove knowns paths from a sound file
@ -888,6 +890,10 @@ app.DATA_DIR), abs=True):
if not file_:
return None
if dirs is None:
dirs = [app.configpaths.get('DATA_ROOT'),
app.DATA_DIR]
name = os.path.basename(file_)
for d in dirs:
d = os.path.join(d, 'sounds', name)

View File

@ -120,7 +120,7 @@ class JingleFileTransfer(JingleContent):
}
if jingle_xtls.PYOPENSSL_PRESENT:
cert_name = os.path.join(configpaths.gajimpaths['MY_CERT'],
cert_name = os.path.join(configpaths.get('MY_CERT'),
jingle_xtls.SELF_SIGNED_CERTIFICATE)
if not (os.path.exists(cert_name + '.cert')
and os.path.exists(cert_name + '.pkey')):

View File

@ -42,12 +42,13 @@ from enum import IntEnum, unique
from gajim.common import exceptions
from gajim.common import app
from gajim.common import configpaths
import sqlite3 as sqlite
LOG_DB_PATH = app.gajimpaths['LOG_DB']
LOG_DB_PATH = configpaths.get('LOG_DB')
LOG_DB_FOLDER, LOG_DB_FILE = os.path.split(LOG_DB_PATH)
CACHE_DB_PATH = app.gajimpaths['CACHE_DB']
CACHE_DB_PATH = configpaths.get('CACHE_DB')
import logging
log = logging.getLogger('gajim.c.logger')

View File

@ -53,6 +53,7 @@ gi.require_version('Pango', '1.0')
from gi.repository import GLib, Gio, Gtk
from gajim.common import i18n
from gajim.common import configpaths
from gajim.common import logging_helpers
MIN_NBXMPP_VER = "0.6.4"
@ -112,9 +113,6 @@ class GajimApplication(Gtk.Application):
self.connect('startup', self._startup)
self.connect('activate', self._activate)
self.profile = ''
self.config_path = None
self.profile_separation = False
self.interface = None
GLib.set_prgname('gajim')
@ -157,10 +155,6 @@ class GajimApplication(Gtk.Application):
sys.exit(1)
# Create and initialize Application Paths & Databases
from gajim.common import configpaths
configpaths.gajimpaths.init(
self.config_path, self.profile, self.profile_separation)
from gajim.common import app
from gajim.common import check_paths
from gajim.common import exceptions
@ -209,7 +203,7 @@ class GajimApplication(Gtk.Application):
# libintl = ctypes.cdll.LoadLibrary(libintl_path)
# libintl.bindtextdomain(APP, DIR)
# libintl.bind_textdomain_codeset(APP, 'UTF-8')
# plugins_locale_dir = os.path.join(common.configpaths.gajimpaths[
# plugins_locale_dir = os.path.join(common.configpaths[
# 'PLUGINS_USER'], 'locale').encode(locale.getpreferredencoding())
# libintl.bindtextdomain('gajim_plugins', plugins_locale_dir)
# libintl.bind_textdomain_codeset('gajim_plugins', 'UTF-8')
@ -345,23 +339,22 @@ class GajimApplication(Gtk.Application):
def _handle_local_options(self, application,
options: GLib.VariantDict) -> int:
# Parse all options that have to be executed before ::startup
logging_helpers.init()
if options.contains('profile'):
# Incorporate profile name into application id
# to have a single app instance for each profile.
profile = options.lookup_value('profile').get_string()
app_id = '%s.%s' % (self.get_application_id(), profile)
self.set_application_id(app_id)
self.profile = profile
configpaths.set_profile(profile)
if options.contains('separate'):
self.profile_separation = True
configpaths.set_separation(True)
if options.contains('config-path'):
self.config_path = options.lookup_value('config-path').get_string()
if options.contains('version'):
from gajim import __version__
print(__version__)
return 0
path = options.lookup_value('config-path').get_string()
configpaths.set_config_root(path)
configpaths.init()
logging_helpers.init()
if options.contains('quiet'):
logging_helpers.set_quiet()
if options.contains('verbose'):

View File

@ -107,11 +107,10 @@ from threading import Thread
from gajim.common import ged
from gajim.common.caps_cache import muc_caps_cache
from gajim.common.configpaths import gajimpaths
config_filename = gajimpaths['CONFIG_FILE']
from gajim.common import configpaths
from gajim.common import optparser
parser = optparser.OptionsParser(config_filename)
parser = optparser.OptionsParser(configpaths.get('CONFIG_FILE'))
import logging
log = logging.getLogger('gajim.interface')

View File

@ -67,8 +67,9 @@ def parseOpts():
config_path = parseOpts()
del parseOpts
import gajim.common.configpaths
gajim.common.configpaths.gajimpaths.init(config_path)
from gajim.common import configpaths
configpaths.set_config_root(config_path)
configpaths.init()
del config_path
from gajim.common import app
from gajim import gtkgui_helpers

View File

@ -48,8 +48,8 @@ import urllib
if __name__ == '__main__':
from gajim.common import i18n
import gajim.common.configpaths
gajim.common.configpaths.gajimpaths.init(None)
from gajim.common import configpaths
configpaths.init()
from gajim.common import app
from gajim import gtkgui_helpers
from gajim.gtkgui_helpers import get_icon_pixmap

View File

@ -19,7 +19,7 @@
## along with Gajim. If not, see <http://www.gnu.org/licenses/>.
##
from gajim.common.configpaths import gajimpaths
from gajim.common import configpaths
import Crypto
from gajim.common import crypto
@ -28,9 +28,10 @@ from gajim.common import exceptions
import os
import pickle
secrets_filename = gajimpaths['SECRETS_FILE']
secrets_filename = configpaths.get('SECRETS_FILE')
secrets_cache = None
class Secrets():
def __init__(self, filename):
self.filename = filename

View File

@ -37,8 +37,9 @@ def setup_env():
os.mkdir(configdir)
os.mkdir(pluginsconfigdir)
import gajim.common.configpaths
gajim.common.configpaths.gajimpaths.init(configdir)
from gajim.common import configpaths
configpaths.set_config_root(configdir)
configpaths.init()
# for some reason gajim.common.app needs to be imported before xmpppy?
from gajim.common import app

View File

@ -49,8 +49,9 @@ if os.path.isdir(configdir):
os.mkdir(configdir)
import gajim.common.configpaths
gajim.common.configpaths.gajimpaths.init(configdir)
from gajim.common import configpaths
configpaths.set_config_root(configdir)
configpaths.init()
# for some reason common.app needs to be imported before xmpppy?
from gajim.common import app