From e027a188a98bcfb19059e4aa1b46485307095023 Mon Sep 17 00:00:00 2001 From: Luke Murphy Date: Sat, 20 Jul 2019 12:27:32 +0200 Subject: [PATCH 1/2] Refactor exposing of global configuration We do this to make it easier to control this value during testing. We should not import these values at package setup time. Nor should we import them at package load time. This change introduces a new API for the Moulinette package. The moulinette.env accessor. This is a breaking change. However, I've searched around and can't seem to find any usage that relies directly on these properties being available. I've tried to maintain API backwards compatibility in all cases otherwise. --- moulinette/__init__.py | 12 ++++++++---- moulinette/actionsmap.py | 13 ++++++++++++- moulinette/cache.py | 4 +++- moulinette/core.py | 10 +++++++--- moulinette/globals.py | 12 ++++++++---- setup.py | 4 +++- 6 files changed, 41 insertions(+), 14 deletions(-) diff --git a/moulinette/__init__.py b/moulinette/__init__.py index 719c5dd3..1db22b60 100755 --- a/moulinette/__init__.py +++ b/moulinette/__init__.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- from moulinette.core import init_interface, MoulinetteError, MoulinetteSignals, Moulinette18n -from moulinette.globals import DATA_DIR, LIB_DIR, LOCALES_DIR, CACHE_DIR +from moulinette.globals import init_moulinette_env __title__ = 'moulinette' __version__ = '0.1' @@ -28,9 +28,8 @@ __credits__ = """ along with this program; if not, see http://www.gnu.org/licenses """ __all__ = [ - 'init', 'api', 'cli', 'm18n', + 'init', 'api', 'cli', 'm18n', 'env', 'init_interface', 'MoulinetteError', - 'DATA_DIR', 'LIB_DIR', 'LOCALES_DIR', 'CACHE_DIR', ] @@ -62,7 +61,7 @@ def init(logging_config=None, **kwargs): configure_logging(logging_config) # Add library directory to python path - sys.path.insert(0, LIB_DIR) + sys.path.insert(0, init_moulinette_env()['LIB_DIR']) # Easy access to interfaces @@ -139,3 +138,8 @@ def cli(namespaces, args, use_cache=True, output_as=None, logging.getLogger(namespaces[0]).error(e.strerror) return 1 return 0 + + +def env(): + """Initialise moulinette specific configuration.""" + return init_moulinette_env() diff --git a/moulinette/actionsmap.py b/moulinette/actionsmap.py index 4458fd44..63483701 100644 --- a/moulinette/actionsmap.py +++ b/moulinette/actionsmap.py @@ -10,7 +10,7 @@ from collections import OrderedDict from moulinette import m18n, msignals from moulinette.cache import open_cachefile -from moulinette.globals import CACHE_DIR, DATA_DIR +from moulinette.globals import init_moulinette_env from moulinette.core import (MoulinetteError, MoulinetteLock) from moulinette.interfaces import ( BaseActionsMapParser, GLOBAL_SECTION, TO_RETURN_PROP @@ -393,6 +393,10 @@ class ActionsMap(object): self.parser_class = parser_class self.use_cache = use_cache + moulinette_env = init_moulinette_env() + DATA_DIR = moulinette_env['DATA_DIR'] + CACHE_DIR = moulinette_env['CACHE_DIR'] + if len(namespaces) == 0: namespaces = self.get_namespaces() actionsmaps = OrderedDict() @@ -537,6 +541,9 @@ class ActionsMap(object): """ namespaces = [] + moulinette_env = init_moulinette_env() + DATA_DIR = moulinette_env['DATA_DIR'] + for f in os.listdir('%s/actionsmap' % DATA_DIR): if f.endswith('.yml'): namespaces.append(f[:-4]) @@ -554,6 +561,10 @@ class ActionsMap(object): A dict of actions map for each namespaces """ + moulinette_env = init_moulinette_env() + CACHE_DIR = moulinette_env['CACHE_DIR'] + DATA_DIR = moulinette_env['DATA_DIR'] + actionsmaps = {} if not namespaces: namespaces = klass.get_namespaces() diff --git a/moulinette/cache.py b/moulinette/cache.py index 78a32d73..49120a22 100644 --- a/moulinette/cache.py +++ b/moulinette/cache.py @@ -2,7 +2,7 @@ import os -from moulinette.globals import CACHE_DIR +from moulinette.globals import init_moulinette_env def get_cachedir(subdir='', make_dir=True): @@ -16,6 +16,8 @@ def get_cachedir(subdir='', make_dir=True): - make_dir -- False to not make directory if it not exists """ + CACHE_DIR = init_moulinette_env()['CACHE_DIR'] + path = os.path.join(CACHE_DIR, subdir) if make_dir and not os.path.isdir(path): diff --git a/moulinette/core.py b/moulinette/core.py index 86e47b72..0b1d5dd6 100644 --- a/moulinette/core.py +++ b/moulinette/core.py @@ -8,7 +8,7 @@ import logging from importlib import import_module import moulinette -from moulinette.globals import LOCALES_DIR, LIB_DIR +from moulinette.globals import init_moulinette_env from moulinette.cache import get_cachedir @@ -179,8 +179,12 @@ class Moulinette18n(object): self.default_locale = default_locale self.locale = default_locale + moulinette_env = init_moulinette_env() + self.locales_dir = moulinette_env['LOCALES_DIR'] + self.lib_dir = moulinette_env['LIB_DIR'] + # Init global translator - self._global = Translator(LOCALES_DIR, default_locale) + self._global = Translator(self.locales_dir, default_locale) # Define namespace related variables self._namespaces = {} @@ -198,7 +202,7 @@ class Moulinette18n(object): """ if namespace not in self._namespaces: # Create new Translator object - translator = Translator('%s/%s/locales' % (LIB_DIR, namespace), + translator = Translator('%s/%s/locales' % (self.lib_dir, namespace), self.default_locale) translator.set_locale(self.locale) self._namespaces[namespace] = translator diff --git a/moulinette/globals.py b/moulinette/globals.py index 885667c6..99f7ccf0 100644 --- a/moulinette/globals.py +++ b/moulinette/globals.py @@ -2,7 +2,11 @@ from os import environ -DATA_DIR = environ.get('MOULINETTE_DATA_DIR', '/usr/share/moulinette') -LIB_DIR = environ.get('MOULINETTE_LIB_DIR', '/usr/lib/moulinette') -LOCALES_DIR = environ.get('MOULINETTE_LOCALES_DIR', '/usr/share/moulinette/locale') -CACHE_DIR = environ.get('MOULINETTE_CACHE_DIR', '/var/cache/moulinette') + +def init_moulinette_env(): + return { + 'DATA_DIR': environ.get('MOULINETTE_DATA_DIR', '/usr/share/moulinette'), + 'LIB_DIR': environ.get('MOULINETTE_LIB_DIR', '/usr/lib/moulinette'), + 'LOCALES_DIR': environ.get('MOULINETTE_LOCALES_DIR', '/usr/share/moulinette/locale'), + 'CACHE_DIR': environ.get('MOULINETTE_CACHE_DIR', '/var/cache/moulinette'), + } diff --git a/setup.py b/setup.py index 9dd447c3..e4c64cd4 100755 --- a/setup.py +++ b/setup.py @@ -3,8 +3,10 @@ import os import sys from setuptools import setup, find_packages +from moulinette.globals import init_moulinette_env -from moulinette.globals import LOCALES_DIR + +LOCALES_DIR = init_moulinette_env()['LOCALES_DIR'] # Extend installation locale_files = [] From 14a3d634533aceab954dec9ce520f1d01e5f9167 Mon Sep 17 00:00:00 2001 From: Luke Murphy Date: Sat, 20 Jul 2019 12:29:35 +0200 Subject: [PATCH 2/2] Test the cache file opening and creation --- moulinette/cache.py | 4 +++- test/test_cache.py | 11 +++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) create mode 100644 test/test_cache.py diff --git a/moulinette/cache.py b/moulinette/cache.py index 49120a22..4da4ece8 100644 --- a/moulinette/cache.py +++ b/moulinette/cache.py @@ -42,4 +42,6 @@ def open_cachefile(filename, mode='r', **kwargs): # Set make_dir if not given kwargs['make_dir'] = kwargs.get('make_dir', True if mode[0] == 'w' else False) - return open('%s/%s' % (get_cachedir(**kwargs), filename), mode) + cache_dir = get_cachedir(**kwargs) + file_path = os.path.join(cache_dir, filename) + return open(file_path, mode) diff --git a/test/test_cache.py b/test/test_cache.py new file mode 100644 index 00000000..64843f6d --- /dev/null +++ b/test/test_cache.py @@ -0,0 +1,11 @@ +import os.path + +def test_open_cachefile_creates(monkeypatch, tmp_path): + monkeypatch.setenv('MOULINETTE_CACHE_DIR', str(tmp_path)) + + from moulinette.cache import open_cachefile + + handle = open_cachefile('foo.cache', mode='w') + + assert handle.mode == 'w' + assert handle.name == os.path.join(str(tmp_path), 'foo.cache')