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
|
||||
# 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
|
||||
# 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
|
||||
html_sidebars = {
|
||||
'**': [
|
||||
'about.html',
|
||||
'navigation.html',
|
||||
'relations.html', # needs 'show_related': True theme option to display
|
||||
# 'about.html',
|
||||
# 'navigation.html',
|
||||
# 'relations.html', # needs 'show_related': True theme option to display
|
||||
'searchbox.html',
|
||||
'donate.html',
|
||||
# 'donate.html',
|
||||
]
|
||||
}
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@ a reference.
|
|||
:maxdepth: 2
|
||||
:caption: Contents:
|
||||
|
||||
m18n
|
||||
utils/filesystem
|
||||
utils/network
|
||||
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 -*-
|
||||
|
||||
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'
|
||||
__version__ = '0.1'
|
||||
|
@ -27,11 +28,17 @@ __credits__ = """
|
|||
along with this program; if not, see http://www.gnu.org/licenses
|
||||
"""
|
||||
__all__ = [
|
||||
'init', 'api', 'cli',
|
||||
'init', 'api', 'cli', 'm18n',
|
||||
'init_interface', 'MoulinetteError',
|
||||
'DATA_DIR', 'LIB_DIR', 'LOCALES_DIR', 'CACHE_DIR',
|
||||
]
|
||||
|
||||
|
||||
msignals = MoulinetteSignals()
|
||||
msettings = dict()
|
||||
m18n = Moulinette18n()
|
||||
|
||||
|
||||
# Package functions
|
||||
|
||||
def init(logging_config=None, **kwargs):
|
||||
|
@ -50,22 +57,12 @@ def init(logging_config=None, **kwargs):
|
|||
|
||||
"""
|
||||
import sys
|
||||
import __builtin__
|
||||
from moulinette.core import (
|
||||
Package, Moulinette18n, MoulinetteSignals
|
||||
)
|
||||
from moulinette.utils.log import configure_logging
|
||||
|
||||
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
|
||||
sys.path.insert(0, pkg.libdir)
|
||||
sys.path.insert(0, LIB_DIR)
|
||||
|
||||
|
||||
# Easy access to interfaces
|
||||
|
|
|
@ -9,6 +9,9 @@ import cPickle as pickle
|
|||
from time import time
|
||||
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.interfaces import (
|
||||
BaseActionsMapParser, GLOBAL_SECTION, TO_RETURN_PROP
|
||||
|
@ -373,10 +376,10 @@ class ActionsMap(object):
|
|||
for n in namespaces:
|
||||
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_pkl = '%s/actionsmap/%s-%d-%d.pkl' % (
|
||||
pkg.cachedir,
|
||||
CACHE_DIR,
|
||||
n,
|
||||
actionsmap_yml_stat.st_size,
|
||||
actionsmap_yml_stat.st_mtime
|
||||
|
@ -498,7 +501,7 @@ class ActionsMap(object):
|
|||
"""
|
||||
namespaces = []
|
||||
|
||||
for f in os.listdir('%s/actionsmap' % pkg.datadir):
|
||||
for f in os.listdir('%s/actionsmap' % DATA_DIR):
|
||||
if f.endswith('.yml'):
|
||||
namespaces.append(f[:-4])
|
||||
return namespaces
|
||||
|
@ -524,23 +527,23 @@ class ActionsMap(object):
|
|||
logger.debug("generating cache for actions map namespace '%s'", n)
|
||||
|
||||
# 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:
|
||||
actionsmaps[n] = ordered_yaml_load(f)
|
||||
|
||||
# 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
|
||||
for i in os.listdir('%s/actionsmap/' % pkg.cachedir):
|
||||
for i in os.listdir('%s/actionsmap/' % CACHE_DIR):
|
||||
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
|
||||
am_file_stat = os.stat(am_file)
|
||||
|
||||
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)
|
||||
|
||||
return actionsmaps
|
||||
|
|
|
@ -4,6 +4,8 @@ import errno
|
|||
import gnupg
|
||||
import logging
|
||||
|
||||
from moulinette import m18n
|
||||
from moulinette.cache import open_cachefile
|
||||
from moulinette.core import MoulinetteError
|
||||
|
||||
logger = logging.getLogger('moulinette.authenticator')
|
||||
|
@ -129,8 +131,8 @@ class BaseAuthenticator(object):
|
|||
|
||||
def _open_sessionfile(self, session_id, mode='r'):
|
||||
"""Open a session file for this instance in given mode"""
|
||||
return pkg.open_cachefile('%s.asc' % session_id, mode,
|
||||
subdir='session/%s' % self.name)
|
||||
return open_cachefile('%s.asc' % session_id, mode,
|
||||
subdir='session/%s' % self.name)
|
||||
|
||||
def _store_session(self, session_id, session_hash, password):
|
||||
"""Store a session and its associated password"""
|
||||
|
|
|
@ -7,6 +7,7 @@ import logging
|
|||
import ldap
|
||||
import ldap.modlist as modlist
|
||||
|
||||
from moulinette import m18n
|
||||
from moulinette.core import MoulinetteError
|
||||
from moulinette.authenticators import BaseAuthenticator
|
||||
|
||||
|
@ -212,5 +213,5 @@ class Authenticator(BaseAuthenticator):
|
|||
attr, value)
|
||||
raise MoulinetteError(errno.EEXIST,
|
||||
m18n.g('ldap_attribute_already_exists',
|
||||
attribute=attr, value=value))
|
||||
attribute=attr, value=value))
|
||||
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
|
||||
|
||||
import moulinette
|
||||
from moulinette.globals import LOCALES_DIR, LIB_DIR
|
||||
from moulinette.cache import get_cachedir
|
||||
|
||||
|
||||
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 -------------------------------------------------
|
||||
|
||||
class Translator(object):
|
||||
|
@ -187,20 +87,15 @@ class Translator(object):
|
|||
- key -- The key to translate
|
||||
|
||||
"""
|
||||
def _load_key(locale):
|
||||
value = self._translations[locale][key]
|
||||
return value.encode('utf-8').format(*args, **kwargs)
|
||||
if key in self._translations.get(self.locale, {}):
|
||||
return self._translations[self.locale][key].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'",
|
||||
key, self.default_locale)
|
||||
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.locale = default_locale
|
||||
self.pkg = package
|
||||
|
||||
# Init global translator
|
||||
self._global = Translator(self.pkg.localedir, default_locale)
|
||||
self._global = Translator(LOCALES_DIR, default_locale)
|
||||
|
||||
# Define namespace related variables
|
||||
self._namespaces = {}
|
||||
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):
|
||||
"""Load the namespace to use
|
||||
|
||||
|
@ -273,10 +162,10 @@ class Moulinette18n(object):
|
|||
"""
|
||||
if namespace not in self._namespaces:
|
||||
# Create new Translator object
|
||||
n = Translator('%s/%s/locales' % (self.pkg.libdir, namespace),
|
||||
self.default_locale)
|
||||
n.set_locale(self.locale)
|
||||
self._namespaces[namespace] = n
|
||||
translator = Translator('%s/%s/locales' % (LIB_DIR, namespace),
|
||||
self.default_locale)
|
||||
translator.set_locale(self.locale)
|
||||
self._namespaces[namespace] = translator
|
||||
|
||||
# Set current namespace
|
||||
self._current_namespace = namespace
|
||||
|
@ -312,12 +201,7 @@ class Moulinette18n(object):
|
|||
- key -- The key to translate
|
||||
|
||||
"""
|
||||
try:
|
||||
return self._namespace.translate(key, *args, **kwargs)
|
||||
except:
|
||||
logger.exception("cannot translate key '%s' for namespace '%s'",
|
||||
key, self._current_namespace)
|
||||
return key
|
||||
return self._namespaces[self._current_namespace].translate(key, *args, **kwargs)
|
||||
|
||||
|
||||
class MoulinetteSignals(object):
|
||||
|
@ -450,7 +334,7 @@ def init_interface(name, kwargs={}, actionsmap={}):
|
|||
mod = import_module('moulinette.interfaces.%s' % name)
|
||||
except ImportError:
|
||||
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:
|
||||
try:
|
||||
# Retrieve interface classes
|
||||
|
@ -458,7 +342,7 @@ def init_interface(name, kwargs={}, actionsmap={}):
|
|||
interface = mod.Interface
|
||||
except AttributeError:
|
||||
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
|
||||
if isinstance(actionsmap, dict):
|
||||
|
@ -467,7 +351,7 @@ def init_interface(name, kwargs={}, actionsmap={}):
|
|||
amap = actionsmap
|
||||
else:
|
||||
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)
|
||||
|
||||
|
@ -488,7 +372,7 @@ def init_authenticator((vendor, name), kwargs={}):
|
|||
mod = import_module('moulinette.authenticators.%s' % vendor)
|
||||
except ImportError:
|
||||
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:
|
||||
return mod.Authenticator(name, **kwargs)
|
||||
|
||||
|
@ -504,7 +388,7 @@ def clean_session(session_id, profiles=[]):
|
|||
- profiles -- A list of profiles to clean
|
||||
|
||||
"""
|
||||
sessiondir = pkg.get_cachedir('session')
|
||||
sessiondir = get_cachedir('session')
|
||||
if not profiles:
|
||||
profiles = os.listdir(sessiondir)
|
||||
|
||||
|
@ -578,7 +462,7 @@ class MoulinetteLock(object):
|
|||
|
||||
if self.timeout is not None and (time.time() - start_time) > self.timeout:
|
||||
raise MoulinetteError(errno.EBUSY,
|
||||
m18n.g('instance_already_running'))
|
||||
moulinette.m18n.g('instance_already_running'))
|
||||
# Wait before checking again
|
||||
time.sleep(self.interval)
|
||||
|
||||
|
@ -605,8 +489,8 @@ class MoulinetteLock(object):
|
|||
except IOError:
|
||||
raise MoulinetteError(
|
||||
errno.EPERM, '%s. %s.'.format(
|
||||
m18n.g('permission_denied'),
|
||||
m18n.g('root_required')))
|
||||
moulinette.m18n.g('permission_denied'),
|
||||
moulinette.m18n.g('root_required')))
|
||||
|
||||
def __enter__(self):
|
||||
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
|
||||
from collections import deque
|
||||
|
||||
from moulinette import msignals, msettings, m18n
|
||||
from moulinette.core import (init_authenticator, MoulinetteError)
|
||||
|
||||
logger = logging.getLogger('moulinette.interface')
|
||||
|
|
|
@ -13,6 +13,7 @@ from geventwebsocket import WebSocketError
|
|||
|
||||
from bottle import run, request, response, Bottle, HTTPResponse
|
||||
|
||||
from moulinette import msignals, m18n, DATA_DIR
|
||||
from moulinette.core import MoulinetteError, clean_session
|
||||
from moulinette.interfaces import (
|
||||
BaseActionsMapParser, BaseInterface, ExtendedArgumentParser,
|
||||
|
@ -780,11 +781,11 @@ class Interface(BaseInterface):
|
|||
|
||||
"""
|
||||
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()
|
||||
|
||||
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()
|
||||
except IOError:
|
||||
return None
|
||||
|
|
|
@ -11,6 +11,7 @@ from collections import OrderedDict
|
|||
|
||||
import argcomplete
|
||||
|
||||
from moulinette import msignals, m18n
|
||||
from moulinette.core import MoulinetteError
|
||||
from moulinette.interfaces import (
|
||||
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
|
||||
from pwd import getpwnam
|
||||
|
||||
from moulinette import m18n
|
||||
from moulinette.globals import CACHE_DIR
|
||||
from moulinette.core import MoulinetteError
|
||||
|
||||
# Files & directories --------------------------------------------------
|
||||
|
|
|
@ -2,6 +2,7 @@ import errno
|
|||
import requests
|
||||
import json
|
||||
|
||||
from moulinette import m18n
|
||||
from moulinette.core import MoulinetteError
|
||||
|
||||
|
||||
|
|
25
setup.py
25
setup.py
|
@ -3,36 +3,19 @@ import os
|
|||
import sys
|
||||
|
||||
from distutils.core import setup
|
||||
from distutils.dir_util import mkpath
|
||||
from distutils.sysconfig import PREFIX
|
||||
|
||||
# Define package directories
|
||||
datadir = os.path.join(PREFIX, 'share/moulinette')
|
||||
libdir = os.path.join(PREFIX, 'lib/moulinette')
|
||||
localedir = os.path.join(datadir, 'locale')
|
||||
cachedir = '/var/cache/moulinette'
|
||||
from moulinette.globals import LOCALES_DIR
|
||||
|
||||
|
||||
# Extend installation
|
||||
locale_files = []
|
||||
|
||||
if "install" in sys.argv:
|
||||
# Evaluate locale files
|
||||
for f in os.listdir('locales'):
|
||||
if f.endswith('.json'):
|
||||
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',
|
||||
version='2.0.0',
|
||||
|
@ -47,5 +30,5 @@ setup(name='Moulinette',
|
|||
'moulinette.interfaces',
|
||||
'moulinette.utils',
|
||||
],
|
||||
data_files=[(localedir, locale_files)]
|
||||
data_files=[(LOCALES_DIR, locale_files)]
|
||||
)
|
||||
|
|
Loading…
Reference in a new issue