/
config.py
137 lines (113 loc) · 4.17 KB
/
config.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
# Copyright (c) 2017 Niklas Rosenstein
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
__all__ = ['get_default_prefix', 'Config']
import appdirs
import collections
import os
import sys
def is_virtualenv():
return hasattr(sys, 'real_prefix') or (sys.prefix == sys.base_prefix)
def get_default_prefix():
"""
Returns the default prefix path of where to store ppy packages, Python
modules, scripts, etc.
"""
if is_virtualenv():
# Use the virtualenv's prefix instead.
return os.path.join(sys.prefix, 'share', 'ppy')
return appdirs.user_data_dir('ppy', False, roaming=True)
def get_default_bindir():
"""
Returns the default value for the `bindir` option. Inside virtual
environments, it will be the `bin/` or `Scripts/` directory respectively
depending on the system, otherwise it will be `~/bin` (if it exists) or
alternatively be the `bin/` directory in the directory returned by
#get_default_prefix().
"""
if is_virtualenv():
if os.name == 'nt':
return os.path.join(sys.prefix, 'Scripts')
else:
return os.path.join(sys.prefix, 'bin')
dirname = os.path.expanduser('~/bin')
if os.path.isdir(dirname):
return dirname
return os.path.join(get_default_prefix(), 'bin')
class Config(object):
"""
Reader/writer for the ppy configuration file. The file format must be in
plain `key=value` format, one per line.
# Parameters
filename (str): The config file to parse, and optionally save to. Pass
#NotImplemented to prevent the #Config object from actually loading any
configuration file. Defaults to the value of the `PPY_CONFIG` environment
variable or `~/.ppyrc`.
"""
defaults = {
'prefix': get_default_prefix(),
'bindir': get_default_bindir()
}
def __init__(self, filename=NotImplemented, defaults=None):
if filename is NotImplemented:
filename = os.getenv('PPY_CONFIG', '~/.ppyrc')
if filename:
filename = os.path.normpath(os.path.expanduser(filename))
if defaults is None:
defaults = Config.defaults
self.filename = filename
self.values = collections.OrderedDict()
self.defaults = defaults
self.loaded = False
if self.filename:
self.load()
def __repr__(self):
return '<Config {!r}>'.format(self.filename)
def load(self):
self.loaded = False
if not os.path.isfile(self.filename):
return
self.loaded = True
with open(self.filename, 'r') as fp:
for line in fp:
key, value = line.rstrip('\n').partition('=')[::2]
self.values[key.lower()] = value or ''
def save(self, create_directory=True):
if not self.values:
return
if create_directory:
dirname = os.path.dirname(self.filename)
if not os.path.isdir(dirname):
os.makedirs(dirname)
with open(self.filename, 'w') as fp:
for key, value in self.values.items():
if not key: continue
fp.write('{}={}\n'.format(key, value))
def __getitem__(self, key):
try:
return self.values[key]
except KeyError:
return self.defaults[key]
def __setitem__(self, key, value):
self.values[key] = str(value)
def get(self, key, default=None):
try:
return self[key]
except KeyError:
return default