Merge branch 'unstable' into testing

This commit is contained in:
Jérôme Lebleu 2015-11-02 22:41:31 +01:00
commit f4c5f37614
6 changed files with 156 additions and 6 deletions

2
debian/copyright vendored
View file

@ -2,7 +2,7 @@ Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Source: https://github.com/YunoHost/moulinette
Files: *
Copyright: 2014 YUNOHOST.ORG
Copyright: 2015 YUNOHOST.ORG
License: AGPL-3
License: AGPL-3

0
debian/install vendored
View file

View file

@ -94,7 +94,7 @@ def api(namespaces, host='localhost', port=80, routes={},
'use_cache': use_cache })
moulinette.run(host, port)
def cli(namespaces, args, print_json=False, use_cache=True):
def cli(namespaces, args, print_json=False, print_plain=False, use_cache=True):
"""Command line interface
Execute an action with the moulinette from the CLI and print its
@ -104,6 +104,7 @@ def cli(namespaces, args, print_json=False, use_cache=True):
- namespaces -- The list of namespaces to use
- args -- A list of argument strings
- print_json -- True to print result as a JSON encoded string
- print_plain -- True to print result as a script-usable string
- use_cache -- False if it should parse the actions map file
instead of using the cached one
@ -114,7 +115,7 @@ def cli(namespaces, args, print_json=False, use_cache=True):
moulinette = init_interface('cli',
actionsmap={'namespaces': namespaces,
'use_cache': use_cache})
moulinette.run(args, print_json)
moulinette.run(args, print_json, print_plain)
except MoulinetteError as e:
print('%s %s' % (colorize(m18n.g('error'), 'red'), e.strerror))
return e.errno

View file

@ -194,7 +194,7 @@ class Translator(object):
try:
return _load_key(self.locale)
except KeyError:
except (KeyError, IndexError):
if self.default_locale != self.locale:
logger.info("untranslated key '%s' for locale '%s'",
key, self.locale)

View file

@ -42,8 +42,47 @@ def colorize(astr, color):
else:
return astr
def plain_print_dict(d, depth=0):
"""Print in a plain way a dictionary recursively
Print a dictionary recursively for scripting usage to the standard output.
Output formatting:
>>> d = {'key': 'value', 'list': [1,2], 'dict': {'key2': 'value2'}}
>>> plain_print_dict(d)
#key
value
#list
1
2
#dict
##key2
value2
Keyword arguments:
- d -- The dictionary to print
- depth -- The recursive depth of the dictionary
"""
# skip first key printing
if depth == 0 and (isinstance(d, dict) and len(d) == 1):
_, d = d.popitem()
if isinstance(d, (tuple, set)):
d = list(d)
if isinstance(d, list):
for v in d:
plain_print_dict(v, depth+1)
elif isinstance(d, dict):
for k,v in d.items():
print("{}{}".format("#" * (depth+1), k))
plain_print_dict(v, depth+1)
else:
if isinstance(d, unicode):
d = d.encode('utf-8')
print(d)
def pretty_print_dict(d, depth=0):
"""Print a dictionary recursively
"""Print in a pretty way a dictionary recursively
Print a dictionary recursively with colors to the standard output.
@ -187,7 +226,7 @@ class Interface(BaseInterface):
self.actionsmap = actionsmap
def run(self, args, print_json=False):
def run(self, args, print_json=False, print_plain=False):
"""Run the moulinette
Process the action corresponding to the given arguments 'args'
@ -196,8 +235,12 @@ class Interface(BaseInterface):
Keyword arguments:
- args -- A list of argument strings
- print_json -- True to print result as a JSON encoded string
- print_plain -- True to print result as a script-usable string
"""
if print_json and print_plain:
raise MoulinetteError(errno.EINVAL, m18n.g('invalid_usage'))
try:
ret = self.actionsmap.process(args, timeout=5)
except KeyboardInterrupt, EOFError:
@ -211,6 +254,8 @@ class Interface(BaseInterface):
import json
from moulinette.utils.serialize import JSONExtendedEncoder
print(json.dumps(ret, cls=JSONExtendedEncoder))
elif print_plain:
plain_print_dict(ret)
elif isinstance(ret, dict):
pretty_print_dict(ret)
else:

View file

@ -0,0 +1,104 @@
import os
import shutil
from pwd import getpwnam
from grp import getgrnam
# Files & directories --------------------------------------------------
def mkdir(path, mode=0777, parents=False, uid=None, gid=None, force=False):
"""Create a directory with optional features
Create a directory and optionaly set its permissions to mode and its
owner and/or group. If path refers to an existing path, nothing is done
unless force is True.
Keyword arguments:
- path -- The directory to create
- mode -- Numeric path mode to set
- parents -- Make parent directories as needed
- uid -- Numeric uid or user name
- gid -- Numeric gid or group name
- force -- Force directory creation and owning even if the path exists
"""
if os.path.exists(path) and not force:
return
if parents:
os.makedirs(path, mode)
else:
os.mkdir(path, mode)
try:
chown(path, uid, gid)
except:
pass
def chown(path, uid=None, gid=None, recursive=False):
"""Change the owner and/or group of a path
Keyword arguments:
- uid -- Numeric uid or user name
- gid -- Numeric gid or group name
- recursive -- Operate on path recursively
"""
if uid is None and gid is None:
raise ValueError("either uid or gid argument is required")
# Retrieve uid/gid
if isinstance(uid, basestring):
uid = getpwnam(uid).pw_uid
elif uid is None:
uid = -1
if isinstance(gid, basestring):
gid = getpwnam(gid).gr_gid
elif gid is None:
gid = -1
os.chown(path, uid, gid)
if recursive and os.path.isdir(path):
for root, dirs, files in os.walk(path):
for d in dirs:
os.chown(os.path.join(root, d), uid, gid)
for f in files:
os.chown(os.path.join(root, f), uid, gid)
def chmod(path, mode, fmode=None, recursive=False):
"""Change the mode of a path
Keyword arguments:
- mode -- Numeric path mode to set
- fmode -- Numeric file mode to set in case of a recursive directory
- recursive -- Operate on path recursively
"""
os.chmod(path, mode)
if recursive and os.path.isdir(path):
if fmode is None:
fmode = mode
for root, dirs, files in os.walk(path):
for d in dirs:
os.chmod(path, mode)
for f in files:
os.chmod(path, fmode)
def rm(path, recursive=False, force=False):
"""Remove a file or directory
Keyword arguments:
- path -- The path to remove
- recursive -- Remove directories and their contents recursively
- force -- Ignore nonexistent files
"""
if recursive and os.path.isdir(path):
shutil.rmtree(path, ignore_errors=force)
else:
try:
os.remove(path)
except OSError:
if not force:
raise