mirror of
https://github.com/YunoHost/moulinette.git
synced 2024-09-03 20:06:31 +02:00
Merge branch 'stretch-unstable' into stdinfo
This commit is contained in:
commit
efa9c9bd69
19 changed files with 366 additions and 55 deletions
|
@ -11,7 +11,7 @@ prototype interfaces for your application.
|
|||
Issues
|
||||
------
|
||||
|
||||
- [Please report issues on YunoHost bugtracker](https://dev.yunohost.org/projects/yunohost/issues) (no registration needed).
|
||||
- [Please report issues on YunoHost bugtracker](https://github.com/YunoHost/issues).
|
||||
|
||||
Overview
|
||||
--------
|
||||
|
|
92
debian/changelog
vendored
92
debian/changelog
vendored
|
@ -1,3 +1,95 @@
|
|||
moulinette (3.1.0) stable; urgency=low
|
||||
|
||||
* Fix datetime output formats (#163)
|
||||
* Add the missing Info: prefix for info messages
|
||||
* Rework a bit the way we handle async outputs (#166)
|
||||
* Don't crash the moulinette if we fail to format a string (#168)
|
||||
|
||||
Thanks to all contributors : ljf, Bram, Aleks !
|
||||
|
||||
-- Alexandre Aubin <alex.aubin@mailoo.org> Wed, 15 Aug 2018 21:44:00 +0000
|
||||
|
||||
moulinette (3.0.0) stable; urgency=low
|
||||
|
||||
Merging with Jessie's branches
|
||||
Releasing as stable
|
||||
|
||||
-- Alexandre Aubin <alex.aubin@mailoo.org> Sun, 17 Jun 2018 03:46:00 +0000
|
||||
|
||||
moulinette (3.0.0~beta1.1) testing; urgency=low
|
||||
|
||||
Merging with Jessie's branches
|
||||
|
||||
-- Alexandre Aubin <alex.aubin@mailoo.org> Mon, 28 May 2018 02:55:00 +0000
|
||||
|
||||
moulinette (3.0.0~beta1) testing; urgency=low
|
||||
|
||||
Beta release for Stretch
|
||||
|
||||
-- Alexandre Aubin <alex.aubin@mailoo.org> Thu, 03 May 2018 03:04:45 +0000
|
||||
|
||||
moulinette (2.7.14) stable; urgency=low
|
||||
|
||||
* Improve French, Occitan, Portuguese, Arabic translations
|
||||
* Release as stable
|
||||
|
||||
-- Alexandre Aubin <alex.aubin@mailoo.org> Sun, 17 Jun 2018 01:42:12 +0000
|
||||
|
||||
moulinette (2.7.13) testing; urgency=low
|
||||
|
||||
* [i18n] Improve translations for Portugueuse, Occitan
|
||||
* [enh] Add read_yaml util (#161)
|
||||
|
||||
Contributors : Bram, by0ne, Quent-in
|
||||
|
||||
-- Alexandre Aubin <alex.aubin@mailoo.org> Mon, 28 May 2018 02:55:00 +0000
|
||||
|
||||
moulinette (2.7.12) stable; urgency=low
|
||||
|
||||
* Bumping version number for stable release
|
||||
|
||||
-- Alexandre Aubin <alex.aubin@mailoo.org> Sun, 06 May 2018 16:57:18 +0000
|
||||
|
||||
moulinette (2.7.11) testing; urgency=low
|
||||
|
||||
* [i18n] Improve translations for Arabic, Dutch, French, Occitan, Spanish
|
||||
* [enh] Improve performances by lazy-loading some imports
|
||||
* [enh] Log time needed to load a python module for an action
|
||||
* [fix] Avoid cases where get_cookie returns None
|
||||
* [mod] Improve exception logging in ldap stuff
|
||||
|
||||
Thanks to all contributors (pitchum, Bram, ButteflyOfFire, J. Keerl, Matthieu, Jibec, David B, Quenti, bjarkan) <3 !
|
||||
|
||||
-- Alexandre Aubin <alex.aubin@mailoo.org> Tue, 01 May 2018 23:33:59 +0000
|
||||
|
||||
moulinette (2.7.7) stable; urgency=low
|
||||
|
||||
(Bumping version for stable release)
|
||||
|
||||
-- Alexandre Aubin <alex.aubin@mailoo.org> Thu, 18 Jan 2018 17:41:43 -0500
|
||||
|
||||
moulinette (2.7.6) testing; urgency=low
|
||||
|
||||
* [fix] Indicate where those damn logs files are
|
||||
* [i18n] Improve Spanish and French translations
|
||||
|
||||
Thanks to all contributors (Bram, Jibec, David B.) ! <3
|
||||
|
||||
-- Alexandre Aubin <alex.aubin@mailoo.org> Tue, 16 Jan 2018 17:12:19 -0500
|
||||
|
||||
moulinette (2.7.5) stable; urgency=low
|
||||
|
||||
(Bumping version for stable release)
|
||||
|
||||
-- Alexandre Aubin <alex.aubin@mailoo.org> Sat, 02 Dec 2017 12:26:43 -0500
|
||||
|
||||
moulinette (2.7.3) testing; urgency=low
|
||||
|
||||
* Optional expected status code for download_text/json (#153)
|
||||
* Allow to give lock to multiple processes (#154)
|
||||
|
||||
-- Alexandre Aubin <alex.aubin@mailoo.org> Thu, 12 Oct 2017 16:09:27 -0400
|
||||
|
||||
moulinette (2.7.2) stable; urgency=low
|
||||
|
||||
* Revert hack for buildchain, found a proper solution
|
||||
|
|
|
@ -3,6 +3,7 @@ File system operation utils
|
|||
|
||||
.. autofunction:: moulinette.utils.filesystem.read_file
|
||||
.. autofunction:: moulinette.utils.filesystem.read_json
|
||||
.. autofunction:: moulinette.utils.filesystem.read_yaml
|
||||
.. autofunction:: moulinette.utils.filesystem.write_to_file
|
||||
.. autofunction:: moulinette.utils.filesystem.append_to_file
|
||||
.. autofunction:: moulinette.utils.filesystem.write_to_json
|
||||
|
|
54
locales/ar.json
Normal file
54
locales/ar.json
Normal file
|
@ -0,0 +1,54 @@
|
|||
{
|
||||
"argument_required": "المُعامِل '{argument}' مطلوب",
|
||||
"authentication_profile_required": "المصادقة مع الملف الشخصي '{profile}' مطلوبة",
|
||||
"authentication_required": "المصادقة مطلوبة",
|
||||
"authentication_required_long": "المصادقة مطلوبة قبل القيام بهذا الإجراء",
|
||||
"colon": "{}: ",
|
||||
"confirm": "تأكيد {prompt}",
|
||||
"deprecated_command": "'{prog} {command}' تم التخلي عنه و سوف تتم إزالته مستقبلا",
|
||||
"deprecated_command_alias": "'{prog} {old}' تم التخلي عنه و سوف يتم إزالته مستقبلا، إستخدم '{prog} {new}' بدلا من ذلك",
|
||||
"error": "خطأ :",
|
||||
"error_see_log": "طرأ هناك خطأ. يرجى الإطلاع على السجلات للمزيد مِن التفاصيل على المسار /var/log/yunohost/.",
|
||||
"file_exists": "إنّ الملف موجود من قبل : '{path}'",
|
||||
"file_not_exist": "الملف غير موجود : '{path}'",
|
||||
"folder_exists": "إنّ المجلد موجود من قبل : '{path}'",
|
||||
"folder_not_exist": "المجلد غير موجود",
|
||||
"instance_already_running": "هناك نسخة خادوم تشتغل مِن قبل",
|
||||
"invalid_argument": "المُعامِل غير صالح '{argument}': {error}",
|
||||
"invalid_password": "كلمة السر خاطئة",
|
||||
"invalid_usage": "إستعمال غير صالح، إستخدم --help لعرض المساعدة",
|
||||
"ldap_attribute_already_exists": "الخاصية '{attribute}' موجودة مسبقا و تحمل القيمة '{value}'",
|
||||
"ldap_operation_error": "طرأ هناك خطأ أثناء عملية في LDAP",
|
||||
"ldap_server_down": "لا يمكن الإتصال بخادم LDAP",
|
||||
"logged_in": "مُتّصل",
|
||||
"logged_out": "تم تسجيل خروجك",
|
||||
"not_logged_in": "لم تقم بعدُ بتسجيل دخولك",
|
||||
"operation_interrupted": "تم توقيف العملية",
|
||||
"password": "كلمة السر",
|
||||
"pattern_not_match": "لا يتطابق مع النموذج",
|
||||
"permission_denied": "رُفض التصريح",
|
||||
"root_required": "يتوجب عليك أن تكون مدير الجذر root للقيام بهذا الإجراء",
|
||||
"server_already_running": "هناك خادم يشتغل على ذاك المنفذ",
|
||||
"success": "تم بنجاح !",
|
||||
"unable_authenticate": "تعذرت المصادقة",
|
||||
"unable_retrieve_session": "تعذرت مواصلة الجلسة",
|
||||
"unknown_group": "الفريق '{group}' مجهول",
|
||||
"unknown_user": "المستخدم '{user}' مجهول",
|
||||
"values_mismatch": "القيمتين غير متطابقتين",
|
||||
"warning": "تحذير :",
|
||||
"websocket_request_expected": "كان ينتظر طلبًا عبر الويب سوكت WebSocket",
|
||||
"cannot_open_file": "ليس بالإمكان فتح الملف {file:s} (السبب : {error:s})",
|
||||
"cannot_write_file": "لا يمكن الكتابة في الملف {file:s} (السبب : {error:s})",
|
||||
"unknown_error_reading_file": "طرأ هناك خطأ ما أثناء عملية قراءة الملف {file:s}",
|
||||
"corrupted_json": "قراءة json مُشوّهة مِن {ressource:s} (السبب : {error:s})",
|
||||
"error_writing_file": "طرأ هناك خطأ أثناء الكتابة في الملف {file:s}: {error:s}",
|
||||
"error_removing": "خطأ أثناء عملية حذف {path:s}: {error:s}",
|
||||
"error_changing_file_permissions": "خطأ أثناء عملية تعديل التصريحات لـ {path:s}: {error:s}",
|
||||
"invalid_url": "خطأ في عنوان الرابط {url:s} (هل هذا الموقع موجود حقًا ؟)",
|
||||
"download_ssl_error": "خطأ في الإتصال الآمن عبر الـ SSL أثناء محاولة الإتصال بـ {url:s}",
|
||||
"download_timeout": "{url:s} استغرق مدة طويلة جدا للإستجابة، فتوقّف.",
|
||||
"download_unknown_error": "خطأ أثناء عملية تنزيل البيانات مِن {url:s} : {error:s}",
|
||||
"download_bad_status_code": "{url:s} أعاد رمز الحالة {code:s}",
|
||||
"command_unknown": "الأمر '{command:s}' غير معروف ؟",
|
||||
"corrupted_yaml": "قراءة مُشوّهة لنسق yaml مِن {ressource:s} (السبب : {error:s})"
|
||||
}
|
|
@ -8,11 +8,12 @@
|
|||
"deprecated_command": "'{prog} {command}' is deprecated and will be removed in the future",
|
||||
"deprecated_command_alias": "'{prog} {old}' is deprecated and will be removed in the future, use '{prog} {new}' instead",
|
||||
"error": "Error:",
|
||||
"error_see_log": "An error occurred. Please see the log for details.",
|
||||
"error_see_log": "An error occurred. Please see the logs for details, they are located in /var/log/yunohost/.",
|
||||
"file_exists": "File already exists: '{path}'",
|
||||
"file_not_exist": "File does not exist: '{path}'",
|
||||
"folder_exists": "Folder already exists: '{path}'",
|
||||
"folder_not_exist": "Folder does not exist",
|
||||
"info": "Info:",
|
||||
"instance_already_running": "An instance is already running",
|
||||
"invalid_argument": "Invalid argument '{argument}': {error}",
|
||||
"invalid_password": "Invalid password",
|
||||
|
@ -42,6 +43,7 @@
|
|||
"cannot_write_file": "Could not write file {file:s} (reason: {error:s})",
|
||||
"unknown_error_reading_file": "Unknown error while trying to read file {file:s}",
|
||||
"corrupted_json": "Corrupted json read from {ressource:s} (reason: {error:s})",
|
||||
"corrupted_yaml": "Corrupted yaml read from {ressource:s} (reason: {error:s})",
|
||||
"error_writing_file": "Error when writing file {file:s}: {error:s}",
|
||||
"error_removing": "Error when removing {path:s}: {error:s}",
|
||||
"error_changing_file_permissions": "Error when changing permissions for {path:s}: {error:s}",
|
||||
|
|
|
@ -8,12 +8,12 @@
|
|||
"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.",
|
||||
"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": "El programa ya se está ejecutando",
|
||||
"instance_already_running": "Una instancia ya se está ejecutando",
|
||||
"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",
|
||||
|
@ -36,5 +36,18 @@
|
|||
"unknown_user": "Usuario '{user}' desconocido",
|
||||
"values_mismatch": "Los valores no coinciden",
|
||||
"warning": "Advertencia:",
|
||||
"websocket_request_expected": "Una petición de WebSocket prevista"
|
||||
"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}",
|
||||
"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?)",
|
||||
"download_ssl_error": "Error SSL al conectar con {url:s}",
|
||||
"download_timeout": "{url:s} tardó demasiado en responder, me rindo.",
|
||||
"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 ?"
|
||||
}
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
{
|
||||
"argument_required": "L'argument « {argument} » est requis",
|
||||
"authentication_profile_required": "Authentification au profil « {profile} » requise",
|
||||
"authentication_profile_required": "L’authentification au profil « {profile} » requise",
|
||||
"authentication_required": "Authentification requise",
|
||||
"authentication_required_long": "L'authentification est requise pour exécuter cette action",
|
||||
"authentication_required_long": "L’authentification est requise pour exécuter cette action",
|
||||
"colon": "{} : ",
|
||||
"confirm": "Confirmez : {prompt}",
|
||||
"deprecated_command": "« {prog} {command} » est déprécié et sera bientôt supprimé",
|
||||
"deprecated_command_alias": "« {prog} {old} » est déprécié et sera bientôt supprimé, utilisez « {prog} {new} » à la place",
|
||||
"error": "Erreur :",
|
||||
"error_see_log": "Une erreur est survenue. Veuillez consulter les journaux pour plus de détails.",
|
||||
"error_see_log": "Une erreur est survenue. Veuillez consulter les journaux pour plus de détails, ils sont situés en /var/log/yunohost/.",
|
||||
"file_exists": "Le fichier existe déjà : « {path} »",
|
||||
"file_not_exist": "Le fichier « {path} » n'existe pas",
|
||||
"folder_exists": "Le dossier existe déjà : « {path} »",
|
||||
|
@ -27,7 +27,7 @@
|
|||
"password": "Mot de passe",
|
||||
"pattern_not_match": "Ne correspond pas au motif",
|
||||
"permission_denied": "Permission refusée",
|
||||
"root_required": "Vous devez avoir les droits super-utilisateur pour exécuter cette action",
|
||||
"root_required": "Vous devez être super-utilisateur pour exécuter cette action",
|
||||
"server_already_running": "Un serveur est déjà en cours d'exécution sur ce port",
|
||||
"success": "Succès !",
|
||||
"unable_authenticate": "Impossible de vous authentifier",
|
||||
|
@ -49,5 +49,6 @@
|
|||
"download_timeout": "{url:s} a pris trop de temps pour répondre, abandon.",
|
||||
"download_unknown_error": "Erreur lors du téléchargement des données à partir de {url:s}:{error:s}",
|
||||
"download_bad_status_code": "{url:s} code de statut renvoyé {code:s}",
|
||||
"command_unknown": "Commande {command:s} inconnue ?"
|
||||
"command_unknown": "Commande '{command:s}' inconnue ?",
|
||||
"corrupted_yaml": "YAML corrompu lu {ressource:s} depuis (cause : {error:s})"
|
||||
}
|
||||
|
|
|
@ -1,21 +1,21 @@
|
|||
{
|
||||
"argument_required": "Argument {argument} is vereist",
|
||||
"authentication_profile_required": "Authenticatie tot profiel '{profile}' is vereist",
|
||||
"authentication_required": "Authenticatie vereist",
|
||||
"authentication_required_long": "Authenticatie is vereist om deze actie uit te voeren",
|
||||
"authentication_required": "Aanmelding vereist",
|
||||
"authentication_required_long": "Aanmelding is vereist om deze actie uit te voeren",
|
||||
"colon": "{}: ",
|
||||
"confirm": "Bevestig {prompt}",
|
||||
"error": "Fout:",
|
||||
"error_see_log": "Er is een fout opgetreden, zie logboek voor meer informatie.",
|
||||
"file_exists": "Kan '{path}' niet aanmaken: Bestand bestaat al",
|
||||
"error_see_log": "Er is een fout opgetreden, zie logboek voor meer informatie. Je kan deze vinden in /var/log/yunohost/.",
|
||||
"file_exists": "Kan '{path}' niet aanmaken: bestand bestaat al",
|
||||
"file_not_exist": "Bestand bestaat niet: '{path}'",
|
||||
"folder_exists": "kan map ‘{path}’ niet aanmaken: Bestand bestaat al",
|
||||
"folder_exists": "Deze map bestaat al: '{path}'",
|
||||
"folder_not_exist": "Map bestaat niet",
|
||||
"instance_already_running": "Er is al een instantie aan het draaien",
|
||||
"invalid_argument": "Onjuist argument '{argument}': {error}",
|
||||
"instance_already_running": "Er is al een instantie actief",
|
||||
"invalid_argument": "Ongeldig argument '{argument}': {error}",
|
||||
"invalid_password": "Ongeldig wachtwoord",
|
||||
"invalid_usage": "Geef 'pass --help' in voor meer informatie",
|
||||
"ldap_attribute_already_exists": "Attribuut bestaat al: '{attribute}={value}'",
|
||||
"invalid_usage": "Ongeldig gebruik, doe --help om de hulptekst te lezen",
|
||||
"ldap_attribute_already_exists": "Attribuut '{attribute}' bestaat al met waarde '{value}'",
|
||||
"ldap_operation_error": "Er is een fout opgetreden bij het uitvoeren van LDAP operatie",
|
||||
"ldap_server_down": "Kan LDAP server niet bereiken",
|
||||
"logged_in": "Ingelogd",
|
||||
|
@ -26,7 +26,7 @@
|
|||
"pattern_not_match": "Past niet in het patroon",
|
||||
"permission_denied": "Toegang geweigerd",
|
||||
"root_required": "Je moet root zijn om deze actie uit te voeren",
|
||||
"server_already_running": "Er is al een server aktief op die poort",
|
||||
"server_already_running": "Er is al een server actief op die poort",
|
||||
"success": "Succes!",
|
||||
"unable_authenticate": "Aanmelding niet mogelijk",
|
||||
"unable_retrieve_session": "Kan de sessie niet ophalen",
|
||||
|
@ -34,7 +34,20 @@
|
|||
"warning": "Waarschuwing:",
|
||||
"websocket_request_expected": "Verwachtte een WebSocket request",
|
||||
"deprecated_command": "'{prog} {command}' is verouderd en wordt binnenkort verwijderd",
|
||||
"deprecated_command_alias": "'{prog} {old}' is verouderd en wordt binnenkort verwijderd, gebruik '{prog} {new}' in plaats daarvan",
|
||||
"deprecated_command_alias": "'{prog} {old}' is verouderd en wordt binnenkort verwijderd, gebruik in de plaats '{prog} {new}'",
|
||||
"unknown_group": "Groep '{group}' is onbekend",
|
||||
"unknown_user": "Gebruiker '{user}' is onbekend"
|
||||
"unknown_user": "Gebruiker '{user}' is onbekend",
|
||||
"cannot_open_file": "Niet mogelijk om bestand {file:s} te openen (reden: {error:s})",
|
||||
"cannot_write_file": "Niet gelukt om bestand {file:s} te schrijven (reden: {error:s})",
|
||||
"unknown_error_reading_file": "Ongekende fout tijdens het lezen van bestand {file:s}",
|
||||
"corrupted_json": "Corrupte json gelezen van {ressource:s} (reden: {error:s})",
|
||||
"error_writing_file": "Fout tijdens het schrijven van bestand {file:s}: {error:s}",
|
||||
"error_removing": "Fout tijdens het verwijderen van {path:s}: {error:s}",
|
||||
"error_changing_file_permissions": "Fout tijdens het veranderen van machtiging voor {path:s}: {error:s}",
|
||||
"invalid_url": "Ongeldige URL {url:s} (bestaat deze website?)",
|
||||
"download_ssl_error": "SSL fout gedurende verbinding met {url:s}",
|
||||
"download_timeout": "{url:s} neemt te veel tijd om te antwoorden, we geven het op.",
|
||||
"download_unknown_error": "Fout tijdens het downloaden van data van {url:s}: {error:s}",
|
||||
"download_bad_status_code": "{url:s} stuurt status code {code:s}",
|
||||
"command_unknown": "Opdracht '{command:s}' ongekend ?"
|
||||
}
|
||||
|
|
54
locales/oc.json
Normal file
54
locales/oc.json
Normal file
|
@ -0,0 +1,54 @@
|
|||
{
|
||||
"argument_required": "L’argument {argument} es requesit",
|
||||
"authentication_profile_required": "L’identificacion del perfil {profile} es requesida",
|
||||
"authentication_required": "Autentificacion requesida",
|
||||
"authentication_required_long": "Una autentificacion es requesida per acomplir aquesta accion",
|
||||
"logged_in": "Connectat",
|
||||
"logged_out": "Desconnectat",
|
||||
"password": "Senhal",
|
||||
"colon": "{}: ",
|
||||
"confirm": "Confirmatz : {prompt}",
|
||||
"deprecated_command": "« {prog} {command} » es despreciat e serà lèu suprimit",
|
||||
"deprecated_command_alias": "« {prog} {old} » es despreciat e serà lèu suprimit, utilizatz « {prog} {new} » allòc",
|
||||
"error": "Error :",
|
||||
"error_see_log": "Una error s’es producha. Mercés de consultar los jornals per mai detalhs, son plaçats dins /var/log/yunohost/.",
|
||||
"file_exists": "Lo fichièr existís ja : « {path} »",
|
||||
"file_not_exist": "Lo fichièr « {path} » existís pas",
|
||||
"folder_exists": "Lo repertòri existís ja : « {path} »",
|
||||
"folder_not_exist": "Lo repertòri existís pas",
|
||||
"instance_already_running": "Una instància es ja en execucion",
|
||||
"invalid_argument": "Argument « {argument} » incorrècte : {error}",
|
||||
"invalid_password": "Senhal incorrècte",
|
||||
"ldap_server_down": "Impossible d’aténher lo servidor LDAP",
|
||||
"not_logged_in": "Cap de session començada",
|
||||
"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",
|
||||
"unknown_group": "Grop « {group} » desconegut",
|
||||
"unknown_user": "Utilizaire « {user} » desconegut",
|
||||
"values_mismatch": "Las valors correspondon pas",
|
||||
"warning": "Atencion :",
|
||||
"invalid_usage": "Usatge invalid, utilizatz --help per accedir a l’ajuda",
|
||||
"ldap_attribute_already_exists": "L’atribut « {attribute} » existís ja amb la valor : {value}",
|
||||
"ldap_operation_error": "Una error s’es producha pendent l’operacion LDAP",
|
||||
"operation_interrupted": "Operacion interrompuda",
|
||||
"server_already_running": "Un servidor es ja en execucion sus aqueste pòrt",
|
||||
"success": "Capitada !",
|
||||
"unable_authenticate": "Impossible de vos autentificar",
|
||||
"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}",
|
||||
"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}",
|
||||
"invalid_url": "Url invalida {url:s} (existís aqueste site ?)",
|
||||
"download_ssl_error": "Error SSL en se connectant a {url:s}",
|
||||
"download_timeout": "{url:s} a trigat per respondre, avèm quitat d’esperar.",
|
||||
"download_unknown_error": "Error en telecargar de donadas de {url:s} : {error:s}",
|
||||
"download_bad_status_code": "{url:s} tòrna lo còdi d’estat {code:s}",
|
||||
"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})"
|
||||
}
|
|
@ -34,7 +34,21 @@
|
|||
"websocket_request_expected": "Esperado um pedido a WebSocket",
|
||||
"deprecated_command": "'{prog} {command}' está obsoleto e será removido no futuro",
|
||||
"deprecated_command_alias": "'{prog} {old}' está obsoleto e será removido no futuro, em vez disso, usa '{prog} {new}'",
|
||||
"error_see_log": "Um erro ocorreu. Por favor, veja mais detalhes no log.",
|
||||
"error_see_log": "Ocorreu um erro . Por favor, veja os logs para maiores detalhes, eles estão localizados em /var/log/yunohost/.",
|
||||
"unknown_group": "Grupo '{group}' desconhecido",
|
||||
"unknown_user": "Nome de utilizador '{user}' desconhecido"
|
||||
"unknown_user": "Nome de utilizador '{user}' desconhecido",
|
||||
"cannot_open_file": "Não foi possível abrir o arquivo {file:s} (reason: {error:s})",
|
||||
"cannot_write_file": "Não foi possível abrir o arquivo {file:s} (reason: {error:s})",
|
||||
"unknown_error_reading_file": "Erro desconhecido ao tentar ler o arquivo {file:s}",
|
||||
"error_writing_file": "Erro ao gravar arquivo {file:s}: {error:s}",
|
||||
"error_removing": "Erro ao remover {path:s}: {error:s}",
|
||||
"error_changing_file_permissions": "Erro ao alterar as permissões para {path:s}: {error:s}",
|
||||
"invalid_url": "URL inválida {url:s} (does this site exists ?)",
|
||||
"download_ssl_error": "Erro de SSL ao conectar-se a {url:s}",
|
||||
"download_timeout": "{url:s} demorou muito para responder, desistiu.",
|
||||
"download_unknown_error": "Erro quando baixando os dados de {url:s} : {error:s}",
|
||||
"download_bad_status_code": "{url:s} retornou o código de status {code:s}",
|
||||
"command_unknown": "Comando '{command:s}' desconhecido ?",
|
||||
"corrupted_json": "Json corrompido lido do {ressource:s} (motivo: {error:s})",
|
||||
"corrupted_yaml": "Yaml corrompido lido do {ressource:s} (motivo: {error:s})"
|
||||
}
|
||||
|
|
|
@ -391,7 +391,7 @@ class ActionsMap(object):
|
|||
with open(actionsmap_pkl) as f:
|
||||
actionsmaps[n] = pickle.load(f)
|
||||
# TODO: Switch to python3 and catch proper exception
|
||||
except IOError:
|
||||
except (IOError, EOFError):
|
||||
self.use_cache = False
|
||||
actionsmaps = self.generate_cache(namespaces)
|
||||
elif use_cache: # cached file doesn't exists
|
||||
|
@ -469,10 +469,13 @@ class ActionsMap(object):
|
|||
|
||||
# Lock the moulinette for the namespace
|
||||
with MoulinetteLock(namespace, timeout):
|
||||
start = time()
|
||||
try:
|
||||
mod = __import__('%s.%s' % (namespace, category),
|
||||
globals=globals(), level=0,
|
||||
fromlist=[func_name])
|
||||
logger.debug('loading python module %s took %.3fs',
|
||||
'%s.%s' % (namespace, category), time() - start)
|
||||
func = getattr(mod, func_name)
|
||||
except (AttributeError, ImportError):
|
||||
logger.exception("unable to load function %s.%s",
|
||||
|
@ -495,7 +498,7 @@ class ActionsMap(object):
|
|||
return func(**arguments)
|
||||
finally:
|
||||
stop = time()
|
||||
logger.debug('action [%s] ended after %.3fs',
|
||||
logger.debug('action [%s] executed in %.3fs',
|
||||
log_id, stop - start)
|
||||
|
||||
@staticmethod
|
||||
|
|
|
@ -62,7 +62,8 @@ class Authenticator(BaseAuthenticator):
|
|||
try:
|
||||
# Retrieve identity
|
||||
who = self.con.whoami_s()
|
||||
except:
|
||||
except Exception as e:
|
||||
logger.warning("Error during ldap authentication process: %s", e)
|
||||
return False
|
||||
else:
|
||||
if who[3:] == self.userdn:
|
||||
|
@ -131,9 +132,9 @@ class Authenticator(BaseAuthenticator):
|
|||
|
||||
try:
|
||||
result = self.con.search_s(base, ldap.SCOPE_SUBTREE, filter, attrs)
|
||||
except:
|
||||
except Exception as e:
|
||||
logger.exception("error during LDAP search operation with: base='%s', "
|
||||
"filter='%s', attrs=%s", base, filter, attrs)
|
||||
"filter='%s', attrs=%s and exception %s", base, filter, attrs, e)
|
||||
raise MoulinetteError(169, m18n.g('ldap_operation_error'))
|
||||
|
||||
result_list = []
|
||||
|
@ -162,9 +163,9 @@ class Authenticator(BaseAuthenticator):
|
|||
|
||||
try:
|
||||
self.con.add_s(dn, ldif)
|
||||
except:
|
||||
except Exception as e:
|
||||
logger.exception("error during LDAP add operation with: rdn='%s', "
|
||||
"attr_dict=%s", rdn, attr_dict)
|
||||
"attr_dict=%s and exception %s", rdn, attr_dict, e)
|
||||
raise MoulinetteError(169, m18n.g('ldap_operation_error'))
|
||||
else:
|
||||
return True
|
||||
|
@ -183,8 +184,8 @@ class Authenticator(BaseAuthenticator):
|
|||
dn = rdn + ',' + self.basedn
|
||||
try:
|
||||
self.con.delete_s(dn)
|
||||
except:
|
||||
logger.exception("error during LDAP delete operation with: rdn='%s'", rdn)
|
||||
except Exception as e:
|
||||
logger.exception("error during LDAP delete operation with: rdn='%s' and exception %s", rdn, e)
|
||||
raise MoulinetteError(169, m18n.g('ldap_operation_error'))
|
||||
else:
|
||||
return True
|
||||
|
@ -212,9 +213,10 @@ class Authenticator(BaseAuthenticator):
|
|||
dn = new_rdn + ',' + self.basedn
|
||||
|
||||
self.con.modify_ext_s(dn, ldif)
|
||||
except:
|
||||
except Exception as e:
|
||||
logger.exception("error during LDAP update operation with: rdn='%s', "
|
||||
"attr_dict=%s, new_rdn=%s", rdn, attr_dict, new_rdn)
|
||||
"attr_dict=%s, new_rdn=%s and exception: %s", rdn, attr_dict,
|
||||
new_rdn, e)
|
||||
raise MoulinetteError(169, m18n.g('ldap_operation_error'))
|
||||
else:
|
||||
return True
|
||||
|
|
|
@ -88,14 +88,23 @@ class Translator(object):
|
|||
- key -- The key to translate
|
||||
|
||||
"""
|
||||
failed_to_format = False
|
||||
if key in self._translations.get(self.locale, {}):
|
||||
return self._translations[self.locale][key].encode('utf-8').format(*args, **kwargs)
|
||||
try:
|
||||
return self._translations[self.locale][key].encode('utf-8').format(*args, **kwargs)
|
||||
except KeyError as e:
|
||||
logger.exception("Failed to format translated string '%s' with error: %s" % (key, e))
|
||||
failed_to_format = True
|
||||
|
||||
if self.default_locale != self.locale and key in self._translations.get(self.default_locale, {}):
|
||||
if failed_to_format or (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 self._translations[self.default_locale][key].encode('utf-8').format(*args, **kwargs)
|
||||
except KeyError as e:
|
||||
logger.exception("Failed to format translatable string '%s' with error: %s" % (key, e))
|
||||
return self._translations[self.locale][key].encode('utf-8')
|
||||
|
||||
logger.exception("unable to retrieve key '%s' for default locale '%s'",
|
||||
key, self.default_locale)
|
||||
|
@ -500,7 +509,7 @@ class MoulinetteLock(object):
|
|||
lock_pids = f.read().strip().split('\n')
|
||||
|
||||
# Make sure to convert those pids to integers
|
||||
lock_pids = [ int(pid) for pid in lock_pids ]
|
||||
lock_pids = [int(pid) for pid in lock_pids if pid.strip() != '']
|
||||
|
||||
return lock_pids
|
||||
|
||||
|
|
|
@ -438,7 +438,7 @@ class _ActionsMapPlugin(object):
|
|||
try:
|
||||
s_secret = self.secrets[s_id]
|
||||
s_hash = request.get_cookie('session.hashes',
|
||||
secret=s_secret)[authenticator.name]
|
||||
secret=s_secret, default={})[authenticator.name]
|
||||
except KeyError:
|
||||
if authenticator.name == 'default':
|
||||
msg = m18n.g('authentication_required')
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import os
|
||||
import yaml
|
||||
import errno
|
||||
import shutil
|
||||
import json
|
||||
|
@ -64,6 +65,28 @@ def read_json(file_path):
|
|||
return loaded_json
|
||||
|
||||
|
||||
def read_yaml(file_path):
|
||||
"""
|
||||
Safely read a yaml file
|
||||
|
||||
Keyword argument:
|
||||
file_path -- Path to the yaml file
|
||||
"""
|
||||
|
||||
# Read file
|
||||
file_content = read_file(file_path)
|
||||
|
||||
# Try to load yaml to check if it's syntaxically correct
|
||||
try:
|
||||
loaded_yaml = yaml.safe_load(file_content)
|
||||
except ValueError as e:
|
||||
raise MoulinetteError(errno.EINVAL,
|
||||
m18n.g('corrupted_yaml',
|
||||
ressource=file_path, error=str(e)))
|
||||
|
||||
return loaded_yaml
|
||||
|
||||
|
||||
def write_to_file(file_path, data, file_mode="w"):
|
||||
"""
|
||||
Write a single string or a list of string to a text file.
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import errno
|
||||
import requests
|
||||
import json
|
||||
|
||||
from moulinette import m18n
|
||||
|
@ -17,6 +16,7 @@ def download_text(url, timeout=30, expected_status_code=200):
|
|||
expected_status_code -- Status code expected from the request. Can be
|
||||
None to ignore the status code.
|
||||
"""
|
||||
import requests # lazy loading this module for performance reasons
|
||||
# Assumptions
|
||||
assert isinstance(url, str)
|
||||
|
||||
|
|
|
@ -95,22 +95,33 @@ def call_async_output(args, callback, **kwargs):
|
|||
if stdinfo:
|
||||
stdinfo_reader, stdinfo_consum = async_file_reading(stdinfo_f, callback[2])
|
||||
|
||||
while not stdout_reader.eof() or not stderr_reader.eof():
|
||||
while not stdout_reader.eof() and not stderr_reader.eof():
|
||||
while not stdout_consum.empty() or not stderr_consum.empty():
|
||||
# alternate between the 2 consumers to avoid desynchronisation
|
||||
# this way is not 100% perfect but should do it
|
||||
stdout_consum.process_next_line()
|
||||
stderr_consum.process_next_line()
|
||||
stdinfo_consum.process_next_line()
|
||||
time.sleep(.1)
|
||||
stderr_reader.join()
|
||||
stderr_consum.join()
|
||||
# clear the queues
|
||||
stdout_consum.process_current_queue()
|
||||
stderr_consum.process_current_queue()
|
||||
stdinfo_consum.process_current_queue()
|
||||
else:
|
||||
while not stdout_reader.eof():
|
||||
stdout_consum.process_current_queue()
|
||||
time.sleep(.1)
|
||||
stdout_reader.join()
|
||||
stdout_consum.join()
|
||||
# clear the queue
|
||||
stdout_consum.process_current_queue()
|
||||
|
||||
if stdinfo:
|
||||
# Remove the stdinfo pipe
|
||||
os.remove(stdinfo)
|
||||
os.rmdir(os.path.dirname(stdinfo))
|
||||
stdinfo_reader.join()
|
||||
stdinfo_consum.join()
|
||||
stdinfo_consum.process_current_queue()
|
||||
|
||||
# on slow hardware, in very edgy situations it is possible that the process
|
||||
# isn't finished just after having closed stdout and stderr, so we wait a
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import logging
|
||||
from json.encoder import JSONEncoder
|
||||
import datetime
|
||||
|
||||
logger = logging.getLogger('moulinette.utils.serialize')
|
||||
|
||||
|
@ -24,6 +25,10 @@ class JSONExtendedEncoder(JSONEncoder):
|
|||
hasattr(o, '__iter__') and hasattr(o, 'next')):
|
||||
return list(o)
|
||||
|
||||
# Display the date in its iso format ISO-8601 Internet Profile (RFC 3339)
|
||||
if isinstance(o, datetime.datetime) or isinstance(o, datetime.date):
|
||||
return o.isoformat()
|
||||
|
||||
# Return the repr for object that json can't encode
|
||||
logger.warning('cannot properly encode in JSON the object %s, '
|
||||
'returned repr is: %r', type(o), o)
|
||||
|
|
|
@ -73,14 +73,29 @@ class AsynchronousFileReader(Process):
|
|||
Process.join(self, timeout)
|
||||
|
||||
|
||||
def consume_queue(queue, callback):
|
||||
"""Consume the queue and give content to the callback."""
|
||||
while True:
|
||||
line = queue.get()
|
||||
if line:
|
||||
if line == StopIteration:
|
||||
break
|
||||
callback(line)
|
||||
class Consummer(object):
|
||||
def __init__(self, queue, callback):
|
||||
self.queue = queue
|
||||
self.callback = callback
|
||||
|
||||
def empty(self):
|
||||
return self.queue.empty()
|
||||
|
||||
def process_next_line(self):
|
||||
if not self.empty():
|
||||
line = self.queue.get()
|
||||
if line:
|
||||
if line == StopIteration:
|
||||
return
|
||||
self.callback(line)
|
||||
|
||||
def process_current_queue(self):
|
||||
while not self.empty():
|
||||
line = self.queue.get()
|
||||
if line:
|
||||
if line == StopIteration:
|
||||
break
|
||||
self.callback(line)
|
||||
|
||||
|
||||
def async_file_reading(fd, callback):
|
||||
|
@ -88,6 +103,5 @@ def async_file_reading(fd, callback):
|
|||
queue = SimpleQueue()
|
||||
reader = AsynchronousFileReader(fd, queue)
|
||||
reader.start()
|
||||
consummer = Process(target=consume_queue, args=(queue, callback))
|
||||
consummer.start()
|
||||
consummer = Consummer(queue, callback)
|
||||
return (reader, consummer)
|
||||
|
|
Loading…
Add table
Reference in a new issue