From 115b557b67893111d5b7708f6b3b3226615f3092 Mon Sep 17 00:00:00 2001 From: Alexandre Aubin Date: Thu, 13 Dec 2018 18:49:20 +0000 Subject: [PATCH] autopep8 + a few manual tweaks --- src/yunohost/app.py | 51 +++--- src/yunohost/backup.py | 165 +++++++++--------- src/yunohost/certificate.py | 64 +++---- .../0001_change_cert_group_to_sslcert.py | 2 + .../0002_migrate_to_tsig_sha256.py | 4 +- .../0003_migrate_to_stretch.py | 13 +- .../0004_php5_to_php7_pools.py | 3 +- .../0005_postgresql_9p4_to_9p6.py | 1 + .../0006_sync_admin_and_root_passwords.py | 2 + ...0007_ssh_conf_managed_by_yunohost_step1.py | 9 +- ...0008_ssh_conf_managed_by_yunohost_step2.py | 5 +- src/yunohost/domain.py | 4 +- src/yunohost/dyndns.py | 11 +- src/yunohost/firewall.py | 4 +- src/yunohost/hook.py | 6 +- src/yunohost/log.py | 3 +- src/yunohost/monitor.py | 8 +- src/yunohost/service.py | 27 +-- src/yunohost/settings.py | 14 +- src/yunohost/ssh.py | 2 +- src/yunohost/tests/conftest.py | 15 +- src/yunohost/tests/test_appslist.py | 26 +-- src/yunohost/tests/test_appurl.py | 7 +- src/yunohost/tests/test_backuprestore.py | 95 +++++----- src/yunohost/tests/test_changeurl.py | 1 + src/yunohost/tests/test_settings.py | 7 +- src/yunohost/tools.py | 41 +++-- src/yunohost/user.py | 16 +- src/yunohost/utils/error.py | 4 +- src/yunohost/utils/filesystem.py | 2 + src/yunohost/utils/network.py | 2 +- src/yunohost/utils/packages.py | 6 + src/yunohost/utils/password.py | 6 +- src/yunohost/utils/yunopaste.py | 1 + 34 files changed, 341 insertions(+), 286 deletions(-) diff --git a/src/yunohost/app.py b/src/yunohost/app.py index 36a0414ec..8eaef03c5 100644 --- a/src/yunohost/app.py +++ b/src/yunohost/app.py @@ -137,7 +137,7 @@ def app_fetchlist(url=None, name=None): else: appslists_to_be_fetched = appslists.keys() - import requests # lazy loading this module for performance reasons + import requests # lazy loading this module for performance reasons # Fetch all appslists to be fetched for name in appslists_to_be_fetched: @@ -172,7 +172,7 @@ def app_fetchlist(url=None, name=None): appslist = appslist_request.text try: json.loads(appslist) - except ValueError, e: + except ValueError as e: logger.error(m18n.n('appslist_retrieve_bad_format', appslist=name)) continue @@ -542,7 +542,7 @@ def app_change_url(operation_logger, auth, app, domain, path): raise YunohostError("app_change_url_failed_nginx_reload", nginx_errors=nginx_errors) logger.success(m18n.n("app_change_url_success", - app=app, domain=domain, path=path)) + app=app, domain=domain, path=path)) hook_callback('post_app_change_url', args=args_list, env=env_dict) @@ -701,7 +701,6 @@ def app_install(operation_logger, auth, app, label=None, args=None, no_remove_on from yunohost.hook import hook_add, hook_remove, hook_exec, hook_callback from yunohost.log import OperationLogger - # Fetch or extract sources try: os.listdir(INSTALL_TMP) @@ -758,7 +757,7 @@ def app_install(operation_logger, auth, app, label=None, args=None, no_remove_on env_dict["YNH_APP_INSTANCE_NUMBER"] = str(instance_number) # Start register change on system - operation_logger.extra.update({'env':env_dict}) + operation_logger.extra.update({'env': env_dict}) operation_logger.related_to = [s for s in operation_logger.related_to if s[0] != "app"] operation_logger.related_to.append(("app", app_id)) operation_logger.start() @@ -816,8 +815,8 @@ def app_install(operation_logger, auth, app, label=None, args=None, no_remove_on # Execute remove script operation_logger_remove = OperationLogger('remove_on_failed_install', - [('app', app_instance_name)], - env=env_dict_remove) + [('app', app_instance_name)], + env=env_dict_remove) operation_logger_remove.start() remove_retcode = hook_exec( @@ -944,7 +943,6 @@ def app_addaccess(auth, apps, users=[]): for app in apps: - app_settings = _get_app_settings(app) if not app_settings: continue @@ -957,7 +955,7 @@ def app_addaccess(auth, apps, users=[]): # Start register change on system related_to = [('app', app)] - operation_logger= OperationLogger('app_addaccess', related_to) + operation_logger = OperationLogger('app_addaccess', related_to) operation_logger.start() allowed_users = set() @@ -1020,7 +1018,7 @@ def app_removeaccess(auth, apps, users=[]): # Start register change on system related_to = [('app', app)] - operation_logger= OperationLogger('app_removeaccess', related_to) + operation_logger = OperationLogger('app_removeaccess', related_to) operation_logger.start() if remove_all: @@ -1034,7 +1032,7 @@ def app_removeaccess(auth, apps, users=[]): if allowed_user not in users: allowed_users.add(allowed_user) - operation_logger.related_to += [ ('user', x) for x in allowed_users ] + operation_logger.related_to += [('user', x) for x in allowed_users] operation_logger.flush() new_users = ','.join(allowed_users) app_setting(app, 'allowed_users', new_users) @@ -1069,7 +1067,7 @@ def app_clearaccess(auth, apps): # Start register change on system related_to = [('app', app)] - operation_logger= OperationLogger('app_clearaccess', related_to) + operation_logger = OperationLogger('app_clearaccess', related_to) operation_logger.start() if 'mode' in app_settings: @@ -1126,7 +1124,7 @@ def app_makedefault(operation_logger, auth, app, domain=None): if domain is None: domain = app_domain - operation_logger.related_to.append(('domain',domain)) + operation_logger.related_to.append(('domain', domain)) elif domain not in domain_list(auth)['domains']: raise YunohostError('domain_unknown') @@ -1218,7 +1216,7 @@ def app_register_url(auth, app, domain, path): # This line can't be moved on top of file, otherwise it creates an infinite # loop of import with tools.py... - from domain import _get_conflicting_apps, _normalize_domain_path + from .domain import _get_conflicting_apps, _normalize_domain_path domain, path = _normalize_domain_path(domain, path) @@ -1569,10 +1567,10 @@ def app_config_show_panel(app): parsed_values[key] = value return_code = hook_exec(config_script, - args=["show"], - env=env, - stdout_callback=parse_stdout, - ) + args=["show"], + env=env, + stdout_callback=parse_stdout, + ) if return_code != 0: raise Exception("script/config show return value code: %s (considered as an error)", return_code) @@ -1656,9 +1654,9 @@ def app_config_apply(app, args): logger.warning("Ignore key '%s' from arguments because it is not in the config", key) return_code = hook_exec(config_script, - args=["apply"], - env=env, - ) + args=["apply"], + env=env, + ) if return_code != 0: raise Exception("'script/config apply' return value code: %s (considered as an error)", return_code) @@ -2185,7 +2183,6 @@ def _parse_action_args_in_yunohost_format(args, action_args, auth=None): elif arg_type == 'password': msignals.display(m18n.n('good_practices_about_user_password')) - try: input_string = msignals.prompt(ask_string, is_password) except NotImplementedError: @@ -2385,7 +2382,7 @@ def _install_appslist_fetch_cron(): with open(cron_job_file, "w") as f: f.write('\n'.join(cron_job)) - _set_permissions(cron_job_file, "root", "root", 0755) + _set_permissions(cron_job_file, "root", "root", 0o755) # FIXME - Duplicate from certificate.py, should be moved into a common helper @@ -2431,7 +2428,7 @@ def _write_appslist_list(appslist_lists): json.dump(appslist_lists, f) except Exception as e: raise YunohostError("Error while writing list of appslist %s: %s" % - (APPSLISTS_JSON, str(e)), __raw_msg__=True) + (APPSLISTS_JSON, str(e)), __raw_msg__=True) def _register_new_appslist(url, name): @@ -2541,7 +2538,7 @@ def _patch_php5(app_folder): continue c = "sed -i -e 's@/etc/php5@/etc/php/7.0@g' " \ - "-e 's@/var/run/php5-fpm@/var/run/php/php7.0-fpm@g' " \ - "-e 's@php5@php7.0@g' " \ - "%s" % filename + "-e 's@/var/run/php5-fpm@/var/run/php/php7.0-fpm@g' " \ + "-e 's@php5@php7.0@g' " \ + "%s" % filename os.system(c) diff --git a/src/yunohost/backup.py b/src/yunohost/backup.py index 6ed73d343..745291fb1 100644 --- a/src/yunohost/backup.py +++ b/src/yunohost/backup.py @@ -52,6 +52,7 @@ from yunohost.monitor import binary_to_human from yunohost.tools import tools_postinstall from yunohost.service import service_regen_conf from yunohost.log import OperationLogger +from functools import reduce BACKUP_PATH = '/home/yunohost.backup' ARCHIVES_PATH = '%s/archives' % BACKUP_PATH @@ -63,6 +64,7 @@ logger = getActionLogger('yunohost.backup') class BackupRestoreTargetsManager(object): + """ BackupRestoreTargetsManager manage the targets in BackupManager and RestoreManager @@ -176,6 +178,7 @@ class BackupRestoreTargetsManager(object): class BackupManager(): + """ This class collect files to backup in a list and apply one or several backup method on it. @@ -267,9 +270,9 @@ class BackupManager(): self.work_dir = os.path.join(BACKUP_PATH, 'tmp', name) self._init_work_dir() - ########################################################################### - # Misc helpers # - ########################################################################### + # + # Misc helpers # + # @property def info(self): @@ -321,16 +324,16 @@ class BackupManager(): # FIXME replace isdir by exists ? manage better the case where the path # exists if not os.path.isdir(self.work_dir): - filesystem.mkdir(self.work_dir, 0750, parents=True, uid='admin') + filesystem.mkdir(self.work_dir, 0o750, parents=True, uid='admin') elif self.is_tmp_work_dir: logger.debug("temporary directory for backup '%s' already exists", self.work_dir) # FIXME May be we should clean the workdir here raise YunohostError('backup_output_directory_not_empty') - ########################################################################### - # Backup target management # - ########################################################################### + # + # Backup target management # + # def set_system_targets(self, system_parts=[]): """ @@ -380,9 +383,9 @@ class BackupManager(): logger.warning(m18n.n('backup_with_no_restore_script_for_app', app=app)) self.targets.set_result("apps", app, "Warning") - ########################################################################### - # Management of files to backup / "The CSV" # - ########################################################################### + # + # Management of files to backup / "The CSV" # + # def _import_to_list_to_backup(self, tmp_csv): """ @@ -465,9 +468,9 @@ class BackupManager(): logger.error(m18n.n('backup_csv_addition_failed')) self.csv_file.close() - ########################################################################### - # File collection from system parts and apps # - ########################################################################### + # + # File collection from system parts and apps # + # def collect_files(self): """ @@ -602,7 +605,7 @@ class BackupManager(): restore_hooks_dir = os.path.join(self.work_dir, "hooks", "restore") if not os.path.exists(restore_hooks_dir): - filesystem.mkdir(restore_hooks_dir, mode=0750, + filesystem.mkdir(restore_hooks_dir, mode=0o750, parents=True, uid='admin') restore_hooks = hook_list("restore")["hooks"] @@ -668,7 +671,7 @@ class BackupManager(): logger.debug(m18n.n('backup_running_app_script', app=app)) try: # Prepare backup directory for the app - filesystem.mkdir(tmp_app_bkp_dir, 0750, True, uid='admin') + filesystem.mkdir(tmp_app_bkp_dir, 0o750, True, uid='admin') # Copy the app settings to be able to call _common.sh shutil.copytree(app_setting_path, settings_dir) @@ -702,9 +705,9 @@ class BackupManager(): filesystem.rm(tmp_script, force=True) filesystem.rm(env_dict["YNH_BACKUP_CSV"], force=True) - ########################################################################### - # Actual backup archive creation / method management # - ########################################################################### + # + # Actual backup archive creation / method management # + # def add(self, method): """ @@ -776,6 +779,7 @@ class BackupManager(): class RestoreManager(): + """ RestoreManager allow to restore a past backup archive @@ -824,9 +828,9 @@ class RestoreManager(): self.method = BackupMethod.create(method) self.targets = BackupRestoreTargetsManager() - ########################################################################### - # Misc helpers # - ########################################################################### + # + # Misc helpers # + # @property def success(self): @@ -876,7 +880,7 @@ class RestoreManager(): domain = f.readline().rstrip() except IOError: logger.debug("unable to retrieve current_host from the backup", - exc_info=1) + exc_info=1) # FIXME include the current_host by default ? raise YunohostError('backup_invalid_archive') @@ -902,9 +906,9 @@ class RestoreManager(): logger.warning(m18n.n('restore_cleaning_failed')) filesystem.rm(self.work_dir, True, True) - ########################################################################### - # Restore target manangement # - ########################################################################### + # + # Restore target manangement # + # def set_system_targets(self, system_parts=[]): """ @@ -980,9 +984,9 @@ class RestoreManager(): self.info['apps'].keys(), unknown_error) - ########################################################################### - # Archive mounting # - ########################################################################### + # + # Archive mounting # + # def mount(self): """ @@ -1023,9 +1027,9 @@ class RestoreManager(): self._read_info_files() - ########################################################################### - # Space computation / checks # - ########################################################################### + # + # Space computation / checks # + # def _compute_needed_space(self): """ @@ -1082,13 +1086,13 @@ class RestoreManager(): return True elif free_space > needed_space: # TODO Add --force options to avoid the error raising - raise YunohostError('restore_may_be_not_enough_disk_space', free_space=free_space, needed_space=needed_space, margin=margin) + raise YunohostError('restore_may_be_not_enough_disk_space', free_space=free_space, needed_space=needed_space, margin=margin) else: raise YunohostError('restore_not_enough_disk_space', free_space=free_space, needed_space=needed_space, margin=margin) - ########################################################################### - # "Actual restore" (reverse step of the backup collect part) # - ########################################################################### + # + # "Actual restore" (reverse step of the backup collect part) # + # def restore(self): """ @@ -1104,7 +1108,6 @@ class RestoreManager(): # Apply dirty patch to redirect php5 file on php7 self._patch_backup_csv_file() - self._restore_system() self._restore_apps() finally: @@ -1130,7 +1133,7 @@ class RestoreManager(): contains_php5 = True row['source'] = row['source'].replace('/etc/php5', '/etc/php/7.0') \ .replace('/var/run/php5-fpm', '/var/run/php/php7.0-fpm') \ - .replace('php5','php7') + .replace('php5', 'php7') newlines.append(row) except (IOError, OSError, csv.Error) as e: @@ -1260,7 +1263,7 @@ class RestoreManager(): # Check if the app has a restore script app_restore_script_in_archive = os.path.join(app_scripts_in_archive, - 'restore') + 'restore') if not os.path.isfile(app_restore_script_in_archive): logger.warning(m18n.n('unrestore_app', app=app_instance_name)) self.targets.set_result("apps", app_instance_name, "Warning") @@ -1273,7 +1276,7 @@ class RestoreManager(): app_instance_name) app_scripts_new_path = os.path.join(app_settings_new_path, 'scripts') shutil.copytree(app_settings_in_archive, app_settings_new_path) - filesystem.chmod(app_settings_new_path, 0400, 0400, True) + filesystem.chmod(app_settings_new_path, 0o400, 0o400, True) filesystem.chown(app_scripts_new_path, 'admin', None, True) # Copy the app scripts to a writable temporary folder @@ -1281,7 +1284,7 @@ class RestoreManager(): # in the backup method ? tmp_folder_for_app_restore = tempfile.mkdtemp(prefix='restore') copytree(app_scripts_in_archive, tmp_folder_for_app_restore) - filesystem.chmod(tmp_folder_for_app_restore, 0550, 0550, True) + filesystem.chmod(tmp_folder_for_app_restore, 0o550, 0o550, True) filesystem.chown(tmp_folder_for_app_restore, 'admin', None, True) restore_script = os.path.join(tmp_folder_for_app_restore, 'restore') @@ -1298,7 +1301,7 @@ class RestoreManager(): raise_on_error=True, env=env_dict) except: - msg = m18n.n('restore_app_failed',app=app_instance_name) + msg = m18n.n('restore_app_failed', app=app_instance_name) logger.exception(msg) operation_logger.error(msg) @@ -1314,8 +1317,8 @@ class RestoreManager(): env_dict_remove["YNH_APP_INSTANCE_NUMBER"] = str(app_instance_nb) operation_logger = OperationLogger('remove_on_failed_restore', - [('app', app_instance_name)], - env=env_dict_remove) + [('app', app_instance_name)], + env=env_dict_remove) operation_logger.start() # Execute remove script @@ -1359,12 +1362,13 @@ class RestoreManager(): return env_var -############################################################################### -# Backup methods # -############################################################################### +# +# Backup methods # +# class BackupMethod(object): + """ BackupMethod is an abstract class that represents a way to backup and restore a list of files. @@ -1637,7 +1641,7 @@ class BackupMethod(object): if size > MB_ALLOWED_TO_ORGANIZE: try: i = msignals.prompt(m18n.n('backup_ask_for_copying_if_needed', - answers='y/N', size=str(size))) + answers='y/N', size=str(size))) except NotImplemented: raise YunohostError('backup_unable_to_organize_files') else: @@ -1646,7 +1650,7 @@ class BackupMethod(object): # Copy unbinded path logger.debug(m18n.n('backup_copying_to_organize_the_archive', - size=str(size))) + size=str(size))) for path in paths_needed_to_be_copied: dest = os.path.join(self.work_dir, path['dest']) if os.path.isdir(path['source']): @@ -1686,6 +1690,7 @@ class BackupMethod(object): class CopyBackupMethod(BackupMethod): + """ This class just do an uncompress copy of each file in a location, and could be the inverse for restoring @@ -1712,7 +1717,7 @@ class CopyBackupMethod(BackupMethod): dest_parent = os.path.dirname(dest) if not os.path.exists(dest_parent): - filesystem.mkdir(dest_parent, 0750, True, uid='admin') + filesystem.mkdir(dest_parent, 0o750, True, uid='admin') if os.path.isdir(source): shutil.copytree(source, dest) @@ -1747,6 +1752,7 @@ class CopyBackupMethod(BackupMethod): class TarBackupMethod(BackupMethod): + """ This class compress all files to backup in archive. """ @@ -1777,7 +1783,7 @@ class TarBackupMethod(BackupMethod): """ if not os.path.exists(self.repo): - filesystem.mkdir(self.repo, 0750, parents=True, uid='admin') + filesystem.mkdir(self.repo, 0o750, parents=True, uid='admin') # Check free space in output self._check_is_enough_free_space() @@ -1895,6 +1901,7 @@ class BorgBackupMethod(BackupMethod): class CustomBackupMethod(BackupMethod): + """ This class use a bash script/hook "backup_method" to do the backup/restore operations. A user can add his own hook inside @@ -1958,9 +1965,9 @@ class CustomBackupMethod(BackupMethod): self.manager.description] -############################################################################### -# "Front-end" # -############################################################################### +# +# "Front-end" # +# def backup_create(name=None, description=None, methods=[], output_directory=None, no_compress=False, @@ -1980,9 +1987,9 @@ def backup_create(name=None, description=None, methods=[], # TODO: Add a 'clean' argument to clean output directory - ########################################################################### - # Validate / parse arguments # - ########################################################################### + # + # Validate / parse arguments # + # # Validate there is no archive with the same name if name and name in backup_list()['archives']: @@ -1995,7 +2002,7 @@ def backup_create(name=None, description=None, methods=[], # Check for forbidden folders if output_directory.startswith(ARCHIVES_PATH) or \ re.match(r'^/(|(bin|boot|dev|etc|lib|root|run|sbin|sys|usr|var)(|/.*))$', - output_directory): + output_directory): raise YunohostError('backup_output_directory_forbidden') # Check that output directory is empty @@ -2017,9 +2024,9 @@ def backup_create(name=None, description=None, methods=[], system = [] apps = [] - ########################################################################### - # Intialize # - ########################################################################### + # + # Intialize # + # # Create yunohost archives directory if it does not exists _create_archive_dir() @@ -2044,9 +2051,9 @@ def backup_create(name=None, description=None, methods=[], backup_manager.set_system_targets(system) backup_manager.set_apps_targets(apps) - ########################################################################### - # Collect files and put them in the archive # - ########################################################################### + # + # Collect files and put them in the archive # + # # Collect files to be backup (by calling app backup script / system hooks) backup_manager.collect_files() @@ -2074,9 +2081,9 @@ def backup_restore(auth, name, system=[], apps=[], force=False): apps -- List of application names to restore """ - ########################################################################### - # Validate / parse arguments # - ########################################################################### + # + # Validate / parse arguments # + # # If no --system or --apps given, restore everything if system is None and apps is None: @@ -2105,9 +2112,9 @@ def backup_restore(auth, name, system=[], apps=[], force=False): # TODO Partial app restore could not work if ldap is not restored before # TODO repair mysql if broken and it's a complete restore - ########################################################################### - # Initialize # - ########################################################################### + # + # Initialize # + # restore_manager = RestoreManager(name) @@ -2116,9 +2123,9 @@ def backup_restore(auth, name, system=[], apps=[], force=False): restore_manager.assert_enough_free_space() - ########################################################################### - # Mount the archive then call the restore for each system part / app # - ########################################################################### + # + # Mount the archive then call the restore for each system part / app # + # restore_manager.mount() restore_manager.restore() @@ -2156,7 +2163,7 @@ def backup_list(with_info=False, human_readable=False): except ValueError: continue result.append(name) - result.sort(key=lambda x: os.path.getctime(os.path.join(ARCHIVES_PATH, x+".tar.gz"))) + result.sort(key=lambda x: os.path.getctime(os.path.join(ARCHIVES_PATH, x + ".tar.gz"))) if result and with_info: d = OrderedDict() @@ -2194,7 +2201,7 @@ def backup_info(name, with_details=False, human_readable=False): # Raise exception if link is broken (e.g. on unmounted external storage) if not os.path.exists(archive_file): raise YunohostError('backup_archive_broken_link', - path=archive_file) + path=archive_file) info_file = "%s/%s.info.json" % (ARCHIVES_PATH, name) @@ -2259,7 +2266,7 @@ def backup_delete(name): """ if name not in backup_list()["archives"]: raise YunohostError('backup_archive_name_unknown', - name=name) + name=name) hook_callback('pre_backup_delete', args=[name]) @@ -2277,9 +2284,9 @@ def backup_delete(name): logger.success(m18n.n('backup_deleted')) -############################################################################### -# Misc helpers # -############################################################################### +# +# Misc helpers # +# def _create_archive_dir(): @@ -2288,7 +2295,7 @@ def _create_archive_dir(): if os.path.lexists(ARCHIVES_PATH): raise YunohostError('backup_output_symlink_dir_broken', path=ARCHIVES_PATH) - os.mkdir(ARCHIVES_PATH, 0750) + os.mkdir(ARCHIVES_PATH, 0o750) def _call_for_each_path(self, callback, csv_path=None): diff --git a/src/yunohost/certificate.py b/src/yunohost/certificate.py index cdcf4bbe9..aea0c60b1 100644 --- a/src/yunohost/certificate.py +++ b/src/yunohost/certificate.py @@ -80,9 +80,9 @@ DNS_RESOLVERS = [ "80.67.188.188" # LDN ] -############################################################################### -# Front-end stuff # -############################################################################### +# +# Front-end stuff # +# def certificate_status(auth, domain_list, full=False): @@ -149,7 +149,7 @@ def _certificate_install_selfsigned(domain_list, force=False): for domain in domain_list: operation_logger = OperationLogger('selfsigned_cert_install', [('domain', domain)], - args={'force': force}) + args={'force': force}) # Paths of files and folder we'll need date_tag = datetime.utcnow().strftime("%Y%m%d.%H%M%S") @@ -215,10 +215,10 @@ def _certificate_install_selfsigned(domain_list, force=False): crt_pem.write(ca_pem.read()) # Set appropriate permissions - _set_permissions(new_cert_folder, "root", "root", 0755) - _set_permissions(key_file, "root", "ssl-cert", 0640) - _set_permissions(crt_file, "root", "ssl-cert", 0640) - _set_permissions(conf_file, "root", "root", 0600) + _set_permissions(new_cert_folder, "root", "root", 0o755) + _set_permissions(key_file, "root", "ssl-cert", 0o640) + _set_permissions(crt_file, "root", "ssl-cert", 0o640) + _set_permissions(conf_file, "root", "root", 0o600) # Actually enable the certificate we created _enable_certificate(domain, new_cert_folder) @@ -273,8 +273,8 @@ def _certificate_install_letsencrypt(auth, domain_list, force=False, no_checks=F for domain in domain_list: operation_logger = OperationLogger('letsencrypt_cert_install', [('domain', domain)], - args={'force': force, 'no_checks': no_checks, - 'staging': staging}) + args={'force': force, 'no_checks': no_checks, + 'staging': staging}) logger.info( "Now attempting install of certificate for domain %s!", domain) @@ -298,6 +298,7 @@ def _certificate_install_letsencrypt(auth, domain_list, force=False, no_checks=F logger.error(msg) operation_logger.error(msg) + def certificate_renew(auth, domain_list, force=False, no_checks=False, email=False, staging=False): """ Renew Let's Encrypt certificate for given domains (all by default) @@ -367,8 +368,8 @@ def certificate_renew(auth, domain_list, force=False, no_checks=False, email=Fal for domain in domain_list: operation_logger = OperationLogger('letsencrypt_cert_renew', [('domain', domain)], - args={'force': force, 'no_checks': no_checks, - 'staging': staging, 'email': email}) + args={'force': force, 'no_checks': no_checks, + 'staging': staging, 'email': email}) logger.info( "Now attempting renewing of certificate for domain %s !", domain) @@ -401,9 +402,10 @@ def certificate_renew(auth, domain_list, force=False, no_checks=False, email=Fal logger.error("Sending email with details to root ...") _email_renewing_failed(domain, e, stack.getvalue()) -############################################################################### -# Back-end stuff # -############################################################################### +# +# Back-end stuff # +# + def _install_cron(): cron_job_file = "/etc/cron.daily/yunohost-certificate-renew" @@ -412,7 +414,7 @@ def _install_cron(): f.write("#!/bin/bash\n") f.write("yunohost domain cert-renew --email\n") - _set_permissions(cron_job_file, "root", "root", 0755) + _set_permissions(cron_job_file, "root", "root", 0o755) def _email_renewing_failed(domain, exception_message, stack): @@ -517,8 +519,8 @@ def _fetch_and_enable_new_certificate(domain, staging=False, no_checks=False): if not os.path.exists(TMP_FOLDER): os.makedirs(TMP_FOLDER) - _set_permissions(WEBROOT_FOLDER, "root", "www-data", 0650) - _set_permissions(TMP_FOLDER, "root", "root", 0640) + _set_permissions(WEBROOT_FOLDER, "root", "www-data", 0o650) + _set_permissions(TMP_FOLDER, "root", "root", 0o640) # Regen conf for dnsmasq if needed _regen_dnsmasq_if_needed() @@ -529,7 +531,7 @@ def _fetch_and_enable_new_certificate(domain, staging=False, no_checks=False): domain_key_file = "%s/%s.pem" % (TMP_FOLDER, domain) _generate_key(domain_key_file) - _set_permissions(domain_key_file, "root", "ssl-cert", 0640) + _set_permissions(domain_key_file, "root", "ssl-cert", 0o640) _prepare_certificate_signing_request(domain, domain_key_file, TMP_FOLDER) @@ -563,7 +565,7 @@ def _fetch_and_enable_new_certificate(domain, staging=False, no_checks=False): raise YunohostError('certmanager_cert_signing_failed') - import requests # lazy loading this module for performance reasons + import requests # lazy loading this module for performance reasons try: intermediate_certificate = requests.get(INTERMEDIATE_CERTIFICATE_URL, timeout=30).text except requests.exceptions.Timeout as e: @@ -585,12 +587,12 @@ def _fetch_and_enable_new_certificate(domain, staging=False, no_checks=False): os.makedirs(new_cert_folder) - _set_permissions(new_cert_folder, "root", "root", 0655) + _set_permissions(new_cert_folder, "root", "root", 0o655) # Move the private key domain_key_file_finaldest = os.path.join(new_cert_folder, "key.pem") shutil.move(domain_key_file, domain_key_file_finaldest) - _set_permissions(domain_key_file_finaldest, "root", "ssl-cert", 0640) + _set_permissions(domain_key_file_finaldest, "root", "ssl-cert", 0o640) # Write the cert domain_cert_file = os.path.join(new_cert_folder, "crt.pem") @@ -599,7 +601,7 @@ def _fetch_and_enable_new_certificate(domain, staging=False, no_checks=False): f.write(signed_certificate) f.write(intermediate_certificate) - _set_permissions(domain_cert_file, "root", "ssl-cert", 0640) + _set_permissions(domain_cert_file, "root", "ssl-cert", 0o640) if staging: return @@ -614,7 +616,7 @@ def _fetch_and_enable_new_certificate(domain, staging=False, no_checks=False): def _prepare_certificate_signing_request(domain, key_file, output_folder): - from OpenSSL import crypto # lazy loading this module for performance reasons + from OpenSSL import crypto # lazy loading this module for performance reasons # Init a request csr = crypto.X509Req() @@ -645,7 +647,7 @@ def _get_status(domain): if not os.path.isfile(cert_file): raise YunohostError('certmanager_no_cert_file', domain=domain, file=cert_file) - from OpenSSL import crypto # lazy loading this module for performance reasons + from OpenSSL import crypto # lazy loading this module for performance reasons try: cert = crypto.load_certificate( crypto.FILETYPE_PEM, open(cert_file).read()) @@ -735,19 +737,19 @@ def _get_status(domain): "ACME_eligible": ACME_eligible } -############################################################################### -# Misc small stuff ... # -############################################################################### +# +# Misc small stuff ... # +# def _generate_account_key(): logger.debug("Generating account key ...") _generate_key(ACCOUNT_KEY_FILE) - _set_permissions(ACCOUNT_KEY_FILE, "root", "root", 0400) + _set_permissions(ACCOUNT_KEY_FILE, "root", "root", 0o400) def _generate_key(destination_path): - from OpenSSL import crypto # lazy loading this module for performance reasons + from OpenSSL import crypto # lazy loading this module for performance reasons k = crypto.PKey() k.generate_key(crypto.TYPE_RSA, KEY_SIZE) @@ -836,7 +838,7 @@ def _dns_ip_match_public_ip(public_ip, domain): def _domain_is_accessible_through_HTTP(ip, domain): - import requests # lazy loading this module for performance reasons + import requests # lazy loading this module for performance reasons try: requests.head("http://" + ip, headers={"Host": domain}, timeout=10) except requests.exceptions.Timeout as e: diff --git a/src/yunohost/data_migrations/0001_change_cert_group_to_sslcert.py b/src/yunohost/data_migrations/0001_change_cert_group_to_sslcert.py index cd39df9fa..6485861b7 100644 --- a/src/yunohost/data_migrations/0001_change_cert_group_to_sslcert.py +++ b/src/yunohost/data_migrations/0001_change_cert_group_to_sslcert.py @@ -3,7 +3,9 @@ import glob from yunohost.tools import Migration from moulinette.utils.filesystem import chown + class MyMigration(Migration): + "Change certificates group permissions from 'metronome' to 'ssl-cert'" all_certificate_files = glob.glob("/etc/yunohost/certs/*/*.pem") diff --git a/src/yunohost/data_migrations/0002_migrate_to_tsig_sha256.py b/src/yunohost/data_migrations/0002_migrate_to_tsig_sha256.py index 39e4d2afe..824245c82 100644 --- a/src/yunohost/data_migrations/0002_migrate_to_tsig_sha256.py +++ b/src/yunohost/data_migrations/0002_migrate_to_tsig_sha256.py @@ -16,6 +16,7 @@ logger = getActionLogger('yunohost.migration') class MyMigration(Migration): + "Migrate Dyndns stuff from MD5 TSIG to SHA512 TSIG" def backward(self): @@ -70,7 +71,7 @@ class MyMigration(Migration): os.system("mv /etc/yunohost/dyndns/*+165* /tmp") raise YunohostError('migrate_tsig_failed', domain=domain, - error_code=str(r.status_code), error=error) + error_code=str(r.status_code), error=error) # remove old certificates os.system("mv /etc/yunohost/dyndns/*+157* /tmp") @@ -87,4 +88,3 @@ class MyMigration(Migration): logger.info(m18n.n('migrate_tsig_end')) return - diff --git a/src/yunohost/data_migrations/0003_migrate_to_stretch.py b/src/yunohost/data_migrations/0003_migrate_to_stretch.py index 80d182fbe..ee8c09849 100644 --- a/src/yunohost/data_migrations/0003_migrate_to_stretch.py +++ b/src/yunohost/data_migrations/0003_migrate_to_stretch.py @@ -24,6 +24,7 @@ YUNOHOST_PACKAGES = ["yunohost", "yunohost-admin", "moulinette", "ssowat"] class MyMigration(Migration): + "Upgrade the system to Debian Stretch and Yunohost 3.0" mode = "manual" @@ -168,11 +169,11 @@ class MyMigration(Migration): # - switch yunohost's repo to forge for f in sources_list: command = "sed -i -e 's@ jessie @ stretch @g' " \ - "-e '/backports/ s@^#*@#@' " \ - "-e 's@ jessie/updates @ stretch/updates @g' " \ - "-e 's@ jessie-updates @ stretch-updates @g' " \ - "-e 's@repo.yunohost@forge.yunohost@g' " \ - "{}".format(f) + "-e '/backports/ s@^#*@#@' " \ + "-e 's@ jessie/updates @ stretch/updates @g' " \ + "-e 's@ jessie-updates @ stretch-updates @g' " \ + "-e 's@repo.yunohost@forge.yunohost@g' " \ + "{}".format(f) os.system(command) def get_apps_equivs_packages(self): @@ -286,7 +287,7 @@ class MyMigration(Migration): # Create tmp directory if it does not exists tmp_dir = os.path.join("/tmp/", self.name) if not os.path.exists(tmp_dir): - os.mkdir(tmp_dir, 0700) + os.mkdir(tmp_dir, 0o700) for f in self.files_to_keep: dest_file = f.strip('/').replace("/", "_") diff --git a/src/yunohost/data_migrations/0004_php5_to_php7_pools.py b/src/yunohost/data_migrations/0004_php5_to_php7_pools.py index 0237ddb38..46a5eb91d 100644 --- a/src/yunohost/data_migrations/0004_php5_to_php7_pools.py +++ b/src/yunohost/data_migrations/0004_php5_to_php7_pools.py @@ -19,6 +19,7 @@ MIGRATION_COMMENT = "; YunoHost note : this file was automatically moved from {} class MyMigration(Migration): + "Migrate php5-fpm 'pool' conf files to php7 stuff" def migrate(self): @@ -58,7 +59,7 @@ class MyMigration(Migration): _run_service_command("enable", "php7.0-fpm") os.system("systemctl stop php5-fpm") os.system("systemctl disable php5-fpm") - os.system("rm /etc/logrotate.d/php5-fpm") # We remove this otherwise the logrotate cron will be unhappy + os.system("rm /etc/logrotate.d/php5-fpm") # We remove this otherwise the logrotate cron will be unhappy # Get list of nginx conf file nginx_conf_files = glob.glob("/etc/nginx/conf.d/*.d/*.conf") diff --git a/src/yunohost/data_migrations/0005_postgresql_9p4_to_9p6.py b/src/yunohost/data_migrations/0005_postgresql_9p4_to_9p6.py index 0208b717e..c4a6e7f34 100644 --- a/src/yunohost/data_migrations/0005_postgresql_9p4_to_9p6.py +++ b/src/yunohost/data_migrations/0005_postgresql_9p4_to_9p6.py @@ -11,6 +11,7 @@ logger = getActionLogger('yunohost.migration') class MyMigration(Migration): + "Migrate DBs from Postgresql 9.4 to 9.6 after migrating to Stretch" def migrate(self): diff --git a/src/yunohost/data_migrations/0006_sync_admin_and_root_passwords.py b/src/yunohost/data_migrations/0006_sync_admin_and_root_passwords.py index 1149f28d5..cd13d680d 100644 --- a/src/yunohost/data_migrations/0006_sync_admin_and_root_passwords.py +++ b/src/yunohost/data_migrations/0006_sync_admin_and_root_passwords.py @@ -15,7 +15,9 @@ from yunohost.tools import Migration logger = getActionLogger('yunohost.migration') SMALL_PWD_LIST = ["yunohost", "olinuxino", "olinux", "raspberry", "admin", "root", "test", "rpi"] + class MyMigration(Migration): + "Synchronize admin and root passwords" def migrate(self): diff --git a/src/yunohost/data_migrations/0007_ssh_conf_managed_by_yunohost_step1.py b/src/yunohost/data_migrations/0007_ssh_conf_managed_by_yunohost_step1.py index 306e47672..080cc0163 100644 --- a/src/yunohost/data_migrations/0007_ssh_conf_managed_by_yunohost_step1.py +++ b/src/yunohost/data_migrations/0007_ssh_conf_managed_by_yunohost_step1.py @@ -8,8 +8,10 @@ from moulinette.utils.log import getActionLogger from moulinette.utils.filesystem import mkdir, rm from yunohost.tools import Migration -from yunohost.service import service_regen_conf, _get_conf_hashes, \ - _calculate_hash, _run_service_command +from yunohost.service import service_regen_conf, \ + _get_conf_hashes, \ + _calculate_hash, \ + _run_service_command from yunohost.settings import settings_set from yunohost.utils.error import YunohostError @@ -19,6 +21,7 @@ SSHD_CONF = '/etc/ssh/sshd_config' class MyMigration(Migration): + """ This is the first step of a couple of migrations that ensure SSH conf is managed by YunoHost (even if the "from_script" flag is present, which was @@ -48,7 +51,7 @@ class MyMigration(Migration): # Create sshd_config.d dir if not os.path.exists(SSHD_CONF + '.d'): - mkdir(SSHD_CONF + '.d', 0755, uid='root', gid='root') + mkdir(SSHD_CONF + '.d', 0o755, uid='root', gid='root') # Here, we make it so that /etc/ssh/sshd_config is managed # by the regen conf (in particular in the case where the diff --git a/src/yunohost/data_migrations/0008_ssh_conf_managed_by_yunohost_step2.py b/src/yunohost/data_migrations/0008_ssh_conf_managed_by_yunohost_step2.py index 5d8fee89c..6adfa769f 100644 --- a/src/yunohost/data_migrations/0008_ssh_conf_managed_by_yunohost_step2.py +++ b/src/yunohost/data_migrations/0008_ssh_conf_managed_by_yunohost_step2.py @@ -3,7 +3,8 @@ import re from moulinette.utils.log import getActionLogger from yunohost.tools import Migration -from yunohost.service import service_regen_conf, _get_conf_hashes, \ +from yunohost.service import service_regen_conf, \ + _get_conf_hashes, \ _calculate_hash from yunohost.settings import settings_set, settings_get from yunohost.utils.error import YunohostError @@ -12,7 +13,9 @@ logger = getActionLogger('yunohost.migration') SSHD_CONF = '/etc/ssh/sshd_config' + class MyMigration(Migration): + """ In this second step, the admin is asked if it's okay to use the recommended SSH configuration - which also implies diff --git a/src/yunohost/domain.py b/src/yunohost/domain.py index 515a452a8..29c7ab554 100644 --- a/src/yunohost/domain.py +++ b/src/yunohost/domain.py @@ -115,8 +115,8 @@ def domain_add(operation_logger, auth, domain, dyndns=False): service_regen_conf(names=['nginx', 'metronome', 'dnsmasq', 'postfix']) app_ssowatconf(auth) - except Exception, e: - from sys import exc_info; + except Exception as e: + from sys import exc_info t, v, tb = exc_info() # Force domain removal silently diff --git a/src/yunohost/dyndns.py b/src/yunohost/dyndns.py index 0428eb93c..59a26e74b 100644 --- a/src/yunohost/dyndns.py +++ b/src/yunohost/dyndns.py @@ -104,7 +104,7 @@ def _dyndns_available(provider, domain): except MoulinetteError as e: logger.error(str(e)) raise YunohostError('dyndns_could_not_check_available', - domain=domain, provider=provider) + domain=domain, provider=provider) return r == u"Domain %s is available" % domain @@ -149,7 +149,7 @@ def dyndns_subscribe(operation_logger, subscribe_host="dyndns.yunohost.org", dom with open(key_file) as f: key = f.readline().strip().split(' ', 6)[-1] - import requests # lazy loading this module for performance reasons + import requests # lazy loading this module for performance reasons # Send subscription try: r = requests.post('https://%s/key/%s?key_algo=hmac-sha512' % (subscribe_host, base64.b64encode(key)), data={'subdomain': domain}, timeout=30) @@ -211,7 +211,7 @@ def dyndns_update(operation_logger, dyn_host="dyndns.yunohost.org", domain=None, exception=e, number=migration.number, name=migration.name), - exc_info=1) + exc_info=1) return # Extract 'host', e.g. 'nohost.me' from 'foo.nohost.me' @@ -225,7 +225,6 @@ def dyndns_update(operation_logger, dyn_host="dyndns.yunohost.org", domain=None, 'zone %s' % host, ] - old_ipv4 = check_output("dig @%s +short %s" % (dyn_host, domain)).strip() or None old_ipv6 = check_output("dig @%s +short aaaa %s" % (dyn_host, domain)).strip() or None @@ -252,7 +251,7 @@ def dyndns_update(operation_logger, dyn_host="dyndns.yunohost.org", domain=None, logger.info("Updated needed, going on...") dns_conf = _build_dns_conf(domain) - del dns_conf["extra"] # Ignore records from the 'extra' category + del dns_conf["extra"] # Ignore records from the 'extra' category # Delete the old records for all domain/subdomains @@ -273,7 +272,7 @@ def dyndns_update(operation_logger, dyn_host="dyndns.yunohost.org", domain=None, # should be muc.the.domain.tld. or the.domain.tld if record["value"] == "@": record["value"] = domain - record["value"] = record["value"].replace(";","\;") + record["value"] = record["value"].replace(";", "\;") action = "update add {name}.{domain}. {ttl} {type} {value}".format(domain=domain, **record) action = action.replace(" @.", " ") diff --git a/src/yunohost/firewall.py b/src/yunohost/firewall.py index f7c6c0875..39102bdc2 100644 --- a/src/yunohost/firewall.py +++ b/src/yunohost/firewall.py @@ -374,10 +374,10 @@ def firewall_upnp(action='status', no_refresh=False): try: # Add new port mapping upnpc.addportmapping(port, protocol, upnpc.lanaddr, - port, 'yunohost firewall: port %d' % port, '') + port, 'yunohost firewall: port %d' % port, '') except: logger.debug('unable to add port %d using UPnP', - port, exc_info=1) + port, exc_info=1) enabled = False if enabled != firewall['uPnP']['enabled']: diff --git a/src/yunohost/hook.py b/src/yunohost/hook.py index 5a6c4c154..79e9289ef 100644 --- a/src/yunohost/hook.py +++ b/src/yunohost/hook.py @@ -354,7 +354,7 @@ def hook_exec(path, args=None, raise_on_error=False, no_trace=False, # prepend environment variables cmd = '{0} {1}'.format( ' '.join(['{0}={1}'.format(k, shell_quote(v)) - for k, v in env.items()]), cmd) + for k, v in env.items()]), cmd) command.append(cmd.format(script=cmd_script, args=cmd_args)) if logger.isEnabledFor(log.DEBUG): @@ -369,8 +369,8 @@ def hook_exec(path, args=None, raise_on_error=False, no_trace=False, ) if stdinfo: - callbacks = ( callbacks[0], callbacks[1], - lambda l: logger.info(l.rstrip())) + callbacks = (callbacks[0], callbacks[1], + lambda l: logger.info(l.rstrip())) logger.debug("About to run the command '%s'" % command) diff --git a/src/yunohost/log.py b/src/yunohost/log.py index 7b32f18dd..d1e0c0e05 100644 --- a/src/yunohost/log.py +++ b/src/yunohost/log.py @@ -283,6 +283,7 @@ def is_unit_operation(entities=['app', 'domain', 'service', 'user'], class OperationLogger(object): + """ Instances of this class represents unit operation done on the ynh instance. @@ -423,7 +424,7 @@ class OperationLogger(object): else: if is_api: msg = "" + m18n.n('log_link_to_failed_log', - name=self.name, desc=desc) + "" + name=self.name, desc=desc) + "" else: msg = m18n.n('log_help_to_get_failed_log', name=self.name, desc=desc) diff --git a/src/yunohost/monitor.py b/src/yunohost/monitor.py index 469ac41f1..7af55f287 100644 --- a/src/yunohost/monitor.py +++ b/src/yunohost/monitor.py @@ -288,7 +288,7 @@ def monitor_system(units=None, human_readable=False): else: raise YunohostError('unit_unknown', unit=u) - if len(units) == 1 and type(result[units[0]]) is not str: + if len(units) == 1 and not isinstance(result[units[0]], str): return result[units[0]] return result @@ -404,7 +404,7 @@ def monitor_enable(with_stats=False): """ from yunohost.service import (service_status, service_enable, - service_start) + service_start) glances = service_status('glances') if glances['status'] != 'running': @@ -414,7 +414,7 @@ def monitor_enable(with_stats=False): # Install crontab if with_stats: - # day: every 5 min # week: every 1 h # month: every 4 h # + # day: every 5 min # week: every 1 h # month: every 4 h # rules = ('*/5 * * * * root {cmd} day >> /dev/null\n' '3 * * * * root {cmd} week >> /dev/null\n' '6 */4 * * * root {cmd} month >> /dev/null').format( @@ -431,7 +431,7 @@ def monitor_disable(): """ from yunohost.service import (service_status, service_disable, - service_stop) + service_stop) glances = service_status('glances') if glances['status'] != 'inactive': diff --git a/src/yunohost/service.py b/src/yunohost/service.py index b2c18c74e..a8ef0e796 100644 --- a/src/yunohost/service.py +++ b/src/yunohost/service.py @@ -151,6 +151,7 @@ def service_stop(names): raise YunohostError('service_stop_failed', service=name, logs=_get_journalctl_logs(name)) logger.debug(m18n.n('service_already_stopped', service=name)) + @is_unit_operation() def service_enable(operation_logger, names): """ @@ -377,7 +378,7 @@ def service_regen_conf(operation_logger, names=[], with_diff=False, force=False, if not names: operation_logger.name_parameter_override = 'all' elif len(names) != 1: - operation_logger.name_parameter_override = str(len(operation_logger.related_to))+'_services' + operation_logger.name_parameter_override = str(len(operation_logger.related_to)) + '_services' operation_logger.start() # Clean pending conf directory @@ -389,7 +390,7 @@ def service_regen_conf(operation_logger, names=[], with_diff=False, force=False, shutil.rmtree(os.path.join(PENDING_CONF_DIR, name), ignore_errors=True) else: - filesystem.mkdir(PENDING_CONF_DIR, 0755, True) + filesystem.mkdir(PENDING_CONF_DIR, 0o755, True) # Format common hooks arguments common_args = [1 if force else 0, 1 if dry_run else 0] @@ -400,7 +401,7 @@ def service_regen_conf(operation_logger, names=[], with_diff=False, force=False, def _pre_call(name, priority, path, args): # create the pending conf directory for the service service_pending_path = os.path.join(PENDING_CONF_DIR, name) - filesystem.mkdir(service_pending_path, 0755, True, uid='root') + filesystem.mkdir(service_pending_path, 0o755, True, uid='root') # return the arguments to pass to the script return pre_args + [service_pending_path, ] @@ -418,7 +419,7 @@ def service_regen_conf(operation_logger, names=[], with_diff=False, force=False, if not names: raise YunohostError('service_regenconf_failed', - services=', '.join(pre_result['failed'])) + services=', '.join(pre_result['failed'])) # Set the processing method _regen = _process_regen_conf if not dry_run else lambda *a, **k: True @@ -603,7 +604,7 @@ def _run_service_command(action, service): cmd = 'systemctl %s %s' % (action, service) need_lock = services[service].get('need_lock', False) \ - and action in ['start', 'stop', 'restart', 'reload'] + and action in ['start', 'stop', 'restart', 'reload'] try: # Launch the command @@ -637,10 +638,10 @@ def _give_lock(action, service, p): else: systemctl_PID_name = "ControlPID" - cmd_get_son_PID ="systemctl show %s -p %s" % (service, systemctl_PID_name) + cmd_get_son_PID = "systemctl show %s -p %s" % (service, systemctl_PID_name) son_PID = 0 # As long as we did not found the PID and that the command is still running - while son_PID == 0 and p.poll() == None: + while son_PID == 0 and p.poll() is None: # Call systemctl to get the PID # Output of the command is e.g. ControlPID=1234 son_PID = subprocess.check_output(cmd_get_son_PID.split()) \ @@ -657,11 +658,12 @@ def _give_lock(action, service, p): return son_PID + def _remove_lock(PID_to_remove): # FIXME ironically not concurrency safe because it's not atomic... PIDs = filesystem.read_file(MOULINETTE_LOCK).split("\n") - PIDs_to_keep = [ PID for PID in PIDs if int(PID) != PID_to_remove ] + PIDs_to_keep = [PID for PID in PIDs if int(PID) != PID_to_remove] filesystem.write_to_file(MOULINETTE_LOCK, '\n'.join(PIDs_to_keep)) @@ -775,6 +777,7 @@ def _find_previous_log_file(file): return None + def _get_files_diff(orig_file, new_file, as_string=False, skip_header=True): """Compare two files and return the differences @@ -919,22 +922,22 @@ def _process_regen_conf(system_conf, new_conf=None, save=True): backup_dir = os.path.dirname(backup_path) if not os.path.isdir(backup_dir): - filesystem.mkdir(backup_dir, 0755, True) + filesystem.mkdir(backup_dir, 0o755, True) shutil.copy2(system_conf, backup_path) logger.debug(m18n.n('service_conf_file_backed_up', - conf=system_conf, backup=backup_path)) + conf=system_conf, backup=backup_path)) try: if not new_conf: os.remove(system_conf) logger.debug(m18n.n('service_conf_file_removed', - conf=system_conf)) + conf=system_conf)) else: system_dir = os.path.dirname(system_conf) if not os.path.isdir(system_dir): - filesystem.mkdir(system_dir, 0755, True) + filesystem.mkdir(system_dir, 0o755, True) shutil.copyfile(new_conf, system_conf) logger.debug(m18n.n('service_conf_file_updated', diff --git a/src/yunohost/settings.py b/src/yunohost/settings.py index c48f567ab..bbfb3ca56 100644 --- a/src/yunohost/settings.py +++ b/src/yunohost/settings.py @@ -88,12 +88,12 @@ def settings_set(key, value): if key_type == "bool": if not isinstance(value, bool): raise YunohostError('global_settings_bad_type_for_setting', setting=key, - received_type=type(value).__name__, expected_type=key_type) + received_type=type(value).__name__, expected_type=key_type) elif key_type == "int": if not isinstance(value, int) or isinstance(value, bool): if isinstance(value, str): try: - value=int(value) + value = int(value) except: raise YunohostError('global_settings_bad_type_for_setting', setting=key, @@ -101,19 +101,19 @@ def settings_set(key, value): expected_type=key_type) else: raise YunohostError('global_settings_bad_type_for_setting', setting=key, - received_type=type(value).__name__, expected_type=key_type) + received_type=type(value).__name__, expected_type=key_type) elif key_type == "string": if not isinstance(value, basestring): raise YunohostError('global_settings_bad_type_for_setting', setting=key, - received_type=type(value).__name__, expected_type=key_type) + received_type=type(value).__name__, expected_type=key_type) elif key_type == "enum": if value not in settings[key]["choices"]: raise YunohostError('global_settings_bad_choice_for_enum', setting=key, - received_type=type(value).__name__, - expected_type=", ".join(settings[key]["choices"])) + received_type=type(value).__name__, + expected_type=", ".join(settings[key]["choices"])) else: raise YunohostError('global_settings_unknown_type', setting=key, - unknown_type=key_type) + unknown_type=key_type) settings[key]["value"] = value diff --git a/src/yunohost/ssh.py b/src/yunohost/ssh.py index a9e5babf7..7c8c85b35 100644 --- a/src/yunohost/ssh.py +++ b/src/yunohost/ssh.py @@ -98,7 +98,7 @@ def user_ssh_add_key(auth, username, key, comment): # create empty file to set good permissions write_to_file(authorized_keys_file, "") chown(authorized_keys_file, uid=user["uid"][0]) - chmod(authorized_keys_file, 0600) + chmod(authorized_keys_file, 0o600) authorized_keys_content = read_file(authorized_keys_file) diff --git a/src/yunohost/tests/conftest.py b/src/yunohost/tests/conftest.py index 6958ae679..a2dc585bd 100644 --- a/src/yunohost/tests/conftest.py +++ b/src/yunohost/tests/conftest.py @@ -7,12 +7,14 @@ sys.path.append("..") def pytest_addoption(parser): parser.addoption("--yunodebug", action="store_true", default=False) -############################################################################### -# Tweak translator to raise exceptions if string keys are not defined # -############################################################################### +# +# Tweak translator to raise exceptions if string keys are not defined # +# old_translate = moulinette.core.Translator.translate + + def new_translate(self, key, *args, **kwargs): if key not in self._translations[self.default_locale].keys(): @@ -21,14 +23,15 @@ def new_translate(self, key, *args, **kwargs): return old_translate(self, key, *args, **kwargs) moulinette.core.Translator.translate = new_translate + def new_m18nn(self, key, *args, **kwargs): return self._namespaces[self._current_namespace].translate(key, *args, **kwargs) moulinette.core.Moulinette18n.n = new_m18nn -############################################################################### -# Init the moulinette to have the cli loggers stuff # -############################################################################### +# +# Init the moulinette to have the cli loggers stuff # +# def pytest_cmdline_main(config): diff --git a/src/yunohost/tests/test_appslist.py b/src/yunohost/tests/test_appslist.py index 7a6f27d6c..817807ed9 100644 --- a/src/yunohost/tests/test_appslist.py +++ b/src/yunohost/tests/test_appslist.py @@ -17,7 +17,7 @@ APPSLISTS_JSON = '/etc/yunohost/appslists.json' def setup_function(function): # Clear all appslist - files = glob.glob(REPO_PATH+"/*") + files = glob.glob(REPO_PATH + "/*") for f in files: os.remove(f) @@ -42,9 +42,9 @@ def cron_job_is_there(): return r == 0 -############################################################################### -# Test listing of appslists and registering of appslists # -############################################################################### +# +# Test listing of appslists and registering of appslists # +# def test_appslist_list_empty(): @@ -103,9 +103,9 @@ def test_appslist_list_register_conflict_url(): assert "plopette" not in appslist_dict.keys() -############################################################################### -# Test fetching of appslists # -############################################################################### +# +# Test fetching of appslists # +# def test_appslist_fetch(): @@ -244,9 +244,9 @@ def test_appslist_fetch_timeout(): app_fetchlist() -############################################################################### -# Test remove of appslist # -############################################################################### +# +# Test remove of appslist # +# def test_appslist_remove(): @@ -274,9 +274,9 @@ def test_appslist_remove_unknown(): app_removelist("dummy") -############################################################################### -# Test migration from legacy appslist system # -############################################################################### +# +# Test migration from legacy appslist system # +# def add_legacy_cron(name, url): diff --git a/src/yunohost/tests/test_appurl.py b/src/yunohost/tests/test_appurl.py index 85f290b5d..d9d5fa7ab 100644 --- a/src/yunohost/tests/test_appurl.py +++ b/src/yunohost/tests/test_appurl.py @@ -22,6 +22,7 @@ def setup_function(function): except: pass + def teardown_function(function): try: @@ -50,18 +51,18 @@ def test_urlavailable(): def test_registerurl(): app_install(auth, "./tests/apps/register_url_app_ynh", - args="domain=%s&path=%s" % (maindomain, "/urlregisterapp")) + args="domain=%s&path=%s" % (maindomain, "/urlregisterapp")) assert not domain_url_available(auth, maindomain, "/urlregisterapp") # Try installing at same location with pytest.raises(YunohostError): app_install(auth, "./tests/apps/register_url_app_ynh", - args="domain=%s&path=%s" % (maindomain, "/urlregisterapp")) + args="domain=%s&path=%s" % (maindomain, "/urlregisterapp")) def test_registerurl_baddomain(): with pytest.raises(YunohostError): app_install(auth, "./tests/apps/register_url_app_ynh", - args="domain=%s&path=%s" % ("yolo.swag", "/urlregisterapp")) + args="domain=%s&path=%s" % ("yolo.swag", "/urlregisterapp")) diff --git a/src/yunohost/tests/test_backuprestore.py b/src/yunohost/tests/test_backuprestore.py index a2356318d..af8538dae 100644 --- a/src/yunohost/tests/test_backuprestore.py +++ b/src/yunohost/tests/test_backuprestore.py @@ -22,6 +22,7 @@ AUTH_IDENTIFIER = ('ldap', 'ldap-anonymous') AUTH_PARAMETERS = {'uri': 'ldap://localhost:389', 'base_dn': 'dc=yunohost,dc=org'} auth = None + def setup_function(function): global maindomain @@ -87,9 +88,9 @@ def teardown_function(function): shutil.rmtree("/opt/test_backup_output_directory") -############################################################################### -# Helpers # -############################################################################### +# +# Helpers # +# def app_is_installed(app): @@ -111,6 +112,7 @@ def backup_test_dependencies_are_met(): return True + def tmp_backup_directory_is_empty(): if not os.path.exists("/home/yunohost.backup/tmp/"): @@ -118,6 +120,7 @@ def tmp_backup_directory_is_empty(): else: return len(os.listdir('/home/yunohost.backup/tmp/')) == 0 + def clean_tmp_backup_directory(): if tmp_backup_directory_is_empty(): @@ -125,10 +128,10 @@ def clean_tmp_backup_directory(): mount_lines = subprocess.check_output("mount").split("\n") - points_to_umount = [ line.split(" ")[2] - for line in mount_lines - if len(line) >= 3 - and line.split(" ")[2].startswith("/home/yunohost.backup/tmp") ] + points_to_umount = [line.split(" ")[2] + for line in mount_lines + if len(line) >= 3 + and line.split(" ")[2].startswith("/home/yunohost.backup/tmp")] for point in reversed(points_to_umount): os.system("umount %s" % point) @@ -138,6 +141,7 @@ def clean_tmp_backup_directory(): shutil.rmtree("/home/yunohost.backup/tmp/") + def reset_ssowat_conf(): # Make sure we have a ssowat @@ -191,9 +195,10 @@ def add_archive_system_from_2p4(): os.system("cp ./tests/apps/backup_system_from_2p4/backup.tar.gz \ /home/yunohost.backup/archives/backup_system_from_2p4.tar.gz") -############################################################################### -# System backup # -############################################################################### +# +# System backup # +# + def test_backup_only_ldap(): @@ -220,9 +225,10 @@ def test_backup_system_part_that_does_not_exists(mocker): m18n.n.assert_any_call('backup_hook_unknown', hook="yolol") m18n.n.assert_any_call('backup_nothings_done') -############################################################################### -# System backup and restore # -############################################################################### +# +# System backup and restore # +# + def test_backup_and_restore_all_sys(): @@ -250,9 +256,9 @@ def test_backup_and_restore_all_sys(): assert os.path.exists("/etc/ssowat/conf.json") -############################################################################### -# System restore from 2.4 # -############################################################################### +# +# System restore from 2.4 # +# @pytest.mark.with_system_archive_from_2p4 def test_restore_system_from_Ynh2p4(monkeypatch, mocker): @@ -265,19 +271,20 @@ def test_restore_system_from_Ynh2p4(monkeypatch, mocker): # Restore system archive from 2.4 try: backup_restore(auth, name=backup_list()["archives"][1], - system=[], - apps=None, - force=True) + system=[], + apps=None, + force=True) finally: # Restore system as it was backup_restore(auth, name=backup_list()["archives"][0], - system=[], - apps=None, - force=True) + system=[], + apps=None, + force=True) + +# +# App backup # +# -############################################################################### -# App backup # -############################################################################### @pytest.mark.with_backup_recommended_app_installed def test_backup_script_failure_handling(monkeypatch, mocker): @@ -300,6 +307,7 @@ def test_backup_script_failure_handling(monkeypatch, mocker): m18n.n.assert_any_call('backup_app_failed', app='backup_recommended_app') + @pytest.mark.with_backup_recommended_app_installed def test_backup_not_enough_free_space(monkeypatch, mocker): @@ -385,6 +393,7 @@ def test_backup_with_different_output_directory(): assert len(archives_info["system"].keys()) == 1 assert "conf_ssh" in archives_info["system"].keys() + @pytest.mark.clean_opt_dir def test_backup_with_no_compress(): # Create the backup @@ -396,15 +405,15 @@ def test_backup_with_no_compress(): assert os.path.exists("/opt/test_backup_output_directory/info.json") -############################################################################### -# App restore # -############################################################################### +# +# App restore # +# @pytest.mark.with_wordpress_archive_from_2p4 def test_restore_app_wordpress_from_Ynh2p4(): backup_restore(auth, system=None, name=backup_list()["archives"][0], - apps=["wordpress"]) + apps=["wordpress"]) @pytest.mark.with_wordpress_archive_from_2p4 @@ -422,7 +431,7 @@ def test_restore_app_script_failure_handling(monkeypatch, mocker): with pytest.raises(YunohostError): backup_restore(auth, system=None, name=backup_list()["archives"][0], - apps=["wordpress"]) + apps=["wordpress"]) m18n.n.assert_any_call('restore_app_failed', app='wordpress') m18n.n.assert_any_call('restore_nothings_done') @@ -443,12 +452,12 @@ def test_restore_app_not_enough_free_space(monkeypatch, mocker): with pytest.raises(YunohostError): backup_restore(auth, system=None, name=backup_list()["archives"][0], - apps=["wordpress"]) + apps=["wordpress"]) m18n.n.assert_any_call('restore_not_enough_disk_space', - free_space=0, - margin=ANY, - needed_space=ANY) + free_space=0, + margin=ANY, + needed_space=ANY) assert not _is_installed("wordpress") @@ -462,7 +471,7 @@ def test_restore_app_not_in_backup(mocker): with pytest.raises(YunohostError): backup_restore(auth, system=None, name=backup_list()["archives"][0], - apps=["yoloswag"]) + apps=["yoloswag"]) m18n.n.assert_any_call('backup_archive_app_not_found', app="yoloswag") assert not _is_installed("wordpress") @@ -475,14 +484,14 @@ def test_restore_app_already_installed(mocker): assert not _is_installed("wordpress") backup_restore(auth, system=None, name=backup_list()["archives"][0], - apps=["wordpress"]) + apps=["wordpress"]) assert _is_installed("wordpress") mocker.spy(m18n, "n") with pytest.raises(YunohostError): backup_restore(auth, system=None, name=backup_list()["archives"][0], - apps=["wordpress"]) + apps=["wordpress"]) m18n.n.assert_any_call('restore_already_installed_app', app="wordpress") m18n.n.assert_any_call('restore_nothings_done') @@ -531,9 +540,10 @@ def _test_backup_and_restore_app(app): assert app_is_installed(app) -############################################################################### -# Some edge cases # -############################################################################### +# +# Some edge cases # +# + def test_restore_archive_with_no_json(mocker): @@ -555,10 +565,9 @@ def test_backup_binds_are_readonly(monkeypatch): self.manager = backup_manager self._organize_files() - confssh = os.path.join(self.work_dir, "conf/ssh") output = subprocess.check_output("touch %s/test 2>&1 || true" % confssh, - shell=True, env={'LANG' : 'en_US.UTF-8'}) + shell=True, env={'LANG': 'en_US.UTF-8'}) assert "Read-only file system" in output @@ -568,7 +577,7 @@ def test_backup_binds_are_readonly(monkeypatch): self.clean() monkeypatch.setattr("yunohost.backup.BackupMethod.mount_and_backup", - custom_mount_and_backup) + custom_mount_and_backup) # Create the backup backup_create(system=[]) diff --git a/src/yunohost/tests/test_changeurl.py b/src/yunohost/tests/test_changeurl.py index 826ec659b..4856e18c1 100644 --- a/src/yunohost/tests/test_changeurl.py +++ b/src/yunohost/tests/test_changeurl.py @@ -53,6 +53,7 @@ def test_appchangeurl(): check_changeurl_app("/newchangeurl") + def test_appchangeurl_sameurl(): install_changeurl_app("/changeurl") check_changeurl_app("/changeurl") diff --git a/src/yunohost/tests/test_settings.py b/src/yunohost/tests/test_settings.py index afb9faee9..0da12597f 100644 --- a/src/yunohost/tests/test_settings.py +++ b/src/yunohost/tests/test_settings.py @@ -18,7 +18,8 @@ def teardown_function(function): def test_settings_get_bool(): - assert settings_get("example.bool") == True + assert settings_get("example.bool") + def test_settings_get_full_bool(): assert settings_get("example.bool", True) == {"type": "bool", "value": True, "default": True, "description": "Example boolean option"} @@ -27,6 +28,7 @@ def test_settings_get_full_bool(): def test_settings_get_int(): assert settings_get("example.int") == 42 + def test_settings_get_full_int(): assert settings_get("example.int", True) == {"type": "int", "value": 42, "default": 42, "description": "Example int option"} @@ -34,6 +36,7 @@ def test_settings_get_full_int(): def test_settings_get_string(): assert settings_get("example.string") == "yolo swag" + def test_settings_get_full_string(): assert settings_get("example.string", True) == {"type": "string", "value": "yolo swag", "default": "yolo swag", "description": "Example string option"} @@ -41,6 +44,7 @@ def test_settings_get_full_string(): def test_settings_get_enum(): assert settings_get("example.enum") == "a" + def test_settings_get_full_enum(): assert settings_get("example.enum", True) == {"type": "enum", "value": "a", "default": "a", "description": "Example enum option", "choices": ["a", "b", "c"]} @@ -152,7 +156,6 @@ def test_reset_all_backup(): assert settings_after_modification == json.load(open(old_settings_backup_path, "r")) - def test_unknown_keys(): unknown_settings_path = SETTINGS_PATH_OTHER_LOCATION % "unknown" unknown_setting = { diff --git a/src/yunohost/tools.py b/src/yunohost/tools.py index 58bdd23d3..43190e5b8 100644 --- a/src/yunohost/tools.py +++ b/src/yunohost/tools.py @@ -136,7 +136,7 @@ def tools_adminpw(auth, new_password, check_strength=True): new_hash = _hash_user_password(new_password) try: - auth.update("cn=admin", { "userPassword": new_hash, }) + auth.update("cn=admin", {"userPassword": new_hash, }) except: logger.exception('unable to change admin password') raise YunohostError('admin_password_change_failed') @@ -265,7 +265,7 @@ def _is_inside_container(): stderr=subprocess.STDOUT) out, _ = p.communicate() - container = ['lxc','lxd','docker'] + container = ['lxc', 'lxd', 'docker'] return out.split()[0] in container @@ -323,7 +323,6 @@ def tools_postinstall(operation_logger, domain, password, ignore_dyndns=False, else: dyndns = False - operation_logger.start() logger.info(m18n.n('yunohost_installing')) @@ -539,7 +538,7 @@ def tools_upgrade(operation_logger, auth, ignore_apps=False, ignore_packages=Fal # If API call if is_api: critical_packages = ("moulinette", "yunohost", - "yunohost-admin", "ssowat", "python") + "yunohost-admin", "ssowat", "python") critical_upgrades = set() for pkg in cache.get_changes(): @@ -575,7 +574,6 @@ def tools_upgrade(operation_logger, auth, ignore_apps=False, ignore_packages=Fal else: logger.info(m18n.n('packages_no_upgrade')) - if not ignore_apps: try: app_upgrade(auth) @@ -719,7 +717,7 @@ def _check_if_vulnerable_to_meltdown(): try: call = subprocess.Popen("bash %s --batch json --variant 3" % SCRIPT_PATH, shell=True, - stdout=subprocess.PIPE, + stdout=subprocess.PIPE, stderr=subprocess.STDOUT) output, _ = call.communicate() @@ -815,12 +813,12 @@ def tools_migrations_list(pending=False, done=False): migrations = [m for m in migrations if m.number > last_migration] # Reduce to dictionnaries - migrations = [{ "id": migration.id, - "number": migration.number, - "name": migration.name, - "mode": migration.mode, - "description": migration.description, - "disclaimer": migration.disclaimer } for migration in migrations ] + migrations = [{"id": migration.id, + "number": migration.number, + "name": migration.name, + "mode": migration.mode, + "description": migration.description, + "disclaimer": migration.disclaimer} for migration in migrations] return {"migrations": migrations} @@ -914,7 +912,7 @@ def tools_migrations_migrate(target=None, skip=False, auto=False, accept_disclai accept_disclaimer = False # Start register change on system - operation_logger= OperationLogger('tools_migrations_migrate_' + mode) + operation_logger = OperationLogger('tools_migrations_migrate_' + mode) operation_logger.start() if not skip: @@ -934,9 +932,9 @@ def tools_migrations_migrate(target=None, skip=False, auto=False, accept_disclai # migration failed, let's stop here but still update state because # we managed to run the previous ones msg = m18n.n('migrations_migration_has_failed', - exception=e, - number=migration.number, - name=migration.name) + exception=e, + number=migration.number, + name=migration.name) logger.error(msg, exc_info=1) operation_logger.error(msg) break @@ -967,6 +965,7 @@ def tools_migrations_migrate(target=None, skip=False, auto=False, accept_disclai write_to_json(MIGRATIONS_STATE_PATH, state) + def tools_migrations_state(): """ Show current migration state @@ -1009,7 +1008,7 @@ def _get_migrations_list(): migrations = [] try: - import data_migrations + from . import data_migrations except ImportError: # not data migrations present, return empty list return migrations @@ -1032,7 +1031,7 @@ def _get_migration_by_name(migration_name): """ try: - import data_migrations + from . import data_migrations except ImportError: raise AssertionError("Unable to find migration with name %s" % migration_name) @@ -1051,7 +1050,7 @@ def _load_migration(migration_file): number, name = migration_id.split("_", 1) logger.debug(m18n.n('migrations_loading_migration', - number=number, name=name)) + number=number, name=name)) try: # this is python builtin method to import a module using a name, we @@ -1064,7 +1063,8 @@ def _load_migration(migration_file): traceback.print_exc() raise YunohostError('migrations_error_failed_to_load_migration', - number=number, name=name) + number=number, name=name) + def _skip_all_migrations(): """ @@ -1115,4 +1115,3 @@ class Migration(object): @property def description(self): return m18n.n("migration_description_%s" % self.id) - diff --git a/src/yunohost/user.py b/src/yunohost/user.py index ea8dc30a9..d0c432c56 100644 --- a/src/yunohost/user.py +++ b/src/yunohost/user.py @@ -40,6 +40,7 @@ from yunohost.log import is_unit_operation logger = getActionLogger('yunohost.user') + def user_list(auth, fields=None): """ List users @@ -98,7 +99,7 @@ def user_list(auth, fields=None): @is_unit_operation([('username', 'user')]) def user_create(operation_logger, auth, username, firstname, lastname, mail, password, - mailbox_quota="0"): + mailbox_quota="0"): """ Create user @@ -262,8 +263,8 @@ def user_delete(operation_logger, auth, username, purge=False): @is_unit_operation([('username', 'user')], exclude=['auth', 'change_password']) def user_update(operation_logger, auth, username, firstname=None, lastname=None, mail=None, - change_password=None, add_mailforward=None, remove_mailforward=None, - add_mailalias=None, remove_mailalias=None, mailbox_quota=None): + change_password=None, add_mailforward=None, remove_mailforward=None, + add_mailalias=None, remove_mailalias=None, mailbox_quota=None): """ Update user informations @@ -466,18 +467,23 @@ def user_info(auth, username): # import yunohost.ssh + def user_ssh_allow(auth, username): return yunohost.ssh.user_ssh_allow(auth, username) + def user_ssh_disallow(auth, username): return yunohost.ssh.user_ssh_disallow(auth, username) + def user_ssh_list_keys(auth, username): return yunohost.ssh.user_ssh_list_keys(auth, username) + def user_ssh_add_key(auth, username, key, comment): return yunohost.ssh.user_ssh_add_key(auth, username, key, comment) + def user_ssh_remove_key(auth, username, key): return yunohost.ssh.user_ssh_remove_key(auth, username, key) @@ -485,6 +491,7 @@ def user_ssh_remove_key(auth, username, key): # End SSH subcategory # + def _convertSize(num, suffix=''): for unit in ['K', 'M', 'G', 'T', 'P', 'E', 'Z']: if abs(num) < 1024.0: @@ -520,6 +527,3 @@ def _hash_user_password(password): salt = '$6$' + salt + '$' return '{CRYPT}' + crypt.crypt(str(password), salt) - - - diff --git a/src/yunohost/utils/error.py b/src/yunohost/utils/error.py index 7c00ee5a4..1d5b05a6f 100644 --- a/src/yunohost/utils/error.py +++ b/src/yunohost/utils/error.py @@ -22,12 +22,14 @@ from moulinette.core import MoulinetteError from moulinette import m18n + class YunohostError(MoulinetteError): + """Yunohost base exception""" + def __init__(self, key, __raw_msg__=False, *args, **kwargs): if __raw_msg__: msg = key else: msg = m18n.n(key, *args, **kwargs) super(YunohostError, self).__init__(msg, __raw_msg__=True) - diff --git a/src/yunohost/utils/filesystem.py b/src/yunohost/utils/filesystem.py index 3f026f980..04d7d3906 100644 --- a/src/yunohost/utils/filesystem.py +++ b/src/yunohost/utils/filesystem.py @@ -20,10 +20,12 @@ """ import os + def free_space_in_directory(dirpath): stat = os.statvfs(dirpath) return stat.f_frsize * stat.f_bavail + def space_used_by_directory(dirpath): stat = os.statvfs(dirpath) return stat.f_frsize * stat.f_blocks diff --git a/src/yunohost/utils/network.py b/src/yunohost/utils/network.py index a9602ff56..1f82a87b0 100644 --- a/src/yunohost/utils/network.py +++ b/src/yunohost/utils/network.py @@ -71,7 +71,7 @@ def get_gateway(): return addr.popitem()[1] if len(addr) == 1 else None -############################################################################### +# def _extract_inet(string, skip_netmask=False, skip_loopback=True): diff --git a/src/yunohost/utils/packages.py b/src/yunohost/utils/packages.py index 3917ef563..5ef97618b 100644 --- a/src/yunohost/utils/packages.py +++ b/src/yunohost/utils/packages.py @@ -33,6 +33,7 @@ logger = logging.getLogger('yunohost.utils.packages') # Exceptions ----------------------------------------------------------------- class PackageException(Exception): + """Base exception related to a package Represent an exception related to the package named `pkgname`. If no @@ -50,16 +51,19 @@ class PackageException(Exception): class UnknownPackage(PackageException): + """The package is not found in the cache.""" message_key = 'package_unknown' class UninstalledPackage(PackageException): + """The package is not installed.""" message_key = 'package_not_installed' class InvalidSpecifier(ValueError): + """An invalid specifier was found.""" @@ -68,6 +72,7 @@ class InvalidSpecifier(ValueError): # See: https://github.com/pypa/packaging class Specifier(object): + """Unique package version specifier Restrict a package version according to the `spec`. It must be a string @@ -257,6 +262,7 @@ class Specifier(object): class SpecifierSet(object): + """A set of package version specifiers Combine several Specifier separated by a comma. It allows to restrict diff --git a/src/yunohost/utils/password.py b/src/yunohost/utils/password.py index 9cee56d53..b4f7025f7 100644 --- a/src/yunohost/utils/password.py +++ b/src/yunohost/utils/password.py @@ -38,9 +38,11 @@ STRENGTH_LEVELS = [ (12, 1, 1, 1, 1), ] + def assert_password_is_strong_enough(profile, password): PasswordValidator(profile).validate(password) + class PasswordValidator(object): def __init__(self, profile): @@ -157,7 +159,7 @@ class PasswordValidator(object): # and the strength of the password (e.g. [11, 2, 7, 2, 0]) # and compare the values 1-by-1. # If one False is found, the password does not satisfy the level - if False in [s>=c for s, c in zip(strength, level_criterias)]: + if False in [s >= c for s, c in zip(strength, level_criterias)]: break # Otherwise, the strength of the password is at least of the current level. strength_level = level + 1 @@ -186,7 +188,7 @@ if __name__ == '__main__': if len(sys.argv) < 2: import getpass pwd = getpass.getpass("") - #print("usage: password.py PASSWORD") + # print("usage: password.py PASSWORD") else: pwd = sys.argv[1] status, msg = PasswordValidator('user').validation_summary(pwd) diff --git a/src/yunohost/utils/yunopaste.py b/src/yunohost/utils/yunopaste.py index 436f94911..3d80ddd4e 100644 --- a/src/yunohost/utils/yunopaste.py +++ b/src/yunohost/utils/yunopaste.py @@ -5,6 +5,7 @@ import json from yunohost.utils.error import YunohostError + def yunopaste(data): paste_server = "https://paste.yunohost.org"