comparison sat/tools/config.py @ 3028:ab2696e34d29

Python 3 port: /!\ this is a huge commit /!\ starting from this commit, SàT is needs Python 3.6+ /!\ SàT maybe be instable or some feature may not work anymore, this will improve with time This patch port backend, bridge and frontends to Python 3. Roughly this has been done this way: - 2to3 tools has been applied (with python 3.7) - all references to python2 have been replaced with python3 (notably shebangs) - fixed files not handled by 2to3 (notably the shell script) - several manual fixes - fixed issues reported by Python 3 that where not handled in Python 2 - replaced "async" with "async_" when needed (it's a reserved word from Python 3.7) - replaced zope's "implements" with @implementer decorator - temporary hack to handle data pickled in database, as str or bytes may be returned, to be checked later - fixed hash comparison for password - removed some code which is not needed anymore with Python 3 - deactivated some code which needs to be checked (notably certificate validation) - tested with jp, fixed reported issues until some basic commands worked - ported Primitivus (after porting dependencies like urwid satext) - more manual fixes
author Goffi <goffi@goffi.org>
date Tue, 13 Aug 2019 19:08:41 +0200
parents 121c4a2a567c
children 98d1f34ce5b9
comparison
equal deleted inserted replaced
3027:ff5bcb12ae60 3028:ab2696e34d29
1 #!/usr/bin/env python2 1 #!/usr/bin/env python3
2 # -*- coding: utf-8 -*- 2 # -*- coding: utf-8 -*-
3 3
4 # SAT: a jabber client 4 # SAT: a jabber client
5 # Copyright (C) 2009-2019 Jérôme Poisson (goffi@goffi.org) 5 # Copyright (C) 2009-2019 Jérôme Poisson (goffi@goffi.org)
6 # Copyright (C) 2013-2016 Adrien Cossa (souliane@mailoo.org) 6 # Copyright (C) 2013-2016 Adrien Cossa (souliane@mailoo.org)
21 """ Configuration related useful methods """ 21 """ Configuration related useful methods """
22 22
23 import os 23 import os
24 import csv 24 import csv
25 import json 25 import json
26 from ConfigParser import SafeConfigParser, DEFAULTSECT, NoOptionError, NoSectionError 26 from configparser import SafeConfigParser, DEFAULTSECT, NoOptionError, NoSectionError
27 from xdg import BaseDirectory 27 from xdg import BaseDirectory
28 from sat.core.log import getLogger 28 from sat.core.log import getLogger
29 from sat.core.constants import Const as C 29 from sat.core.constants import Const as C
30 from sat.core.i18n import _ 30 from sat.core.i18n import _
31 from sat.core import exceptions 31 from sat.core import exceptions
46 target_file = None 46 target_file = None
47 for file_ in C.CONFIG_FILES[::-1]: 47 for file_ in C.CONFIG_FILES[::-1]:
48 # we will eventually update the existing file with the highest priority, 48 # we will eventually update the existing file with the highest priority,
49 # if it's a user personal file... 49 # if it's a user personal file...
50 if not silent: 50 if not silent:
51 log.debug(_(u"Testing file %s") % file_) 51 log.debug(_("Testing file %s") % file_)
52 if os.path.isfile(file_): 52 if os.path.isfile(file_):
53 if file_.startswith(os.path.expanduser("~")): 53 if file_.startswith(os.path.expanduser("~")):
54 config.read([file_]) 54 config.read([file_])
55 target_file = file_ 55 target_file = file_
56 break 56 break
63 with open(target_file, "wb") as configfile: 63 with open(target_file, "wb") as configfile:
64 config.write(configfile) # for the next time that user launches sat 64 config.write(configfile) # for the next time that user launches sat
65 if not silent: 65 if not silent:
66 if option in ("passphrase",): # list here the options storing a password 66 if option in ("passphrase",): # list here the options storing a password
67 value = "******" 67 value = "******"
68 log.warning(_(u"Config auto-update: {option} set to {value} in the file " 68 log.warning(_("Config auto-update: {option} set to {value} in the file "
69 u"{config_file}.").format(option=option, value=value, 69 "{config_file}.").format(option=option, value=value,
70 config_file=target_file)) 70 config_file=target_file))
71 71
72 72
73 def parseMainConf(): 73 def parseMainConf():
74 """look for main .ini configuration file, and parse it""" 74 """look for main .ini configuration file, and parse it"""
75 config = SafeConfigParser(defaults=C.DEFAULT_CONFIG) 75 config = SafeConfigParser(defaults=C.DEFAULT_CONFIG)
76 try: 76 try:
77 config.read(C.CONFIG_FILES) 77 config.read(C.CONFIG_FILES)
78 except Exception as e: 78 except Exception as e:
79 log.error(_(u"Can't read main config: {msg}").format(msg=e), exc_info=True) 79 log.error(_("Can't read main config: {msg}").format(msg=e), exc_info=True)
80 return config 80 return config
81 81
82 82
83 def getConfig(config, section, name, default=None): 83 def getConfig(config, section, name, default=None):
84 """Get a configuration option 84 """Get a configuration option
94 """ 94 """
95 if not section: 95 if not section:
96 section = DEFAULTSECT 96 section = DEFAULTSECT
97 97
98 try: 98 try:
99 value = config.get(section, name).decode("utf-8") 99 value = config.get(section, name)
100 except (NoOptionError, NoSectionError) as e: 100 except (NoOptionError, NoSectionError) as e:
101 if default is Exception: 101 if default is Exception:
102 raise e 102 raise e
103 return default 103 return default
104 104
105 if name.endswith("_path") or name.endswith("_dir"): 105 if name.endswith("_path") or name.endswith("_dir"):
106 value = os.path.expanduser(value) 106 value = os.path.expanduser(value)
107 # thx to Brian (http://stackoverflow.com/questions/186857/splitting-a-semicolon-separated-string-to-a-dictionary-in-python/186873#186873) 107 # thx to Brian (http://stackoverflow.com/questions/186857/splitting-a-semicolon-separated-string-to-a-dictionary-in-python/186873#186873)
108 elif name.endswith("_list"): 108 elif name.endswith("_list"):
109 value = csv.reader( 109 value = next(csv.reader(
110 [value], delimiter=",", quotechar='"', skipinitialspace=True 110 [value], delimiter=",", quotechar='"', skipinitialspace=True
111 ).next() 111 ))
112 elif name.endswith("_dict"): 112 elif name.endswith("_dict"):
113 try: 113 try:
114 value = json.loads(value) 114 value = json.loads(value)
115 except ValueError as e: 115 except ValueError as e:
116 raise exceptions.ParsingError(u"Error while parsing data: {}".format(e)) 116 raise exceptions.ParsingError("Error while parsing data: {}".format(e))
117 if not isinstance(value, dict): 117 if not isinstance(value, dict):
118 raise exceptions.ParsingError( 118 raise exceptions.ParsingError(
119 u"{name} value is not a dict: {value}".format(name=name, value=value) 119 "{name} value is not a dict: {value}".format(name=name, value=value)
120 ) 120 )
121 elif name.endswith("_json"): 121 elif name.endswith("_json"):
122 try: 122 try:
123 value = json.loads(value) 123 value = json.loads(value)
124 except ValueError as e: 124 except ValueError as e:
125 raise exceptions.ParsingError(u"Error while parsing data: {}".format(e)) 125 raise exceptions.ParsingError("Error while parsing data: {}".format(e))
126 return value 126 return value