forked from feast-dev/feast
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathconfig.py
More file actions
224 lines (178 loc) · 6.35 KB
/
config.py
File metadata and controls
224 lines (178 loc) · 6.35 KB
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
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
#
# Copyright 2019 The Feast Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
import logging
import os
from configparser import ConfigParser, NoOptionError
from os.path import expanduser, join
from typing import Dict, Optional
from feast.constants import (
CONFIG_FEAST_ENV_VAR_PREFIX,
CONFIG_FILE_DEFAULT_DIRECTORY,
CONFIG_FILE_NAME,
CONFIG_FILE_SECTION,
FEAST_CONFIG_FILE_ENV_KEY,
)
from feast.constants import FEAST_DEFAULT_OPTIONS as DEFAULTS
_logger = logging.getLogger(__name__)
def _init_config(path: str):
"""
Returns a ConfigParser that reads in a feast configuration file. If the
file does not exist it will be created.
Args:
path: Optional path to initialize as Feast configuration
Returns: ConfigParser of the Feast configuration file, with defaults
preloaded
"""
# Create the configuration file directory if needed
config_dir = os.path.dirname(path)
config_dir = config_dir.rstrip("/") + "/"
if not os.path.exists(os.path.dirname(config_dir)):
os.makedirs(os.path.dirname(config_dir))
# Create the configuration file itself
config = ConfigParser(defaults=DEFAULTS)
if os.path.exists(path):
config.read(path)
# Store all configuration in a single section
if not config.has_section(CONFIG_FILE_SECTION):
config.add_section(CONFIG_FILE_SECTION)
# Save the current configuration
config.write(open(path, "w"))
return config
def _get_feast_env_vars():
"""
Get environmental variables that start with FEAST_
Returns: Dict of Feast environmental variables (stripped of prefix)
"""
feast_env_vars = {}
for key in os.environ.keys():
if key.upper().startswith(CONFIG_FEAST_ENV_VAR_PREFIX):
feast_env_vars[key[len(CONFIG_FEAST_ENV_VAR_PREFIX) :]] = os.environ[key]
return feast_env_vars
class Config:
"""
Maintains and provides access to Feast configuration
Configuration is stored as key/value pairs. The user can specify options
through either input arguments to this class, environmental variables, or
by setting the config in a configuration file
"""
def __init__(
self, options: Optional[Dict[str, str]] = None, path: Optional[str] = None,
):
"""
Configuration options are returned as follows (higher replaces lower)
1. Initialized options ("options" argument)
2. Environmental variables (reloaded on every "get")
3. Configuration file options (loaded once)
4. Default options (loaded once from memory)
Args:
options: (optional) A list of initialized/hardcoded options.
path: (optional) File path to configuration file
"""
if not path:
path = join(
expanduser("~"),
os.environ.get(
FEAST_CONFIG_FILE_ENV_KEY, CONFIG_FILE_DEFAULT_DIRECTORY,
),
CONFIG_FILE_NAME,
)
config = _init_config(path)
self._options = {}
if options and isinstance(options, dict):
self._options = options
self._config = config # type: ConfigParser
self._path = path # type: str
def get(self, option):
"""
Returns a single configuration option as a string
Args:
option: Name of the option
Returns: String option that is returned
"""
return self._config.get(
CONFIG_FILE_SECTION,
option,
vars={**_get_feast_env_vars(), **self._options},
)
def getboolean(self, option):
"""
Returns a single configuration option as a boolean
Args:
option: Name of the option
Returns: Boolean option value that is returned
"""
return self._config.getboolean(
CONFIG_FILE_SECTION,
option,
vars={**_get_feast_env_vars(), **self._options},
)
def getint(self, option):
"""
Returns a single configuration option as an integer
Args:
option: Name of the option
Returns: Integer option value that is returned
"""
return self._config.getint(
CONFIG_FILE_SECTION,
option,
vars={**_get_feast_env_vars(), **self._options},
)
def getfloat(self, option):
"""
Returns a single configuration option as an integer
Args:
option: Name of the option
Returns: Float option value that is returned
"""
return self._config.getfloat(
CONFIG_FILE_SECTION,
option,
vars={**_get_feast_env_vars(), **self._options},
)
def set(self, option, value):
"""
Sets a configuration option. Must be serializable to string
Args:
option: Option name to use as key
value: Value to store under option
"""
self._config.set(CONFIG_FILE_SECTION, option, value=str(value))
def exists(self, option):
"""
Tests whether a specific option is available
Args:
option: Name of the option to check
Returns: Boolean true/false whether the option is set
"""
try:
self.get(option=option)
return True
except NoOptionError:
return False
def save(self):
"""
Save the current configuration to disk. This does not include
environmental variables or initialized options
"""
self._config.write(open(self._path, "w"))
def __str__(self):
result = ""
for section_name in self._config.sections():
result += "\n[" + section_name + "]\n"
for name, value in self._config.items(section_name):
result += name + " = " + value + "\n"
return result