Merge branch 'stretch-unstable' into simplify-auth-mechanism

This commit is contained in:
Alexandre Aubin 2019-11-19 16:55:06 +01:00
commit 9fda7f4716
17 changed files with 242 additions and 61 deletions

View file

@ -1,3 +1,6 @@
[![Build Status](https://travis-ci.org/YunoHost/moulinette.svg?branch=stretch-unstable)](https://travis-ci.org/YunoHost/moulinette)
[![GitHub license](https://img.shields.io/github/license/YunoHost/moulinette)](https://github.com/YunoHost/moulinette/blob/stretch-unstable/LICENSE)
Moulinette
==========
@ -37,15 +40,10 @@ operation on an interface for example (see
[Authenticators](#authenticators)).
### Actions Map
...
### Interfaces
...
### Authenticators
...
Dev Documentation
-----------------
https://moulinette.readthedocs.org
Requirements
------------

24
debian/changelog vendored
View file

@ -1,3 +1,27 @@
moulinette (3.7.0) testing; urgency=low
# ~ Major stuff
- [enh] Add group and permission mechanism ([Moulinette#189](https://github.com/YunoHost/moulinette/pull/189)
- [mod] Be able to customize prompt colors ([Moulinette/808f620](https://github.com/YunoHost/Moulinette/commit/808f620))
- [enh] Support app manifests in toml ([Moulinette#204](https://github.com/YunoHost/moulinette/pull/204), [Moulinette/55515cb](https://github.com/YunoHost/Moulinette/commit/55515cb))
- [enh] Quite a lot of messages improvements, string cleaning, language rework... ([Moulinette/599bec3](https://github.com/YunoHost/Moulinette/commit/599bec3), [Moulinette#208](https://github.com/YunoHost/moulinette/pull/208), [Moulinette#213](https://github.com/YunoHost/moulinette/pull/213), [Moulinette/b7d415d](https://github.com/YunoHost/Moulinette/commit/b7d415d), [Moulinette/a8966b8](https://github.com/YunoHost/Moulinette/commit/a8966b8), [Moulinette/fdf9a71](https://github.com/YunoHost/Moulinette/commit/fdf9a71), [Moulinette/d895ae3](https://github.com/YunoHost/Moulinette/commit/d895ae3), [Moulinette/bdf0a1c](https://github.com/YunoHost/Moulinette/commit/bdf0a1c))
- [i18n] Improved translations for Catalan, Occitan, French, Arabic, Spanish, German, Norwegian Bokmål
# Smaller or pretty technical fix/enh
- [enh] Preparations for moulinette Python3 migration (Tox, Pytest and unit tests) ([Moulinette#203](https://github.com/YunoHost/moulinette/pull/203), [Moulinette#206](https://github.com/YunoHost/moulinette/pull/206), [Moulinette#207](https://github.com/YunoHost/moulinette/pull/207), [Moulinette#210](https://github.com/YunoHost/moulinette/pull/210), [Moulinette#211](https://github.com/YunoHost/moulinette/pull/211) [Moulinette#212](https://github.com/YunoHost/moulinette/pull/212), [Moulinette/2403ee1](https://github.com/YunoHost/Moulinette/commit/2403ee1), [Moulinette/69b0d49](https://github.com/YunoHost/Moulinette/commit/69b0d49), [Moulinette/49c749c](https://github.com/YunoHost/Moulinette/commit/49c749c), [Moulinette/2c84ee1](https://github.com/YunoHost/Moulinette/commit/2c84ee1), [Moulinette/cef72f7](https://github.com/YunoHost/Moulinette/commit/cef72f7))
- [enh] Add a write_to_yaml utility similar to write_to_json ([Moulinette/2e2e627](https://github.com/YunoHost/Moulinette/commit/2e2e627))
- [enh] Warn the user about long locks ([Moulinette#205](https://github.com/YunoHost/moulinette/pull/205))
- [mod] Tweak stuff about setuptools and moulinette deps? ([Moulinette/b739f27](https://github.com/YunoHost/Moulinette/commit/b739f27), [Moulinette/da00fc9](https://github.com/YunoHost/Moulinette/commit/da00fc9), [Moulinette/d8cbbb0](https://github.com/YunoHost/Moulinette/commit/d8cbbb0))
- [fix] Misc micro bugfixes or improvements ([Moulinette/83d9e77](https://github.com/YunoHost/Moulinette/commit/83d9e77))
- [doc] Fix doc building + add doc build tests with Tox ([Moulinette/f1ac5b8](https://github.com/YunoHost/Moulinette/commit/f1ac5b8), [Moulinette/df7d478](https://github.com/YunoHost/Moulinette/commit/df7d478), [Moulinette/74c8f79](https://github.com/YunoHost/Moulinette/commit/74c8f79), [Moulinette/bcf92c7](https://github.com/YunoHost/Moulinette/commit/bcf92c7), [Moulinette/af2c80c](https://github.com/YunoHost/Moulinette/commit/af2c80c), [Moulinette/d52a574](https://github.com/YunoHost/Moulinette/commit/d52a574), [Moulinette/307f660](https://github.com/YunoHost/Moulinette/commit/307f660), [Moulinette/dced104](https://github.com/YunoHost/Moulinette/commit/dced104), [Moulinette/ed3823b](https://github.com/YunoHost/Moulinette/commit/ed3823b))
- [enh] READMEs improvements ([Moulinette/1541b74](https://github.com/YunoHost/Moulinette/commit/1541b74), [Moulinette/ad1eeef](https://github.com/YunoHost/Moulinette/commit/ad1eeef))
Thanks to all contributors <3 ! (accross all repo: Yunohost, Moulinette, SSOwat, Yunohost-admin) : advocatux, Aksel K., Aleks, Allan N., amirale qt, Armin P., Bram, ButterflyOfFire, Carles S. A., chema o. r., decentral1se, Emmanuel V., Etienne M., Filip B., Geoff M., htsr, Jibec, Josué, Julien J., Kayou, liberodark, ljf, lucaskev, Lukas D., madtibo, Martin D., Mélanie C., nr 458 h, pitfd, ppr, Quentí, sidddy, troll, tufek yamero, xaloc33, yalh76
-- Alexandre Aubin <alex.aubin@mailoo.org> Thu, 31 Oct 2019 18:40:00 +0000
moulinette (3.6.4.1) stable; urgency=low
- [fix] Catch all exceptions in read_yaml helper

View file

@ -31,7 +31,7 @@
"server_already_running": "هناك خادم يشتغل على ذاك المنفذ",
"success": "تم بنجاح !",
"unable_authenticate": "تعذرت المصادقة",
"unable_retrieve_session": "تعذرت مواصلة الجلسة",
"unable_retrieve_session": "تعذرت مواصلة الجلسة بسبب '{exception}'",
"unknown_group": "الفريق '{group}' مجهول",
"unknown_user": "المستخدم '{user}' مجهول",
"values_mismatch": "القيمتين غير متطابقتين",
@ -39,7 +39,7 @@
"websocket_request_expected": "كان ينتظر طلبًا عبر الويب سوكت WebSocket",
"cannot_open_file": "ليس بالإمكان فتح الملف {file:s} (السبب : {error:s})",
"cannot_write_file": "لا يمكن الكتابة في الملف {file:s} (السبب : {error:s})",
"unknown_error_reading_file": "طرأ هناك خطأ ما أثناء عملية قراءة الملف {file:s}",
"unknown_error_reading_file": "طرأ هناك خطأ ما أثناء عملية قراءة الملف {file:s} (السبب: {error:s})",
"corrupted_json": "قراءة json مُشوّهة مِن {ressource:s} (السبب : {error:s})",
"error_writing_file": "طرأ هناك خطأ أثناء الكتابة في الملف {file:s}: {error:s}",
"error_removing": "خطأ أثناء عملية حذف {path:s}: {error:s}",
@ -49,7 +49,8 @@
"download_timeout": "{url:s} استغرق مدة طويلة جدا للإستجابة، فتوقّف.",
"download_unknown_error": "خطأ أثناء عملية تنزيل البيانات مِن {url:s} : {error:s}",
"download_bad_status_code": "{url:s} أعاد رمز الحالة {code:s}",
"command_unknown": "الأمر '{command:s}' غير معروف ؟",
"command_unknown": "الأمر '{command:s}' مجهول؟",
"corrupted_yaml": "قراءة مُشوّهة لنسق yaml مِن {ressource:s} (السبب : {error:s})",
"info": "معلومة:"
"info": "معلومة:",
"warn_the_user_about_waiting_lock_again": "جارٍ الانتظار…"
}

View file

@ -31,7 +31,7 @@
"server_already_running": "Ja s'està executant un servidor en aquest port",
"success": "Èxit!",
"unable_authenticate": "No s'ha pogut autenticar",
"unable_retrieve_session": "No s'ha pogut recuperar la sessió",
"unable_retrieve_session": "No s'ha pogut recuperar la sessió a causa de «{exception}»",
"unknown_group": "Grup '{group}' desconegut",
"unknown_user": "Usuari '{user}' desconegut",
"values_mismatch": "Els valors no coincideixen",
@ -39,7 +39,7 @@
"websocket_request_expected": "S'esperava una petició WebSocket",
"cannot_open_file": "No s'ha pogut obrir el fitxer {file:s} (motiu: {error:s})",
"cannot_write_file": "No s'ha pogut escriure el fitxer {file:s} (motiu: {error:s})",
"unknown_error_reading_file": "Error desconegut al intentar llegir el fitxer {file:s}",
"unknown_error_reading_file": "Error desconegut al intentar llegir el fitxer {file:s} (motiu: {error:s})",
"corrupted_json": "Json corrupte llegit des de {ressource:s} (motiu: {error:s})",
"corrupted_yaml": "Yaml corrupte llegit des de {ressource:s} (motiu: {error:s})",
"error_writing_file": "Error al escriure el fitxer {file:s}: {error:s}",
@ -51,5 +51,9 @@
"download_unknown_error": "Error al baixar dades des de {url:s}: {error:s}",
"download_bad_status_code": "{url:s} ha retornat el codi d'estat {code:s}",
"command_unknown": "Ordre '{command:s}' desconegut ?",
"info": "Info:"
"info": "Info:",
"corrupted_toml": "El fitxer TOML ha estat corromput en la lectura des de {ressource:s} (motiu: {error:s})",
"warn_the_user_about_waiting_lock": "Hi ha una altra ordre de YunoHost en execució, s'executarà aquesta ordre un cop l'anterior hagi acabat",
"warn_the_user_about_waiting_lock_again": "Encara en espera…",
"warn_the_user_that_lock_is_acquired": "l'altra ordre tot just ha acabat, ara s'executarà aquesta ordre"
}

View file

@ -11,7 +11,7 @@
"file_not_exist": "Datei ist nicht vorhanden: '{path}'",
"folder_exists": "Ordner existiert bereits: '{path}'",
"folder_not_exist": "Ordner existiert nicht",
"instance_already_running": "Eine Instanz läuft bereits",
"instance_already_running": "Es läuft bereits eine YunoHost-Operation. Bitte warte, bis sie fertig ist, bevor du eine weitere startest.",
"invalid_argument": "Argument ungültig '{argument}': {error}",
"invalid_password": "Passwort falsch",
"invalid_usage": "Falscher Aufruf, verwende --help für den Hilfstext",
@ -29,12 +29,13 @@
"server_already_running": "Einen anderer Dienst arbeitet bereits auf diesem Port",
"success": "Erfolg!",
"unable_authenticate": "Anmelden fehlgeschlagen",
"unable_retrieve_session": "Sitzung konnte nicht abgerufen werden",
"unable_retrieve_session": "Sitzung konnte nicht abgerufen werden. Grund: '{exception}'",
"values_mismatch": "Die Werte passen nicht",
"warning": "Warnung:",
"websocket_request_expected": "Eine WebSocket Anfrage wurde erwartet",
"deprecated_command": "'{prog} {command}' ist veraltet und wird bald entfernt werden",
"deprecated_command_alias": "'{prog} {old}' ist veraltet und wird bald entfernt werden, benutze '{prog} {new}' stattdessen",
"unknown_group": "Gruppe '{group}' ist unbekannt",
"unknown_user": "Benutzer '{user}' ist unbekannt"
"unknown_user": "Benutzer '{user}' ist unbekannt",
"info": "Info:"
}

View file

@ -13,7 +13,7 @@
"folder_exists": "Folder already exists: '{path}'",
"folder_not_exist": "Folder does not exist",
"info": "Info:",
"instance_already_running": "An instance is already running",
"instance_already_running": "There is already a YunoHost operation running. Please wait for it to finish before running another one.",
"invalid_argument": "Invalid argument '{argument}': {error}",
"invalid_password": "Invalid password",
"invalid_token": "Invalid token - please authenticate",

View file

@ -1,23 +1,23 @@
{
"argument_required": "Se requiere el argumento '{argument}'",
"authentication_profile_required": "Autenticación requerida para el perfil '{profile}'",
"argument_required": "Se requiere el argumento «{argument}»",
"authentication_profile_required": "Autentificación requerida para el perfil «{profile}»",
"authentication_required": "Se requiere autentificación",
"authentication_required_long": "Debe autenticarse para realizar esta acción",
"authentication_required_long": "Debe autentificarse para realizar esta acción",
"colon": "{}: ",
"confirm": "Confirmar {prompt}",
"deprecated_command": "'{prog} {command}' está obsoleto y será eliminado en el futuro",
"deprecated_command_alias": "'{prog} {old}' está obsoleto y se eliminará en el futuro, use '{prog} {new}' en su lugar",
"deprecated_command": "«{prog} {command}» está obsoleto y será eliminado en el futuro",
"deprecated_command_alias": "«{prog} {old}» está obsoleto y se eliminará en el futuro, use «{prog} {new}» en su lugar",
"error": "Error:",
"error_see_log": "Ha ocurrido un error. Consulte el registro para obtener más información, localizado en /var/log/yunohost/.",
"file_exists": "El archivo ya existe: '{path}'",
"file_not_exist": "El archivo no existe: '{path}'",
"folder_exists": "El directorio ya existe: '{path}'",
"folder_not_exist": "El directorio no existe",
"instance_already_running": "Una instancia ya se está ejecutando",
"invalid_argument": "Argumento no válido '{argument}': {error}",
"file_exists": "El archivo ya existe: «{path}»",
"file_not_exist": "El archivo no existe: «{path}»",
"folder_exists": "El directorio ya existe: «{path}»",
"folder_not_exist": "La carpeta no existe",
"instance_already_running": "Ya se está ejecutando una instancia de YunoHost. Espere a que termine antes de ejecutar otra.",
"invalid_argument": "Argumento no válido «{argument}»: {error}",
"invalid_password": "Contraseña no válida",
"invalid_usage": "Uso no válido, utilice --help para ver la ayuda",
"ldap_attribute_already_exists": "El atributo '{attribute}' ya existe con el valor '{value}'",
"ldap_attribute_already_exists": "El atributo «{attribute}» ya existe con el valor «{value}»",
"ldap_operation_error": "Ha ocurrido un error durante la operación de LDAP",
"ldap_server_down": "No se pudo conectar con el servidor LDAP",
"logged_in": "Sesión iniciada",
@ -30,26 +30,30 @@
"root_required": "Solo root puede realizar esta acción",
"server_already_running": "Ya se está ejecutando un servidor en ese puerto",
"success": "¡Éxito!",
"unable_authenticate": "No se puede autenticar",
"unable_retrieve_session": "No se puede recuperar la sesión",
"unknown_group": "Grupo '{group}' desconocido",
"unknown_user": "Usuario '{user}' desconocido",
"unable_authenticate": "No se puede autentificar",
"unable_retrieve_session": "No se puede recuperar la sesión por «{exception}»",
"unknown_group": "Grupo «{group}» desconocido",
"unknown_user": "Usuario «{user}» desconocido",
"values_mismatch": "Los valores no coinciden",
"warning": "Advertencia:",
"websocket_request_expected": "Se esperaba una petición WebSocket",
"cannot_open_file": "No se pudo abrir el fichero{file:s} (motivo:{error:s})",
"cannot_write_file": "No se pudo escribir el fichero {file:s} (motivo: {error:s})",
"unknown_error_reading_file": "Error desconocido al intentar leer el fichero {file:s}",
"corrupted_json": "Json corrupto leido desde {ressource:s} (motivo: {error:s})",
"error_writing_file": "Error al escribir el fichero {file:s}: {error:s}",
"cannot_open_file": "No se pudo abrir el archivo {file:s} (motivo: {error:s})",
"cannot_write_file": "No se pudo escribir el archivo {file:s} (motivo: {error:s})",
"unknown_error_reading_file": "Error desconocido al intentar leer el archivo {file:s} (motivo: {error:s})",
"corrupted_json": "Lectura corrupta de Json desde {ressource:s} (motivo: {error:s})",
"error_writing_file": "Error al escribir el archivo {file:s}: {error:s}",
"error_removing": "Error al eliminar {path:s}: {error:s}",
"error_changing_file_permissions": "Error al cambiar los permisos para {path:s}: {error:s}",
"invalid_url": "Url no válida {url:s} (¿existe este sitio web?)",
"invalid_url": "Url no válida {url:s} (¿Existe este sitio?)",
"download_ssl_error": "Error SSL al conectar con {url:s}",
"download_timeout": "{url:s} tardó demasiado en responder, me rindo.",
"download_timeout": "{url:s} tardó demasiado en responder, abandono.",
"download_unknown_error": "Error al descargar datos desde {url:s} : {error:s}",
"download_bad_status_code": "{url:s} devolvió el código de estado {code:s}",
"command_unknown": "Comando '{command:s}' desconocido ?",
"corrupted_yaml": "yaml corrupto leido desde {ressource:s} (motivo: {error:s})",
"info": "Información:"
"command_unknown": "¿Orden «{command:s}» desconocida?",
"corrupted_yaml": "Lectura corrupta de yaml desde {ressource:s} (motivo: {error:s})",
"info": "Información:",
"corrupted_toml": "Lectura corrupta de TOML desde {ressource:s} (motivo: {error:s})",
"warn_the_user_that_lock_is_acquired": "la otra orden ha terminado, iniciando esta orden ahora",
"warn_the_user_about_waiting_lock_again": "Aún esperando...",
"warn_the_user_about_waiting_lock": "Otra orden de YunoHost se está ejecutando ahora, estamos esperando a que termine antes de ejecutar esta"
}

View file

@ -13,7 +13,7 @@
"file_not_exist": "Le fichier '{path}' nexiste pas",
"folder_exists": "Le dossier existe déjà : '{path}'",
"folder_not_exist": "Le dossier nexiste pas",
"instance_already_running": "Une instance est déjà en cours dexécution",
"instance_already_running": "Une instance est déjà en cours dexécution, merci d'attendre sa fin avant d'en lancer une autre.",
"invalid_argument": "Argument '{argument}' incorrect : {error}",
"invalid_password": "Mot de passe incorrect",
"invalid_usage": "Utilisation erronée, utilisez --help pour accéder à laide",
@ -52,8 +52,8 @@
"command_unknown": "Commande '{command:s}' inconnue ?",
"corrupted_yaml": "Fichier YAML corrompu en lecture depuis {ressource:s} (raison : {error:s})",
"info": "Info :",
"corrupted_toml": "Fichier toml corrompu lu depuis {ressources:s}(cause: {error:s})",
"warn_the_user_about_waiting_lock": "Une autre commande Yunohost est en cours, nous attendons qu'elle se termine avant de lancer celle là",
"corrupted_toml": "Fichier TOML corrompu en lecture depuis {ressource:s} (cause : {error:s})",
"warn_the_user_about_waiting_lock": "Une autre commande YunoHost est actuellement en cours, nous attendons qu'elle se termine avant de démarrer celle là",
"warn_the_user_about_waiting_lock_again": "Toujours en attente...",
"warn_the_user_that_lock_is_acquired": "l'autre commande vient de se terminer, lancement de cette commande"
}

View file

@ -1 +1,22 @@
{}
{
"argument_required": "Argumentet '{argument}' er påkrevd",
"warn_the_user_about_waiting_lock_again": "Venter fremdeles…",
"websocket_request_expected": "Forventet en WebSocket-forespørsel",
"warning": "Advarsel:",
"values_mismatch": "Verdiene samsvarer ikke",
"unknown_user": "Ukjent '{group}' bruker",
"unknown_group": "Ukjent '{group}' gruppe",
"unable_authenticate": "Kunne ikke identitetsbekrefte",
"success": "Vellykket.",
"operation_interrupted": "Operasjon forstyrret",
"not_logged_in": "Du er ikke innlogget",
"logged_in": "Innlogget",
"invalid_password": "Ugyldig passord",
"info": "Info:",
"file_exists": "Filen finnes allerede: '{path}'",
"error": "Feil:",
"confirm": "Bekreft {prompt}",
"colon": "{}: ",
"logged_out": "Utlogget",
"password": "Passord"
}

View file

@ -24,7 +24,7 @@
"pattern_not_match": "Correspond pas al patron",
"permission_denied": "Permission refusada",
"root_required": "Cal èsser root per realizar aquesta accion",
"unable_retrieve_session": "Impossible de recuperar la session",
"unable_retrieve_session": "Recuperacion impossibla de la session a causa de « {exception} »",
"unknown_group": "Grop « {group} » desconegut",
"unknown_user": "Utilizaire « {user} » desconegut",
"values_mismatch": "Las valors correspondon pas",
@ -39,7 +39,7 @@
"websocket_request_expected": "Una requèsta WebSocket èra esperada",
"cannot_open_file": "Impossible de dobrir lo fichièr {file:s} (rason: {error:s})",
"cannot_write_file": "Escritura impossibla del fichièr {file:s} (rason: {error:s})",
"unknown_error_reading_file": "Error desconeguda en ensajar de legir lo fichièr {file:s}",
"unknown_error_reading_file": "Error desconeguda en ensajar de legir lo fichièr {file:s} (rason: {error:s})",
"error_writing_file": "Error en escriure lo fichièr {file:s}: {error:s}",
"error_removing": "Error en suprimir {path:s}: {error:s}",
"error_changing_file_permissions": "Error en modificar las permissions per {path:s}: {error:s}",
@ -48,8 +48,12 @@
"download_timeout": "{url:s} a trigat per respondre, avèm quitat desperar.",
"download_unknown_error": "Error en telecargar de donadas de {url:s}: {error:s}",
"download_bad_status_code": "{url:s} tòrna lo còdi destat {code:s}",
"command_unknown": "Comanda {command:s} desconeguda?",
"command_unknown": "Comanda « {command:s} » desconeguda?",
"corrupted_json": "Fichièr Json corromput legit de {ressource:s} (rason: {error:s})",
"corrupted_yaml": "Fichièr YAML corromput legit de {ressource:s} (rason: {error:s})",
"info": "Info:"
"info": "Info:",
"corrupted_toml": "Fichièr TOML corromput en lectura de {ressource:s} estant (rason: {error:s})",
"warn_the_user_about_waiting_lock": "Una autra comanda YunoHost es en execucion, sèm a esperar quacabe abans daviar aquesta daquí",
"warn_the_user_about_waiting_lock_again": "Encara en espèra…",
"warn_the_user_that_lock_is_acquired": "lautra comanda ven dacabar, lançament daquesta comanda"
}

View file

@ -96,7 +96,7 @@ class CommentParameter(_ExtraParameter):
def validate(klass, value, arg_name):
# Deprecated boolean or empty string
if isinstance(value, bool) or (isinstance(value, str) and not value):
logger.warning("expecting a string for extra parameter '%s' of "
logger.warning("expecting a non-empty string for extra parameter '%s' of "
"argument '%s'", klass.name, arg_name)
value = arg_name
elif not isinstance(value, str):
@ -131,7 +131,7 @@ class AskParameter(_ExtraParameter):
def validate(klass, value, arg_name):
# Deprecated boolean or empty string
if isinstance(value, bool) or (isinstance(value, str) and not value):
logger.warning("expecting a string for extra parameter '%s' of "
logger.warning("expecting a non-empty string for extra parameter '%s' of "
"argument '%s'", klass.name, arg_name)
value = arg_name
elif not isinstance(value, str):
@ -199,7 +199,7 @@ class PatternParameter(_ExtraParameter):
def validate(value, arg_name):
# Deprecated string type
if isinstance(value, str):
logger.warning("expecting a list for extra parameter 'pattern' of "
logger.warning("expecting a list as extra parameter 'pattern' of "
"argument '%s'", arg_name)
value = [value, 'pattern_not_match']
elif not isinstance(value, list) or len(value) != 2:

View file

@ -305,7 +305,7 @@ class MoulinetteSignals(object):
return authenticator
return self._authenticate(authenticator)
def prompt(self, message, is_password=False, confirm=False):
def prompt(self, message, is_password=False, confirm=False, color='blue'):
"""Prompt for a value
Prompt the interface for a parameter value which is a password
@ -318,12 +318,13 @@ class MoulinetteSignals(object):
- message -- The message to display
- is_password -- True if the parameter is a password
- confirm -- True if the value must be confirmed
- color -- Color to use for the prompt ...
Returns:
The collected value
"""
return self._prompt(message, is_password, confirm)
return self._prompt(message, is_password, confirm, color=color)
def display(self, message, style='info'):
"""Display a message

View file

@ -12,9 +12,10 @@ class JSONExtendedEncoder(JSONEncoder):
"""Extended JSON encoder
Extend default JSON encoder to recognize more types and classes. It
will never raise if the object can't be encoded and return its repr
Extend default JSON encoder to recognize more types and classes. It will
never raise an exception if the object can't be encoded and return its repr
instead.
The following objects and types are supported:
- set: converted into list

View file

@ -10,7 +10,7 @@ def search(pattern, text, count=0, flags=0):
"""Search for pattern in a text
Scan through text looking for all locations where the regular
expresion pattern matches, and return them as a list of strings.
expression pattern matches, and return them as a list of strings.
The optional argument count is the maximum number of pattern
occurences to return; count must be an integer. If omitted or zero,

87
test/test_actionsmap.py Normal file
View file

@ -0,0 +1,87 @@
import pytest
from moulinette.actionsmap import (
CommentParameter,
AskParameter,
PatternParameter,
RequiredParameter,
ActionsMap
)
from moulinette.interfaces import BaseActionsMapParser
from moulinette.core import MoulinetteError
@pytest.fixture
def iface():
return 'iface'
def test_comment_parameter_bad_bool_value(iface, caplog):
comment = CommentParameter(iface)
assert comment.validate(True, 'a') == 'a'
assert any('expecting a non-empty string' in message for message in caplog.messages)
def test_comment_parameter_bad_empty_string(iface, caplog):
comment = CommentParameter(iface)
assert comment.validate('', 'a') == 'a'
assert any('expecting a non-empty string' in message for message in caplog.messages)
def test_comment_parameter_bad_type(iface):
comment = CommentParameter(iface)
with pytest.raises(TypeError):
comment.validate({}, 'b')
def test_ask_parameter_bad_bool_value(iface, caplog):
ask = AskParameter(iface)
assert ask.validate(True, 'a') == 'a'
assert any('expecting a non-empty string' in message for message in caplog.messages)
def test_ask_parameter_bad_empty_string(iface, caplog):
ask = AskParameter(iface)
assert ask.validate('', 'a') == 'a'
assert any('expecting a non-empty string' in message for message in caplog.messages)
def test_ask_parameter_bad_type(iface):
ask = AskParameter(iface)
with pytest.raises(TypeError):
ask.validate({}, 'b')
def test_pattern_parameter_bad_str_value(iface, caplog):
pattern = PatternParameter(iface)
assert pattern.validate('', 'a') == ['', 'pattern_not_match']
assert any('expecting a list' in message for message in caplog.messages)
@pytest.mark.parametrize('iface', [
[],
['pattern_alone'],
['pattern', 'message', 'extra stuff']
])
def test_pattern_parameter_bad_list_len(iface):
pattern = PatternParameter(iface)
with pytest.raises(TypeError):
pattern.validate(iface, 'a')
def test_required_paremeter_missing_value(iface):
required = RequiredParameter(iface)
with pytest.raises(MoulinetteError) as exception:
required(True, 'a', '')
assert 'is required' in str(exception)
def test_actions_map_unknown_authenticator(monkeypatch, tmp_path):
monkeypatch.setenv('MOULINETTE_DATA_DIR', str(tmp_path))
actionsmap_dir = actionsmap_dir = tmp_path / 'actionsmap'
actionsmap_dir.mkdir()
amap = ActionsMap(BaseActionsMapParser)
with pytest.raises(ValueError) as exception:
amap.get_authenticator(profile='unknown')
assert 'Unknown authenticator' in str(exception)

14
test/test_serialize.py Normal file
View file

@ -0,0 +1,14 @@
from datetime import datetime as dt
from moulinette.utils.serialize import JSONExtendedEncoder
def test_json_extended_encoder(caplog):
encoder = JSONExtendedEncoder()
assert encoder.default(set([1, 2, 3])) == [1, 2, 3]
assert encoder.default(dt(1917, 3, 8)) == '1917-03-08T00:00:00+00:00'
assert encoder.default(None) == 'None'
for message in caplog.messages:
assert 'cannot properly encode in JSON' in message

21
test/test_text.py Normal file
View file

@ -0,0 +1,21 @@
from moulinette.utils.text import search, searchf, prependlines, random_ascii
def test_search():
assert search('a', 'a a a') == ['a', 'a', 'a']
assert search('a', 'a a a', count=2) == ['a', 'a']
assert not search('a', 'c c d')
def test_searchf(test_file):
assert searchf('bar', str(test_file)) == ['bar']
assert not searchf('baz', str(test_file))
def test_prependlines():
assert prependlines('abc\nedf\nghi', 'XXX') == 'XXXabc\nXXXedf\nXXXghi'
assert prependlines('', 'XXX') == 'XXX'
def test_random_ascii():
assert isinstance(random_ascii(length=2), unicode)