mirror of
https://github.com/YunoHost/moulinette.git
synced 2024-09-03 20:06:31 +02:00
Merge pull request #145 from YunoHost/refactoring2
Remove globals variables magic and add explicit import now
This commit is contained in:
commit
1efa5c8b6e
17 changed files with 158 additions and 211 deletions
10
doc/conf.py
10
doc/conf.py
|
@ -85,7 +85,7 @@ todo_include_todos = True
|
||||||
# The theme to use for HTML and HTML Help pages. See the documentation for
|
# The theme to use for HTML and HTML Help pages. See the documentation for
|
||||||
# a list of builtin themes.
|
# a list of builtin themes.
|
||||||
#
|
#
|
||||||
html_theme = 'default'
|
html_theme = 'classic'
|
||||||
|
|
||||||
# Theme options are theme-specific and customize the look and feel of a theme
|
# Theme options are theme-specific and customize the look and feel of a theme
|
||||||
# further. For a list of options available for each theme, see the
|
# further. For a list of options available for each theme, see the
|
||||||
|
@ -105,11 +105,11 @@ html_static_path = ['_static']
|
||||||
# refs: http://alabaster.readthedocs.io/en/latest/installation.html#sidebars
|
# refs: http://alabaster.readthedocs.io/en/latest/installation.html#sidebars
|
||||||
html_sidebars = {
|
html_sidebars = {
|
||||||
'**': [
|
'**': [
|
||||||
'about.html',
|
# 'about.html',
|
||||||
'navigation.html',
|
# 'navigation.html',
|
||||||
'relations.html', # needs 'show_related': True theme option to display
|
# 'relations.html', # needs 'show_related': True theme option to display
|
||||||
'searchbox.html',
|
'searchbox.html',
|
||||||
'donate.html',
|
# 'donate.html',
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,7 @@ a reference.
|
||||||
:maxdepth: 2
|
:maxdepth: 2
|
||||||
:caption: Contents:
|
:caption: Contents:
|
||||||
|
|
||||||
|
m18n
|
||||||
utils/filesystem
|
utils/filesystem
|
||||||
utils/network
|
utils/network
|
||||||
utils/process
|
utils/process
|
||||||
|
|
38
doc/m18n.rst
Normal file
38
doc/m18n.rst
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
Translations using the m18n object
|
||||||
|
==================================
|
||||||
|
|
||||||
|
The moulinette provides a way to do translations and YunoHost uses it. This is
|
||||||
|
done via the `m18n` object that you can import this way:
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
from moulinette import m18n
|
||||||
|
|
||||||
|
The `m18n` object comes with 2 method:
|
||||||
|
|
||||||
|
* `m18n.n` to uses for translations within YunoHost
|
||||||
|
* `m18n.g` to uses for translations within Moulinette itself
|
||||||
|
|
||||||
|
Their API is identical.
|
||||||
|
|
||||||
|
Here are example of uses:
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
m18n.n('some_translation_key')
|
||||||
|
m18n.g('some_translation_key')
|
||||||
|
|
||||||
|
m18n.n('some_translation_key', string_formating_argument_1=some_variable)
|
||||||
|
m18n.g('some_translation_key', string_formating_argument_1=some_variable)
|
||||||
|
|
||||||
|
The translation key must be present in `locales/en.json` of either YunoHost
|
||||||
|
(for `.n`) or moulinette (for `.g`).
|
||||||
|
|
||||||
|
Docstring
|
||||||
|
---------
|
||||||
|
|
||||||
|
As a reference, here are the docstrings of the m18n class:
|
||||||
|
|
||||||
|
.. autoclass:: moulinette.core.Moulinette18n
|
||||||
|
.. automethod:: moulinette.core.Moulinette18n.n
|
||||||
|
.. automethod:: moulinette.core.Moulinette18n.g
|
|
@ -1,6 +1,7 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
from moulinette.core import init_interface, MoulinetteError
|
from moulinette.core import init_interface, MoulinetteError, MoulinetteSignals, Moulinette18n
|
||||||
|
from moulinette.globals import DATA_DIR, LIB_DIR, LOCALES_DIR, CACHE_DIR
|
||||||
|
|
||||||
__title__ = 'moulinette'
|
__title__ = 'moulinette'
|
||||||
__version__ = '0.1'
|
__version__ = '0.1'
|
||||||
|
@ -27,11 +28,17 @@ __credits__ = """
|
||||||
along with this program; if not, see http://www.gnu.org/licenses
|
along with this program; if not, see http://www.gnu.org/licenses
|
||||||
"""
|
"""
|
||||||
__all__ = [
|
__all__ = [
|
||||||
'init', 'api', 'cli',
|
'init', 'api', 'cli', 'm18n',
|
||||||
'init_interface', 'MoulinetteError',
|
'init_interface', 'MoulinetteError',
|
||||||
|
'DATA_DIR', 'LIB_DIR', 'LOCALES_DIR', 'CACHE_DIR',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
msignals = MoulinetteSignals()
|
||||||
|
msettings = dict()
|
||||||
|
m18n = Moulinette18n()
|
||||||
|
|
||||||
|
|
||||||
# Package functions
|
# Package functions
|
||||||
|
|
||||||
def init(logging_config=None, **kwargs):
|
def init(logging_config=None, **kwargs):
|
||||||
|
@ -50,22 +57,12 @@ def init(logging_config=None, **kwargs):
|
||||||
|
|
||||||
"""
|
"""
|
||||||
import sys
|
import sys
|
||||||
import __builtin__
|
|
||||||
from moulinette.core import (
|
|
||||||
Package, Moulinette18n, MoulinetteSignals
|
|
||||||
)
|
|
||||||
from moulinette.utils.log import configure_logging
|
from moulinette.utils.log import configure_logging
|
||||||
|
|
||||||
configure_logging(logging_config)
|
configure_logging(logging_config)
|
||||||
|
|
||||||
# Define and instantiate global objects
|
|
||||||
__builtin__.__dict__['pkg'] = Package(**kwargs)
|
|
||||||
__builtin__.__dict__['m18n'] = Moulinette18n(pkg)
|
|
||||||
__builtin__.__dict__['msignals'] = MoulinetteSignals()
|
|
||||||
__builtin__.__dict__['msettings'] = dict()
|
|
||||||
|
|
||||||
# Add library directory to python path
|
# Add library directory to python path
|
||||||
sys.path.insert(0, pkg.libdir)
|
sys.path.insert(0, LIB_DIR)
|
||||||
|
|
||||||
|
|
||||||
# Easy access to interfaces
|
# Easy access to interfaces
|
||||||
|
|
|
@ -9,6 +9,9 @@ import cPickle as pickle
|
||||||
from time import time
|
from time import time
|
||||||
from collections import OrderedDict
|
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.core import (MoulinetteError, MoulinetteLock)
|
from moulinette.core import (MoulinetteError, MoulinetteLock)
|
||||||
from moulinette.interfaces import (
|
from moulinette.interfaces import (
|
||||||
BaseActionsMapParser, GLOBAL_SECTION, TO_RETURN_PROP
|
BaseActionsMapParser, GLOBAL_SECTION, TO_RETURN_PROP
|
||||||
|
@ -373,10 +376,10 @@ class ActionsMap(object):
|
||||||
for n in namespaces:
|
for n in namespaces:
|
||||||
logger.debug("loading actions map namespace '%s'", n)
|
logger.debug("loading actions map namespace '%s'", n)
|
||||||
|
|
||||||
actionsmap_yml = '%s/actionsmap/%s.yml' % (pkg.datadir, n)
|
actionsmap_yml = '%s/actionsmap/%s.yml' % (DATA_DIR, n)
|
||||||
actionsmap_yml_stat = os.stat(actionsmap_yml)
|
actionsmap_yml_stat = os.stat(actionsmap_yml)
|
||||||
actionsmap_pkl = '%s/actionsmap/%s-%d-%d.pkl' % (
|
actionsmap_pkl = '%s/actionsmap/%s-%d-%d.pkl' % (
|
||||||
pkg.cachedir,
|
CACHE_DIR,
|
||||||
n,
|
n,
|
||||||
actionsmap_yml_stat.st_size,
|
actionsmap_yml_stat.st_size,
|
||||||
actionsmap_yml_stat.st_mtime
|
actionsmap_yml_stat.st_mtime
|
||||||
|
@ -498,7 +501,7 @@ class ActionsMap(object):
|
||||||
"""
|
"""
|
||||||
namespaces = []
|
namespaces = []
|
||||||
|
|
||||||
for f in os.listdir('%s/actionsmap' % pkg.datadir):
|
for f in os.listdir('%s/actionsmap' % DATA_DIR):
|
||||||
if f.endswith('.yml'):
|
if f.endswith('.yml'):
|
||||||
namespaces.append(f[:-4])
|
namespaces.append(f[:-4])
|
||||||
return namespaces
|
return namespaces
|
||||||
|
@ -524,23 +527,23 @@ class ActionsMap(object):
|
||||||
logger.debug("generating cache for actions map namespace '%s'", n)
|
logger.debug("generating cache for actions map namespace '%s'", n)
|
||||||
|
|
||||||
# Read actions map from yaml file
|
# Read actions map from yaml file
|
||||||
am_file = '%s/actionsmap/%s.yml' % (pkg.datadir, n)
|
am_file = '%s/actionsmap/%s.yml' % (DATA_DIR, n)
|
||||||
with open(am_file, 'r') as f:
|
with open(am_file, 'r') as f:
|
||||||
actionsmaps[n] = ordered_yaml_load(f)
|
actionsmaps[n] = ordered_yaml_load(f)
|
||||||
|
|
||||||
# at installation, cachedir might not exists
|
# at installation, cachedir might not exists
|
||||||
if os.path.exists('%s/actionsmap/' % pkg.cachedir):
|
if os.path.exists('%s/actionsmap/' % CACHE_DIR):
|
||||||
# clean old cached files
|
# clean old cached files
|
||||||
for i in os.listdir('%s/actionsmap/' % pkg.cachedir):
|
for i in os.listdir('%s/actionsmap/' % CACHE_DIR):
|
||||||
if i.endswith(".pkl"):
|
if i.endswith(".pkl"):
|
||||||
os.remove('%s/actionsmap/%s' % (pkg.cachedir, i))
|
os.remove('%s/actionsmap/%s' % (CACHE_DIR, i))
|
||||||
|
|
||||||
# Cache actions map into pickle file
|
# Cache actions map into pickle file
|
||||||
am_file_stat = os.stat(am_file)
|
am_file_stat = os.stat(am_file)
|
||||||
|
|
||||||
pkl = '%s-%d-%d.pkl' % (n, am_file_stat.st_size, am_file_stat.st_mtime)
|
pkl = '%s-%d-%d.pkl' % (n, am_file_stat.st_size, am_file_stat.st_mtime)
|
||||||
|
|
||||||
with pkg.open_cachefile(pkl, 'w', subdir='actionsmap') as f:
|
with open_cachefile(pkl, 'w', subdir='actionsmap') as f:
|
||||||
pickle.dump(actionsmaps[n], f)
|
pickle.dump(actionsmaps[n], f)
|
||||||
|
|
||||||
return actionsmaps
|
return actionsmaps
|
||||||
|
|
|
@ -4,6 +4,8 @@ import errno
|
||||||
import gnupg
|
import gnupg
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
|
from moulinette import m18n
|
||||||
|
from moulinette.cache import open_cachefile
|
||||||
from moulinette.core import MoulinetteError
|
from moulinette.core import MoulinetteError
|
||||||
|
|
||||||
logger = logging.getLogger('moulinette.authenticator')
|
logger = logging.getLogger('moulinette.authenticator')
|
||||||
|
@ -129,8 +131,8 @@ class BaseAuthenticator(object):
|
||||||
|
|
||||||
def _open_sessionfile(self, session_id, mode='r'):
|
def _open_sessionfile(self, session_id, mode='r'):
|
||||||
"""Open a session file for this instance in given mode"""
|
"""Open a session file for this instance in given mode"""
|
||||||
return pkg.open_cachefile('%s.asc' % session_id, mode,
|
return open_cachefile('%s.asc' % session_id, mode,
|
||||||
subdir='session/%s' % self.name)
|
subdir='session/%s' % self.name)
|
||||||
|
|
||||||
def _store_session(self, session_id, session_hash, password):
|
def _store_session(self, session_id, session_hash, password):
|
||||||
"""Store a session and its associated password"""
|
"""Store a session and its associated password"""
|
||||||
|
|
|
@ -7,6 +7,7 @@ import logging
|
||||||
import ldap
|
import ldap
|
||||||
import ldap.modlist as modlist
|
import ldap.modlist as modlist
|
||||||
|
|
||||||
|
from moulinette import m18n
|
||||||
from moulinette.core import MoulinetteError
|
from moulinette.core import MoulinetteError
|
||||||
from moulinette.authenticators import BaseAuthenticator
|
from moulinette.authenticators import BaseAuthenticator
|
||||||
|
|
||||||
|
@ -212,5 +213,5 @@ class Authenticator(BaseAuthenticator):
|
||||||
attr, value)
|
attr, value)
|
||||||
raise MoulinetteError(errno.EEXIST,
|
raise MoulinetteError(errno.EEXIST,
|
||||||
m18n.g('ldap_attribute_already_exists',
|
m18n.g('ldap_attribute_already_exists',
|
||||||
attribute=attr, value=value))
|
attribute=attr, value=value))
|
||||||
return True
|
return True
|
||||||
|
|
43
moulinette/cache.py
Normal file
43
moulinette/cache.py
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
|
from moulinette.globals import CACHE_DIR
|
||||||
|
|
||||||
|
|
||||||
|
def get_cachedir(subdir='', make_dir=True):
|
||||||
|
"""Get the path to a cache directory
|
||||||
|
|
||||||
|
Return the path to the cache directory from an optional
|
||||||
|
subdirectory and create it if needed.
|
||||||
|
|
||||||
|
Keyword arguments:
|
||||||
|
- subdir -- A cache subdirectory
|
||||||
|
- make_dir -- False to not make directory if it not exists
|
||||||
|
|
||||||
|
"""
|
||||||
|
path = os.path.join(CACHE_DIR, subdir)
|
||||||
|
|
||||||
|
if make_dir and not os.path.isdir(path):
|
||||||
|
os.makedirs(path)
|
||||||
|
return path
|
||||||
|
|
||||||
|
|
||||||
|
def open_cachefile(filename, mode='r', **kwargs):
|
||||||
|
"""Open a cache file and return a stream
|
||||||
|
|
||||||
|
Attempt to open in 'mode' the cache file 'filename' from the
|
||||||
|
default cache directory and in the subdirectory 'subdir' if
|
||||||
|
given. Directories are created if needed and a stream is
|
||||||
|
returned if the file can be written.
|
||||||
|
|
||||||
|
Keyword arguments:
|
||||||
|
- filename -- The cache filename
|
||||||
|
- mode -- The mode in which the file is opened
|
||||||
|
- **kwargs -- Optional arguments for get_cachedir
|
||||||
|
|
||||||
|
"""
|
||||||
|
# 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)
|
|
@ -8,114 +8,14 @@ import logging
|
||||||
|
|
||||||
from importlib import import_module
|
from importlib import import_module
|
||||||
|
|
||||||
|
import moulinette
|
||||||
|
from moulinette.globals import LOCALES_DIR, LIB_DIR
|
||||||
|
from moulinette.cache import get_cachedir
|
||||||
|
|
||||||
|
|
||||||
logger = logging.getLogger('moulinette.core')
|
logger = logging.getLogger('moulinette.core')
|
||||||
|
|
||||||
|
|
||||||
# Package manipulation -------------------------------------------------
|
|
||||||
|
|
||||||
class Package(object):
|
|
||||||
"""Package representation and easy access methods
|
|
||||||
|
|
||||||
Initialize directories and variables for the package and give them
|
|
||||||
easy access.
|
|
||||||
|
|
||||||
Keyword arguments:
|
|
||||||
- _from_source -- Either the package is running from source or
|
|
||||||
not (only for debugging)
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self, _from_source=False):
|
|
||||||
if _from_source:
|
|
||||||
import sys
|
|
||||||
|
|
||||||
logger.debug('initialize Package object running from source')
|
|
||||||
|
|
||||||
# Retrieve source's base directory
|
|
||||||
basedir = os.path.abspath(os.path.dirname(sys.argv[0]) + '/../')
|
|
||||||
|
|
||||||
# Set local directories
|
|
||||||
self._datadir = '%s/data' % basedir
|
|
||||||
self._libdir = '%s/lib' % basedir
|
|
||||||
self._localedir = '%s/locales' % basedir
|
|
||||||
self._cachedir = '%s/cache' % basedir
|
|
||||||
else:
|
|
||||||
import package
|
|
||||||
|
|
||||||
# Set system directories
|
|
||||||
self._datadir = package.datadir
|
|
||||||
self._libdir = package.libdir
|
|
||||||
self._localedir = package.localedir
|
|
||||||
self._cachedir = package.cachedir
|
|
||||||
|
|
||||||
def __setattr__(self, name, value):
|
|
||||||
if name[0] == '_' and name in self.__dict__:
|
|
||||||
# Deny reassignation of package directories
|
|
||||||
logger.error("cannot reassign Package variable '%s'", name)
|
|
||||||
return
|
|
||||||
self.__dict__[name] = value
|
|
||||||
|
|
||||||
# Easy access to package directories
|
|
||||||
|
|
||||||
@property
|
|
||||||
def datadir(self):
|
|
||||||
"""Return the data directory of the package"""
|
|
||||||
return self._datadir
|
|
||||||
|
|
||||||
@property
|
|
||||||
def libdir(self):
|
|
||||||
"""Return the lib directory of the package"""
|
|
||||||
return self._libdir
|
|
||||||
|
|
||||||
@property
|
|
||||||
def localedir(self):
|
|
||||||
"""Return the locale directory of the package"""
|
|
||||||
return self._localedir
|
|
||||||
|
|
||||||
@property
|
|
||||||
def cachedir(self):
|
|
||||||
"""Return the cache directory of the package"""
|
|
||||||
return self._cachedir
|
|
||||||
|
|
||||||
# Additional methods
|
|
||||||
|
|
||||||
def get_cachedir(self, subdir='', make_dir=True):
|
|
||||||
"""Get the path to a cache directory
|
|
||||||
|
|
||||||
Return the path to the cache directory from an optional
|
|
||||||
subdirectory and create it if needed.
|
|
||||||
|
|
||||||
Keyword arguments:
|
|
||||||
- subdir -- A cache subdirectory
|
|
||||||
- make_dir -- False to not make directory if it not exists
|
|
||||||
|
|
||||||
"""
|
|
||||||
path = os.path.join(self.cachedir, subdir)
|
|
||||||
|
|
||||||
if make_dir and not os.path.isdir(path):
|
|
||||||
os.makedirs(path)
|
|
||||||
return path
|
|
||||||
|
|
||||||
def open_cachefile(self, filename, mode='r', **kwargs):
|
|
||||||
"""Open a cache file and return a stream
|
|
||||||
|
|
||||||
Attempt to open in 'mode' the cache file 'filename' from the
|
|
||||||
default cache directory and in the subdirectory 'subdir' if
|
|
||||||
given. Directories are created if needed and a stream is
|
|
||||||
returned if the file can be written.
|
|
||||||
|
|
||||||
Keyword arguments:
|
|
||||||
- filename -- The cache filename
|
|
||||||
- mode -- The mode in which the file is opened
|
|
||||||
- **kwargs -- Optional arguments for get_cachedir
|
|
||||||
|
|
||||||
"""
|
|
||||||
# Set make_dir if not given
|
|
||||||
kwargs['make_dir'] = kwargs.get('make_dir',
|
|
||||||
True if mode[0] == 'w' else False)
|
|
||||||
return open('%s/%s' % (self.get_cachedir(**kwargs), filename), mode)
|
|
||||||
|
|
||||||
|
|
||||||
# Internationalization -------------------------------------------------
|
# Internationalization -------------------------------------------------
|
||||||
|
|
||||||
class Translator(object):
|
class Translator(object):
|
||||||
|
@ -187,20 +87,15 @@ class Translator(object):
|
||||||
- key -- The key to translate
|
- key -- The key to translate
|
||||||
|
|
||||||
"""
|
"""
|
||||||
def _load_key(locale):
|
if key in self._translations.get(self.locale, {}):
|
||||||
value = self._translations[locale][key]
|
return self._translations[self.locale][key].encode('utf-8').format(*args, **kwargs)
|
||||||
return value.encode('utf-8').format(*args, **kwargs)
|
|
||||||
|
if self.default_locale != self.locale and key in self._translations.get(self.default_locale, {}):
|
||||||
|
logger.info("untranslated key '%s' for locale '%s'",
|
||||||
|
key, self.locale)
|
||||||
|
|
||||||
|
return self._translations[self.default_locale][key].encode('utf-8').format(*args, **kwargs)
|
||||||
|
|
||||||
try:
|
|
||||||
return _load_key(self.locale)
|
|
||||||
except (KeyError, IndexError):
|
|
||||||
if self.default_locale != self.locale:
|
|
||||||
logger.info("untranslated key '%s' for locale '%s'",
|
|
||||||
key, self.locale)
|
|
||||||
try:
|
|
||||||
return _load_key(self.default_locale)
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
logger.exception("unable to retrieve key '%s' for default locale '%s'",
|
logger.exception("unable to retrieve key '%s' for default locale '%s'",
|
||||||
key, self.default_locale)
|
key, self.default_locale)
|
||||||
return key
|
return key
|
||||||
|
@ -244,23 +139,17 @@ class Moulinette18n(object):
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, package, default_locale='en'):
|
def __init__(self, default_locale='en'):
|
||||||
self.default_locale = default_locale
|
self.default_locale = default_locale
|
||||||
self.locale = default_locale
|
self.locale = default_locale
|
||||||
self.pkg = package
|
|
||||||
|
|
||||||
# Init global translator
|
# Init global translator
|
||||||
self._global = Translator(self.pkg.localedir, default_locale)
|
self._global = Translator(LOCALES_DIR, default_locale)
|
||||||
|
|
||||||
# Define namespace related variables
|
# Define namespace related variables
|
||||||
self._namespaces = {}
|
self._namespaces = {}
|
||||||
self._current_namespace = None
|
self._current_namespace = None
|
||||||
|
|
||||||
@property
|
|
||||||
def _namespace(self):
|
|
||||||
"""Return current namespace's Translator object"""
|
|
||||||
return self._namespaces[self._current_namespace]
|
|
||||||
|
|
||||||
def load_namespace(self, namespace):
|
def load_namespace(self, namespace):
|
||||||
"""Load the namespace to use
|
"""Load the namespace to use
|
||||||
|
|
||||||
|
@ -273,10 +162,10 @@ class Moulinette18n(object):
|
||||||
"""
|
"""
|
||||||
if namespace not in self._namespaces:
|
if namespace not in self._namespaces:
|
||||||
# Create new Translator object
|
# Create new Translator object
|
||||||
n = Translator('%s/%s/locales' % (self.pkg.libdir, namespace),
|
translator = Translator('%s/%s/locales' % (LIB_DIR, namespace),
|
||||||
self.default_locale)
|
self.default_locale)
|
||||||
n.set_locale(self.locale)
|
translator.set_locale(self.locale)
|
||||||
self._namespaces[namespace] = n
|
self._namespaces[namespace] = translator
|
||||||
|
|
||||||
# Set current namespace
|
# Set current namespace
|
||||||
self._current_namespace = namespace
|
self._current_namespace = namespace
|
||||||
|
@ -312,12 +201,7 @@ class Moulinette18n(object):
|
||||||
- key -- The key to translate
|
- key -- The key to translate
|
||||||
|
|
||||||
"""
|
"""
|
||||||
try:
|
return self._namespaces[self._current_namespace].translate(key, *args, **kwargs)
|
||||||
return self._namespace.translate(key, *args, **kwargs)
|
|
||||||
except:
|
|
||||||
logger.exception("cannot translate key '%s' for namespace '%s'",
|
|
||||||
key, self._current_namespace)
|
|
||||||
return key
|
|
||||||
|
|
||||||
|
|
||||||
class MoulinetteSignals(object):
|
class MoulinetteSignals(object):
|
||||||
|
@ -450,7 +334,7 @@ def init_interface(name, kwargs={}, actionsmap={}):
|
||||||
mod = import_module('moulinette.interfaces.%s' % name)
|
mod = import_module('moulinette.interfaces.%s' % name)
|
||||||
except ImportError:
|
except ImportError:
|
||||||
logger.exception("unable to load interface '%s'", name)
|
logger.exception("unable to load interface '%s'", name)
|
||||||
raise MoulinetteError(errno.EINVAL, m18n.g('error_see_log'))
|
raise MoulinetteError(errno.EINVAL, moulinette.m18n.g('error_see_log'))
|
||||||
else:
|
else:
|
||||||
try:
|
try:
|
||||||
# Retrieve interface classes
|
# Retrieve interface classes
|
||||||
|
@ -458,7 +342,7 @@ def init_interface(name, kwargs={}, actionsmap={}):
|
||||||
interface = mod.Interface
|
interface = mod.Interface
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
logger.exception("unable to retrieve classes of interface '%s'", name)
|
logger.exception("unable to retrieve classes of interface '%s'", name)
|
||||||
raise MoulinetteError(errno.EIO, m18n.g('error_see_log'))
|
raise MoulinetteError(errno.EIO, moulinette.m18n.g('error_see_log'))
|
||||||
|
|
||||||
# Instantiate or retrieve ActionsMap
|
# Instantiate or retrieve ActionsMap
|
||||||
if isinstance(actionsmap, dict):
|
if isinstance(actionsmap, dict):
|
||||||
|
@ -467,7 +351,7 @@ def init_interface(name, kwargs={}, actionsmap={}):
|
||||||
amap = actionsmap
|
amap = actionsmap
|
||||||
else:
|
else:
|
||||||
logger.error("invalid actionsmap value %r", actionsmap)
|
logger.error("invalid actionsmap value %r", actionsmap)
|
||||||
raise MoulinetteError(errno.EINVAL, m18n.g('error_see_log'))
|
raise MoulinetteError(errno.EINVAL, moulinette.m18n.g('error_see_log'))
|
||||||
|
|
||||||
return interface(amap, **kwargs)
|
return interface(amap, **kwargs)
|
||||||
|
|
||||||
|
@ -488,7 +372,7 @@ def init_authenticator((vendor, name), kwargs={}):
|
||||||
mod = import_module('moulinette.authenticators.%s' % vendor)
|
mod = import_module('moulinette.authenticators.%s' % vendor)
|
||||||
except ImportError:
|
except ImportError:
|
||||||
logger.exception("unable to load authenticator vendor '%s'", vendor)
|
logger.exception("unable to load authenticator vendor '%s'", vendor)
|
||||||
raise MoulinetteError(errno.EINVAL, m18n.g('error_see_log'))
|
raise MoulinetteError(errno.EINVAL, moulinette.m18n.g('error_see_log'))
|
||||||
else:
|
else:
|
||||||
return mod.Authenticator(name, **kwargs)
|
return mod.Authenticator(name, **kwargs)
|
||||||
|
|
||||||
|
@ -504,7 +388,7 @@ def clean_session(session_id, profiles=[]):
|
||||||
- profiles -- A list of profiles to clean
|
- profiles -- A list of profiles to clean
|
||||||
|
|
||||||
"""
|
"""
|
||||||
sessiondir = pkg.get_cachedir('session')
|
sessiondir = get_cachedir('session')
|
||||||
if not profiles:
|
if not profiles:
|
||||||
profiles = os.listdir(sessiondir)
|
profiles = os.listdir(sessiondir)
|
||||||
|
|
||||||
|
@ -578,7 +462,7 @@ class MoulinetteLock(object):
|
||||||
|
|
||||||
if self.timeout is not None and (time.time() - start_time) > self.timeout:
|
if self.timeout is not None and (time.time() - start_time) > self.timeout:
|
||||||
raise MoulinetteError(errno.EBUSY,
|
raise MoulinetteError(errno.EBUSY,
|
||||||
m18n.g('instance_already_running'))
|
moulinette.m18n.g('instance_already_running'))
|
||||||
# Wait before checking again
|
# Wait before checking again
|
||||||
time.sleep(self.interval)
|
time.sleep(self.interval)
|
||||||
|
|
||||||
|
@ -605,8 +489,8 @@ class MoulinetteLock(object):
|
||||||
except IOError:
|
except IOError:
|
||||||
raise MoulinetteError(
|
raise MoulinetteError(
|
||||||
errno.EPERM, '%s. %s.'.format(
|
errno.EPERM, '%s. %s.'.format(
|
||||||
m18n.g('permission_denied'),
|
moulinette.m18n.g('permission_denied'),
|
||||||
m18n.g('root_required')))
|
moulinette.m18n.g('root_required')))
|
||||||
|
|
||||||
def __enter__(self):
|
def __enter__(self):
|
||||||
if not self._locked:
|
if not self._locked:
|
||||||
|
|
4
moulinette/globals.py
Normal file
4
moulinette/globals.py
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
DATA_DIR = '/usr/share/moulinette'
|
||||||
|
LIB_DIR = '/usr/lib/moulinette'
|
||||||
|
LOCALES_DIR = '/usr/share/moulinette/locale'
|
||||||
|
CACHE_DIR = '/var/cache/moulinette'
|
|
@ -7,6 +7,7 @@ import logging
|
||||||
import argparse
|
import argparse
|
||||||
from collections import deque
|
from collections import deque
|
||||||
|
|
||||||
|
from moulinette import msignals, msettings, m18n
|
||||||
from moulinette.core import (init_authenticator, MoulinetteError)
|
from moulinette.core import (init_authenticator, MoulinetteError)
|
||||||
|
|
||||||
logger = logging.getLogger('moulinette.interface')
|
logger = logging.getLogger('moulinette.interface')
|
||||||
|
|
|
@ -13,6 +13,7 @@ from geventwebsocket import WebSocketError
|
||||||
|
|
||||||
from bottle import run, request, response, Bottle, HTTPResponse
|
from bottle import run, request, response, Bottle, HTTPResponse
|
||||||
|
|
||||||
|
from moulinette import msignals, m18n, DATA_DIR
|
||||||
from moulinette.core import MoulinetteError, clean_session
|
from moulinette.core import MoulinetteError, clean_session
|
||||||
from moulinette.interfaces import (
|
from moulinette.interfaces import (
|
||||||
BaseActionsMapParser, BaseInterface, ExtendedArgumentParser,
|
BaseActionsMapParser, BaseInterface, ExtendedArgumentParser,
|
||||||
|
@ -780,11 +781,11 @@ class Interface(BaseInterface):
|
||||||
|
|
||||||
"""
|
"""
|
||||||
if category is None:
|
if category is None:
|
||||||
with open('%s/../doc/resources.json' % pkg.datadir) as f:
|
with open('%s/../doc/resources.json' % DATA_DIR) as f:
|
||||||
return f.read()
|
return f.read()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
with open('%s/../doc/%s.json' % (pkg.datadir, category)) as f:
|
with open('%s/../doc/%s.json' % (DATA_DIR, category)) as f:
|
||||||
return f.read()
|
return f.read()
|
||||||
except IOError:
|
except IOError:
|
||||||
return None
|
return None
|
||||||
|
|
|
@ -11,6 +11,7 @@ from collections import OrderedDict
|
||||||
|
|
||||||
import argcomplete
|
import argcomplete
|
||||||
|
|
||||||
|
from moulinette import msignals, m18n
|
||||||
from moulinette.core import MoulinetteError
|
from moulinette.core import MoulinetteError
|
||||||
from moulinette.interfaces import (
|
from moulinette.interfaces import (
|
||||||
BaseActionsMapParser, BaseInterface, ExtendedArgumentParser,
|
BaseActionsMapParser, BaseInterface, ExtendedArgumentParser,
|
||||||
|
|
|
@ -1,15 +0,0 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
|
|
||||||
# Public constants defined during build
|
|
||||||
|
|
||||||
"""Package's data directory (e.g. /usr/share/moulinette)"""
|
|
||||||
datadir = '%PKGDATADIR%'
|
|
||||||
|
|
||||||
"""Package's library directory (e.g. /usr/lib/moulinette)"""
|
|
||||||
libdir = '%PKGLIBDIR%'
|
|
||||||
|
|
||||||
"""Locale directory for the package (e.g. /usr/share/moulinette/locale)"""
|
|
||||||
localedir = '%PKGLOCALEDIR%'
|
|
||||||
|
|
||||||
"""Cache directory for the package (e.g. /var/cache/moulinette)"""
|
|
||||||
cachedir = '%PKGCACHEDIR%'
|
|
|
@ -5,6 +5,8 @@ import json
|
||||||
import grp
|
import grp
|
||||||
from pwd import getpwnam
|
from pwd import getpwnam
|
||||||
|
|
||||||
|
from moulinette import m18n
|
||||||
|
from moulinette.globals import CACHE_DIR
|
||||||
from moulinette.core import MoulinetteError
|
from moulinette.core import MoulinetteError
|
||||||
|
|
||||||
# Files & directories --------------------------------------------------
|
# Files & directories --------------------------------------------------
|
||||||
|
|
|
@ -2,6 +2,7 @@ import errno
|
||||||
import requests
|
import requests
|
||||||
import json
|
import json
|
||||||
|
|
||||||
|
from moulinette import m18n
|
||||||
from moulinette.core import MoulinetteError
|
from moulinette.core import MoulinetteError
|
||||||
|
|
||||||
|
|
||||||
|
|
25
setup.py
25
setup.py
|
@ -3,36 +3,19 @@ import os
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
from distutils.core import setup
|
from distutils.core import setup
|
||||||
from distutils.dir_util import mkpath
|
|
||||||
from distutils.sysconfig import PREFIX
|
|
||||||
|
|
||||||
# Define package directories
|
from moulinette.globals import LOCALES_DIR
|
||||||
datadir = os.path.join(PREFIX, 'share/moulinette')
|
|
||||||
libdir = os.path.join(PREFIX, 'lib/moulinette')
|
|
||||||
localedir = os.path.join(datadir, 'locale')
|
|
||||||
cachedir = '/var/cache/moulinette'
|
|
||||||
|
|
||||||
# Extend installation
|
# Extend installation
|
||||||
locale_files = []
|
locale_files = []
|
||||||
|
|
||||||
if "install" in sys.argv:
|
if "install" in sys.argv:
|
||||||
# Evaluate locale files
|
# Evaluate locale files
|
||||||
for f in os.listdir('locales'):
|
for f in os.listdir('locales'):
|
||||||
if f.endswith('.json'):
|
if f.endswith('.json'):
|
||||||
locale_files.append('locales/%s' % f)
|
locale_files.append('locales/%s' % f)
|
||||||
|
|
||||||
# Generate package.py
|
|
||||||
package = open('moulinette/package.py.in').read()
|
|
||||||
package = package.replace('%PKGDATADIR%', datadir) \
|
|
||||||
.replace('%PKGLIBDIR%', libdir) \
|
|
||||||
.replace('%PKGLOCALEDIR%', localedir) \
|
|
||||||
.replace('%PKGCACHEDIR%', cachedir)
|
|
||||||
with open('moulinette/package.py', 'w') as f:
|
|
||||||
f.write(package)
|
|
||||||
|
|
||||||
# Create needed directories
|
|
||||||
# mkpath(libdir, mode=0755, verbose=1)
|
|
||||||
# mkpath(os.path.join(datadir, 'actionsmap'), mode=0755, verbose=1)
|
|
||||||
|
|
||||||
|
|
||||||
setup(name='Moulinette',
|
setup(name='Moulinette',
|
||||||
version='2.0.0',
|
version='2.0.0',
|
||||||
|
@ -47,5 +30,5 @@ setup(name='Moulinette',
|
||||||
'moulinette.interfaces',
|
'moulinette.interfaces',
|
||||||
'moulinette.utils',
|
'moulinette.utils',
|
||||||
],
|
],
|
||||||
data_files=[(localedir, locale_files)]
|
data_files=[(LOCALES_DIR, locale_files)]
|
||||||
)
|
)
|
||||||
|
|
Loading…
Add table
Reference in a new issue