forked from Bitmessage/PyBitmessage
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbmconfigparser.py
161 lines (137 loc) · 5.34 KB
/
bmconfigparser.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
"""
BMConfigParser class definition and default configuration settings
"""
import os
import shutil
from threading import Event
from datetime import datetime
from six import string_types
from six.moves import configparser
try:
import state
except ImportError:
from pybitmessage import state
SafeConfigParser = configparser.SafeConfigParser
config_ready = Event()
class BMConfigParser(SafeConfigParser):
"""
Singleton class inherited from :class:`ConfigParser.SafeConfigParser`
with additional methods specific to bitmessage config.
"""
# pylint: disable=too-many-ancestors
_temp = {}
def set(self, section, option, value=None):
if self._optcre is self.OPTCRE or value:
if not isinstance(value, string_types):
raise TypeError("option values must be strings")
if not self.validate(section, option, value):
raise ValueError("Invalid value %s" % value)
return SafeConfigParser.set(self, section, option, value)
def get(self, section, option, **kwargs):
"""Try returning temporary value before using parent get()"""
try:
return self._temp[section][option]
except KeyError:
pass
return SafeConfigParser.get(
self, section, option, **kwargs)
def setTemp(self, section, option, value=None):
"""Temporary set option to value, not saving."""
try:
self._temp[section][option] = value
except KeyError:
self._temp[section] = {option: value}
def safeGetBoolean(self, section, option):
"""Return value as boolean, False on exceptions"""
try:
return self.getboolean(section, option)
except (configparser.NoSectionError, configparser.NoOptionError,
ValueError, AttributeError):
return False
def safeGetInt(self, section, option, default=0):
"""Return value as integer, default on exceptions,
0 if default missing"""
try:
return int(self.get(section, option))
except (configparser.NoSectionError, configparser.NoOptionError,
ValueError, AttributeError):
return default
def safeGetFloat(self, section, option, default=0.0):
"""Return value as float, default on exceptions,
0.0 if default missing"""
try:
return self.getfloat(section, option)
except (configparser.NoSectionError, configparser.NoOptionError,
ValueError, AttributeError):
return default
def safeGet(self, section, option, default=None):
"""
Return value as is, default on exceptions, None if default missing
"""
try:
return self.get(section, option)
except (configparser.NoSectionError, configparser.NoOptionError,
ValueError, AttributeError):
return default
def items(self, section, raw=False, variables=None):
# pylint: disable=signature-differs
"""Return section variables as parent,
but override the "raw" argument to always True"""
return SafeConfigParser.items(self, section, True, variables)
def _reset(self):
"""
Reset current config.
There doesn't appear to be a built in method for this.
"""
self._temp = {}
sections = self.sections()
for x in sections:
self.remove_section(x)
def read(self, filenames=None):
self._reset()
SafeConfigParser.read(
self, os.path.join(os.path.dirname(__file__), 'default.ini'))
if filenames:
SafeConfigParser.read(self, filenames)
def addresses(self):
"""Return a list of local bitmessage addresses (from section labels)"""
return [x for x in self.sections() if x.startswith('BM-')]
def save(self):
"""Save the runtime config onto the filesystem"""
fileName = os.path.join(state.appdata, 'keys.dat')
fileNameBak = '.'.join([
fileName, datetime.now().strftime("%Y%j%H%M%S%f"), 'bak'])
# create a backup copy to prevent the accidental loss due to
# the disk write failure
try:
shutil.copyfile(fileName, fileNameBak)
# The backup succeeded.
fileNameExisted = True
except(IOError, Exception):
# The backup failed. This can happen if the file
# didn't exist before.
fileNameExisted = False
with open(fileName, 'w') as configfile:
self.write(configfile)
# delete the backup
if fileNameExisted:
os.remove(fileNameBak)
def validate(self, section, option, value):
"""Input validator interface (using factory pattern)"""
try:
return getattr(self, 'validate_%s_%s' % (section, option))(value)
except AttributeError:
return True
@staticmethod
def validate_bitmessagesettings_maxoutboundconnections(value):
"""Reject maxoutboundconnections that are too high or too low"""
try:
value = int(value)
except ValueError:
return False
if value < 0 or value > 8:
return False
return True
if not getattr(BMConfigParser, 'read_file', False):
BMConfigParser.read_file = BMConfigParser.readfp
config = BMConfigParser() # TODO: remove this crutch