forked from spotify/luigi
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Optional TOML configs support (spotify#2457)
See the added docs for usage.
- Loading branch information
Showing
13 changed files
with
349 additions
and
38 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
# -*- coding: utf-8 -*- | ||
# | ||
# Copyright 2012-2015 Spotify AB | ||
# | ||
# 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 | ||
# | ||
# http://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. | ||
# | ||
from .cfg_parser import LuigiConfigParser | ||
from .core import get_config, add_config_path | ||
from .toml_parser import LuigiTomlParser | ||
|
||
|
||
__all__ = [ | ||
'add_config_path', | ||
'get_config', | ||
'LuigiConfigParser', | ||
'LuigiTomlParser', | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
# -*- coding: utf-8 -*- | ||
# | ||
# Copyright 2012-2015 Spotify AB | ||
# | ||
# 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 | ||
# | ||
# http://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 | ||
|
||
|
||
# IMPORTANT: don't inherit from `object`! | ||
# ConfigParser have some troubles in this case. | ||
# More info: https://stackoverflow.com/a/19323238 | ||
class BaseParser: | ||
@classmethod | ||
def instance(cls, *args, **kwargs): | ||
""" Singleton getter """ | ||
if cls._instance is None: | ||
cls._instance = cls(*args, **kwargs) | ||
loaded = cls._instance.reload() | ||
logging.getLogger('luigi-interface').info('Loaded %r', loaded) | ||
|
||
return cls._instance | ||
|
||
@classmethod | ||
def add_config_path(cls, path): | ||
cls._config_paths.append(path) | ||
cls.reload() | ||
|
||
@classmethod | ||
def reload(cls): | ||
return cls.instance().read(cls._config_paths) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
# -*- coding: utf-8 -*- | ||
# | ||
# Copyright 2012-2015 Spotify AB | ||
# | ||
# 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 | ||
# | ||
# http://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 | ||
import warnings | ||
|
||
from .cfg_parser import LuigiConfigParser | ||
from .toml_parser import LuigiTomlParser | ||
|
||
|
||
logger = logging.getLogger('luigi-interface') | ||
|
||
|
||
PARSERS = { | ||
'cfg': LuigiConfigParser, | ||
'conf': LuigiConfigParser, | ||
'ini': LuigiConfigParser, | ||
'toml': LuigiTomlParser, | ||
} | ||
|
||
# select parser via env var | ||
DEFAULT_PARSER = 'cfg' | ||
PARSER = os.environ.get('LUIGI_CONFIG_PARSER', DEFAULT_PARSER) | ||
if PARSER not in PARSERS: | ||
warnings.warn("Invalid parser: {parser}".format(parser=PARSER)) | ||
PARSER = DEFAULT_PARSER | ||
|
||
|
||
def get_config(parser=PARSER): | ||
"""Get configs singleton for parser | ||
""" | ||
|
||
parser_class = PARSERS[parser] | ||
if not parser_class.enabled: | ||
logger.error(( | ||
"Parser not installed yet. " | ||
"Please, install luigi with required parser:\n" | ||
"pip install luigi[{parser}]" | ||
).format(parser) | ||
) | ||
|
||
return parser_class.instance() | ||
|
||
|
||
def add_config_path(path): | ||
"""Select config parser by file extension and add path into parser. | ||
""" | ||
if not os.path.isfile(path): | ||
warnings.warn("Config file does not exist: {path}".format(path=path)) | ||
return False | ||
|
||
# select parser by file extension | ||
_base, ext = os.path.splitext(path) | ||
if ext and ext[1:] in PARSERS: | ||
parser_class = PARSERS[ext[1:]] | ||
else: | ||
parser_class = PARSERS[PARSER] | ||
|
||
# add config path to parser | ||
parser_class.add_config_path(path) | ||
return True | ||
|
||
|
||
if 'LUIGI_CONFIG_PATH' in os.environ: | ||
add_config_path(os.environ['LUIGI_CONFIG_PATH']) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
# -*- coding: utf-8 -*- | ||
# | ||
# Copyright 2018 Cindicator Ltd. | ||
# | ||
# 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 | ||
# | ||
# http://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 os.path | ||
|
||
try: | ||
import toml | ||
except ImportError: | ||
toml = False | ||
|
||
from .base_parser import BaseParser | ||
|
||
|
||
class LuigiTomlParser(BaseParser): | ||
NO_DEFAULT = object() | ||
enabled = bool(toml) | ||
data = dict() | ||
_instance = None | ||
_config_paths = [ | ||
'/etc/luigi/luigi.toml', | ||
'luigi.toml', | ||
] | ||
|
||
@staticmethod | ||
def _update_data(data, new_data): | ||
if not new_data: | ||
return data | ||
if not data: | ||
return new_data | ||
for section, content in new_data.items(): | ||
if section not in data: | ||
data[section] = dict() | ||
data[section].update(content) | ||
return data | ||
|
||
def read(self, config_paths): | ||
self.data = dict() | ||
for path in config_paths: | ||
if os.path.isfile(path): | ||
self.data = self._update_data(self.data, toml.load(path)) | ||
return self.data | ||
|
||
def get(self, section, option, default=NO_DEFAULT, **kwargs): | ||
try: | ||
return self.data[section][option] | ||
except KeyError: | ||
if default is self.NO_DEFAULT: | ||
raise | ||
return default | ||
|
||
def getboolean(self, section, option, default=NO_DEFAULT): | ||
return self.get(section, option, default) | ||
|
||
def getint(self, section, option, default=NO_DEFAULT): | ||
return self.get(section, option, default) | ||
|
||
def getfloat(self, section, option, default=NO_DEFAULT): | ||
return self.get(section, option, default) | ||
|
||
def getintdict(self, section): | ||
return self.data.get(section, {}) | ||
|
||
def set(self, section, option, value=None): | ||
if section not in self.data: | ||
self.data[section] = {} | ||
self.data[section][option] = value | ||
|
||
def __getitem__(self, name): | ||
return self.data[name] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.