From e0fa223d3d3f05f4920f22de245ed09d41c6ae81 Mon Sep 17 00:00:00 2001 From: ljf Date: Wed, 14 Sep 2022 18:38:11 +0200 Subject: [PATCH] [fix] Pep8 and syntax --- src/backup.py | 2 +- src/repositories/borg.py | 22 +++++++------- src/repositories/hook.py | 42 ++++++++++++++++++++++---- src/repositories/tar.py | 1 - src/repository.py | 64 ++++++++++++++++++---------------------- src/utils/config.py | 13 ++++---- 6 files changed, 83 insertions(+), 61 deletions(-) diff --git a/src/backup.py b/src/backup.py index 80dabbc2c..8c4838f5e 100644 --- a/src/backup.py +++ b/src/backup.py @@ -31,7 +31,7 @@ import subprocess import csv import tempfile import re -import urllib +import urllib.parse from datetime import datetime from packaging import version diff --git a/src/repositories/borg.py b/src/repositories/borg.py index a9b1d4654..3fd90984e 100644 --- a/src/repositories/borg.py +++ b/src/repositories/borg.py @@ -22,13 +22,13 @@ import os import subprocess import json -from datetime import datetime +from datetime import datetime, timedelta from moulinette.utils.log import getActionLogger -from moulinette import m18n from yunohost.utils.error import YunohostError -from yunohost.repository import LocalBackupRepository +from yunohost.utils.network import shf_request +from yunohost.repository import LocalBackupRepository, BackupArchive logger = getActionLogger("yunohost.repository") @@ -90,14 +90,14 @@ class BorgBackupRepository(LocalBackupRepository): response = shf_request( domain=self.domain, service=services[self.method], - shf_id=values.pop('shf_id', None), + shf_id=self.values.pop('shf_id', None), data={ 'origin': self.domain, 'public_key': self.public_key, 'quota': self.quota, 'alert': self.alert, 'alert_delay': self.alert_delay, - #password: "XXXXXXXX", + # password: "XXXXXXXX", } ) self.new_values['shf_id'] = response['id'] @@ -123,13 +123,13 @@ class BorgBackupRepository(LocalBackupRepository): def purge(self): if self.is_shf: - response = shf_request( + shf_request( domain=self.domain, service="borgbackup", - shf_id=values.pop('shf_id', None), + shf_id=self.values.pop('shf_id', None), data={ 'origin': self.domain, - #password: "XXXXXXXX", + # password: "XXXXXXXX", } ) else: @@ -179,7 +179,7 @@ class BorgBackupRepository(LocalBackupRepository): continue period = timedelta(**{unit: 1}) periods += set([(now - period * i, now - period * (i - 1)) - for i in range(qty)]) + for i in range(qty)]) # Delete unneeded archive for created_at in sorted(archives, reverse=True): @@ -194,7 +194,7 @@ class BorgBackupRepository(LocalBackupRepository): class BorgBackupArchive(BackupArchive): - """ Backup prepared files with borg """ + """ Backup prepared files with borg """ def backup(self): cmd = ['borg', 'create', self.archive_path, './'] @@ -244,5 +244,3 @@ class BorgBackupArchive(BackupArchive): # FIXME How to be sure the place where we mount is secure ? cmd = ['borg', 'mount', self.archive_path, path] self.repo._call('mount_archive', cmd) - - diff --git a/src/repositories/hook.py b/src/repositories/hook.py index 817519162..7641b05f9 100644 --- a/src/repositories/hook.py +++ b/src/repositories/hook.py @@ -1,3 +1,32 @@ +# -*- coding: utf-8 -*- + +""" License + + Copyright (C) 2013 Yunohost + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program; if not, see http://www.gnu.org/licenses + +""" +from moulinette import m18n +from moulinette.utils.log import getActionLogger +from moulinette.utils.filesystem import rm + +from yunohost.hook import hook_callback +from yunohost.utils.error import YunohostError +from yunohost.repository import BackupRepository, BackupArchive +logger = getActionLogger("yunohost.repository") + class HookBackupRepository(BackupRepository): method_name = "hook" @@ -13,7 +42,7 @@ class HookBackupRepository(BackupRepository): def remove(self, purge=False): if self.__class__ == BackupRepository: - raise NotImplementedError() # purge + raise NotImplementedError() # purge rm(self.save_path, force=True) logger.success(m18n.n("repository_removed", repository=self.shortname)) @@ -24,8 +53,8 @@ class HookBackupRepository(BackupRepository): def info(self, space_used=False): result = super().get(mode="export") - if self.__class__ == BackupRepository and space_used == True: - raise NotImplementedError() # purge + if self.__class__ == BackupRepository and space_used is True: + raise NotImplementedError() # purge return {self.shortname: result} @@ -44,7 +73,7 @@ class HookBackupArchive(BackupArchive): """ self._call('backup', self.work_dir, self.name, self.repo.location, self.manager.size, - self.manager.description) + self.manager.description) def restore(self): raise NotImplementedError() @@ -64,7 +93,7 @@ class HookBackupArchive(BackupArchive): return result def info(self): - raise NotImplementedError() #compute_space_used + raise NotImplementedError() # compute_space_used """ Return json string of the info.json file Exceptions: @@ -82,7 +111,7 @@ class HookBackupArchive(BackupArchive): """ super().mount() self._call('mount', self.work_dir, self.name, self.repo.location, self.manager.size, - self.manager.description) + self.manager.description) def extract(self): raise NotImplementedError() @@ -97,6 +126,7 @@ class HookBackupArchive(BackupArchive): except YunohostError: return False return True + def _call(self, *args): """ Call a submethod of backup method hook diff --git a/src/repositories/tar.py b/src/repositories/tar.py index d49643ed7..9d0fe539d 100644 --- a/src/repositories/tar.py +++ b/src/repositories/tar.py @@ -235,4 +235,3 @@ class TarBackupArchive: if not os.path.exists(archive_file): raise YunohostError('backup_archive_broken_link', path=archive_file) - diff --git a/src/repository.py b/src/repository.py index 0f40cc4d7..a79bffab5 100644 --- a/src/repository.py +++ b/src/repository.py @@ -23,25 +23,26 @@ Manage backup repositories """ +import json import os import re -import time +import shutil import subprocess -import re -import urllib.parse +import tarfile +import tempfile from moulinette import Moulinette, m18n from moulinette.core import MoulinetteError from moulinette.utils.log import getActionLogger -from moulinette.utils.filesystem import read_file, read_yaml, write_to_json, rm, mkdir, chmod, chown -from moulinette.utils.network import download_text, download_json +from moulinette.utils.filesystem import read_file, rm, mkdir +from moulinette.utils.network import download_text +from datetime import timedelta, datetime -from yunohost.utils.config import ConfigPanel, Question -from yunohost.utils.error import YunohostError -from yunohost.utils.filesystem import space_used_in_directory, disk_usage, binary_to_human -from yunohost.utils.network import get_ssh_public_key, shf_request, SHF_BASE_URL -from yunohost.log import OperationLogger, is_unit_operation +from yunohost.utils.config import ConfigPanel +from yunohost.utils.error import YunohostError, YunohostValidationError +from yunohost.utils.filesystem import disk_usage, binary_to_human, free_space_in_directory +from yunohost.utils.network import get_ssh_public_key, SHF_BASE_URL logger = getActionLogger('yunohost.repository') REPOSITORIES_DIR = '/etc/yunohost/repositories' @@ -104,12 +105,11 @@ class BackupRepository(ConfigPanel): for repo in repositories: try: repositories[repo] = BackupRepository(repo).info(space_used) - except Exception as e: + except Exception: logger.error(f"Unable to open repository {repo}") return repositories - # ================================================= # Config Panel Hooks # ================================================= @@ -117,19 +117,18 @@ class BackupRepository(ConfigPanel): def post_ask__domain(self, question): """ Detect if the domain support Self-Hosting Federation protocol """ - #import requests + # import requests # FIXME What if remote server is self-signed ? # FIXME What if remote server is unreachable temporarily ? url = SHF_BASE_URL.format(domain=question.value) + "/" try: - #r = requests.get(url, timeout=10) + # r = requests.get(url, timeout=10) download_text(url, timeout=10) - except MoulinetteError as e: + except MoulinetteError: logger.debug("SHF not running") - return { 'is_shf': False } + return {'is_shf': False} logger.debug("SHF running") - return { 'is_shf': True } - + return {'is_shf': True} # ================================================= # Config Panel Override @@ -156,7 +155,7 @@ class BackupRepository(ConfigPanel): def _parse_pre_answered(self, *args): super()._parse_pre_answered(*args) - if 'location' in self.args: + if 'location' in self.args: self.args.update(BackupRepository.split_location(self.args['location'])) if 'domain' in self.args: self.args['is_remote'] = bool(self.args['domain']) @@ -179,7 +178,6 @@ class BackupRepository(ConfigPanel): self.new_values.pop(prop, None) super()._apply() - # ================================================= # BackupMethod encapsulation # ================================================= @@ -237,7 +235,7 @@ class BackupRepository(ConfigPanel): def info(self, space_used=False): result = super().get(mode="export") - if self.__class__ == BackupRepository and space_used == True: + if self.__class__ == BackupRepository and space_used is True: result["space_used"] = self.compute_space_used() return {self.shortname: result} @@ -245,7 +243,7 @@ class BackupRepository(ConfigPanel): def list(self, with_info): archives = self.list_archive_name() if with_info: - d = OrderedDict() + d = {} for archive in archives: try: d[archive] = BackupArchive(repo=self, name=archive).info() @@ -289,7 +287,7 @@ class BackupRepository(ConfigPanel): continue period = timedelta(**{unit: 1}) periods += set([(now - period * i, now - period * (i - 1)) - for i in range(qty)]) + for i in range(qty)]) # Delete unneeded archive for created_at in sorted(archives, reverse=True): @@ -412,7 +410,7 @@ class BackupArchive: raise YunohostError( "backup_archive_cant_retrieve_info_json", archive=self.archive_path ) - extract_paths = [] + if f"{leading_dot}backup.csv" in files_in_archive: yield f"{leading_dot}backup.csv" else: @@ -447,7 +445,7 @@ class BackupArchive: if not os.path.lexists(archive_file): archive_file += ".gz" if not os.path.lexists(archive_file): - raise YunohostValidationError("backup_archive_name_unknown", name=name) + raise YunohostValidationError("backup_archive_name_unknown", name=self.name) # If symlink, retrieve the real path if os.path.islink(archive_file): @@ -491,7 +489,7 @@ class BackupArchive: raise YunohostError('backup_info_json_not_implemented') try: info = json.load(info_json) - except: + except Exception: logger.debug("unable to load info json", exc_info=1) raise YunohostError('backup_invalid_archive') @@ -558,7 +556,8 @@ class BackupArchive: raise YunohostError("backup_cleaning_failed") if self.manager.is_tmp_work_dir: - filesystem.rm(self.work_dir, True, True) + rm(self.work_dir, True, True) + def _organize_files(self): """ Mount all csv src in their related path @@ -587,11 +586,11 @@ class BackupArchive: # Be sure the parent dir of destination exists if not os.path.isdir(dest_dir): - filesystem.mkdir(dest_dir, parents=True) + mkdir(dest_dir, parents=True) # For directory, attempt to mount bind if os.path.isdir(src): - filesystem.mkdir(dest, parents=True, force=True) + mkdir(dest, parents=True, force=True) try: subprocess.check_call(["mount", "--rbind", src, dest]) @@ -688,7 +687,6 @@ class BackupArchive: if self.__class__ == BackupArchive: raise NotImplementedError() - def download(self): if self.__class__ == BackupArchive: raise NotImplementedError() @@ -712,9 +710,3 @@ class BackupArchive: def mount(self): if self.__class__ == BackupArchive: raise NotImplementedError() - - - - - - diff --git a/src/utils/config.py b/src/utils/config.py index c92de7f36..6f91c5a39 100644 --- a/src/utils/config.py +++ b/src/utils/config.py @@ -49,10 +49,13 @@ from yunohost.log import OperationLogger logger = getActionLogger("yunohost.config") CONFIG_PANEL_VERSION_SUPPORTED = 1.0 -# Those js-like evaluate functions are used to eval safely visible attributes -# The goal is to evaluate in the same way than js simple-evaluate -# https://github.com/shepherdwind/simple-evaluate + def evaluate_simple_ast(node, context=None): + """ + Those js-like evaluate functions are used to eval safely visible attributes + The goal is to evaluate in the same way than js simple-evaluate + https://github.com/shepherdwind/simple-evaluate + """ if context is None: context = {} @@ -1130,9 +1133,9 @@ class DomainQuestion(Question): @staticmethod def normalize(value, option={}): if value.startswith("https://"): - value = value[len("https://") :] + value = value[len("https://"):] elif value.startswith("http://"): - value = value[len("http://") :] + value = value[len("http://"):] # Remove trailing slashes value = value.rstrip("/").lower()