diff --git a/docs/conf.py b/docs/conf.py index 35746dd77..a4b1caf2f 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -40,7 +40,7 @@ # General information about the project. project = 'Borg - Deduplicating Archiver' -copyright = u'2010-2014 Jonas Borgström, 2015-2022 The Borg Collective (see AUTHORS file)' +copyright = '2010-2014 Jonas Borgström, 2015-2022 The Borg Collective (see AUTHORS file)' # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the diff --git a/scripts/glibc_check.py b/scripts/glibc_check.py index 44fd25cd1..5f8344960 100755 --- a/scripts/glibc_check.py +++ b/scripts/glibc_check.py @@ -35,12 +35,12 @@ def main(): output = subprocess.check_output(objdump % filename, shell=True, stderr=subprocess.STDOUT) output = output.decode() - versions = set(parse_version(match.group(1)) - for match in glibc_re.finditer(output)) + versions = {parse_version(match.group(1)) + for match in glibc_re.finditer(output)} requires_glibc = max(versions) overall_versions.add(requires_glibc) if verbose: - print("%s %s" % (filename, format_version(requires_glibc))) + print(f"{filename} {format_version(requires_glibc)}") except subprocess.CalledProcessError: if verbose: print("%s errored." % filename) diff --git a/scripts/py36-blake2.py b/scripts/py36-blake2.py index 758a4f346..fff13b588 100644 --- a/scripts/py36-blake2.py +++ b/scripts/py36-blake2.py @@ -1,4 +1,3 @@ - """ This script checks compatibility of crypto.blake2b_256 against hashlib.blake2b in CPython 3.6. """ diff --git a/setup_docs.py b/setup_docs.py index d326ec8d2..9513604bb 100644 --- a/setup_docs.py +++ b/setup_docs.py @@ -12,7 +12,7 @@ def long_desc_from_readme(): - with open('README.rst', 'r') as fd: + with open('README.rst') as fd: long_description = fd.read() # remove header, but have one \n before first headline start = long_description.find('What is BorgBackup?') @@ -33,7 +33,7 @@ def format_metavar(option): elif option.nargs is None: return option.metavar else: - raise ValueError('Can\'t format metavar %s, unknown nargs %s!' % (option.metavar, option.nargs)) + raise ValueError(f'Can\'t format metavar {option.metavar}, unknown nargs {option.nargs}!') class build_usage(Command): @@ -367,7 +367,7 @@ def generate_level(self, prefix, parser, Archiver, extra_choices=None): subparsers = [action for action in parser._actions if 'SubParsersAction' in str(action.__class__)][0] for subcommand in subparsers.choices: write('| borg', '[common options]', command, subcommand, '...') - self.see_also.setdefault(command, []).append('%s-%s' % (command, subcommand)) + self.see_also.setdefault(command, []).append(f'{command}-{subcommand}') else: if command == "borgfs": write(command, end='') diff --git a/src/borg/archive.py b/src/borg/archive.py index 1c6f1ac09..279a0e131 100644 --- a/src/borg/archive.py +++ b/src/borg/archive.py @@ -198,7 +198,7 @@ def __init__(self, op, os_error): def __str__(self): if self.op: - return '%s: %s' % (self.op, self.os_error) + return f'{self.op}: {self.os_error}' else: return str(self.os_error) @@ -464,7 +464,7 @@ def __init__(self, repository, key, manifest, name, cache=None, create=False, raise self.AlreadyExists(name) i = 0 while True: - self.checkpoint_name = '%s.checkpoint%s' % (name, i and ('.%d' % i) or '') + self.checkpoint_name = '{}.checkpoint{}'.format(name, i and ('.%d' % i) or '') if self.checkpoint_name not in manifest.archives: break i += 1 @@ -1823,7 +1823,7 @@ def replacement_chunk(size): chunks_healthy = item.chunks_healthy if has_chunks_healthy else chunks_current if has_chunks_healthy and len(chunks_current) != len(chunks_healthy): # should never happen, but there was issue #3218. - logger.warning('{}: {}: Invalid chunks_healthy metadata removed!'.format(archive_name, item.path)) + logger.warning(f'{archive_name}: {item.path}: Invalid chunks_healthy metadata removed!') del item.chunks_healthy has_chunks_healthy = False chunks_healthy = chunks_current @@ -1867,7 +1867,7 @@ def replacement_chunk(size): # if this is first repair, remember the correct chunk IDs, so we can maybe heal the file later item.chunks_healthy = item.chunks if has_chunks_healthy and chunk_list == chunks_healthy: - logger.info('{}: {}: Completely healed previously damaged file!'.format(archive_name, item.path)) + logger.info(f'{archive_name}: {item.path}: Completely healed previously damaged file!') del item.chunks_healthy item.chunks = chunk_list if 'size' in item: @@ -1902,7 +1902,7 @@ def report(msg, chunk_id, chunk_no): logger.error(msg) def list_keys_safe(keys): - return ', '.join((k.decode(errors='replace') if isinstance(k, bytes) else str(k) for k in keys)) + return ', '.join(k.decode(errors='replace') if isinstance(k, bytes) else str(k) for k in keys) def valid_item(obj): if not isinstance(obj, StableDict): @@ -1972,7 +1972,7 @@ def valid_item(obj): with cache_if_remote(self.repository) as repository: for i, info in enumerate(archive_infos): pi.show(i) - logger.info('Analyzing archive {} ({}/{})'.format(info.name, i + 1, num_archives)) + logger.info(f'Analyzing archive {info.name} ({i + 1}/{num_archives})') archive_id = info.id if archive_id not in self.chunks: logger.error('Archive metadata block is missing!') @@ -2008,7 +2008,7 @@ def orphan_chunks_check(self): unused = {id_ for id_, entry in self.chunks.iteritems() if entry.refcount == 0} orphaned = unused - self.possibly_superseded if orphaned: - logger.error('{} orphaned objects found!'.format(len(orphaned))) + logger.error(f'{len(orphaned)} orphaned objects found!') self.error_found = True if self.repair and unused: logger.info('Deleting %d orphaned and %d superseded objects...' % ( diff --git a/src/borg/archiver.py b/src/borg/archiver.py index 1302bf916..be2b4c5c4 100644 --- a/src/borg/archiver.py +++ b/src/borg/archiver.py @@ -377,7 +377,7 @@ def do_key_export(self, args, repository): else: manager.export(args.path) except IsADirectoryError: - self.print_error("'{}' must be a file, not a directory".format(args.path)) + self.print_error(f"'{args.path}' must be a file, not a directory") return EXIT_ERROR return EXIT_SUCCESS @@ -1191,7 +1191,7 @@ def _delete_archives(self, args, repository): current_archive = manifest.archives.pop(archive_name) except KeyError: self.exit_code = EXIT_WARNING - logger.warning('Archive {} not found ({}/{}).'.format(archive_name, i, len(archive_names))) + logger.warning(f'Archive {archive_name} not found ({i}/{len(archive_names)}).') else: deleted = True if self.output_list: @@ -1851,12 +1851,12 @@ def list_config(config): value = default_values.get(key) if value is None: raise Error('The repository config is missing the %s key which has no default value' % key) - print('%s = %s' % (key, value)) + print(f'{key} = {value}') for key in ['last_segment_checked', ]: value = config.get('repository', key, fallback=None) if value is None: continue - print('%s = %s' % (key, value)) + print(f'{key} = {value}') if not args.list: if args.name is None: @@ -2059,7 +2059,7 @@ def do_debug_search_repo_objs(self, args, repository): def print_finding(info, wanted, data, offset): before = data[offset - context:offset] after = data[offset + len(wanted):offset + len(wanted) + context] - print('%s: %s %s %s == %r %r %r' % (info, before.hex(), wanted.hex(), after.hex(), + print('{}: {} {} {} == {!r} {!r} {!r}'.format(info, before.hex(), wanted.hex(), after.hex(), before, wanted, after)) wanted = args.wanted @@ -5032,7 +5032,7 @@ def sig_info_handler(sig_no, stack): # pragma: no cover total = loc['st'].st_size except Exception: pos, total = 0, 0 - logger.info("{0} {1}/{2}".format(path, format_file_size(pos), format_file_size(total))) + logger.info(f"{path} {format_file_size(pos)}/{format_file_size(total)}") break if func in ('extract_item', ): # extract op path = loc['item'].path @@ -5040,7 +5040,7 @@ def sig_info_handler(sig_no, stack): # pragma: no cover pos = loc['fd'].tell() except Exception: pos = 0 - logger.info("{0} {1}/???".format(path, format_file_size(pos))) + logger.info(f"{path} {format_file_size(pos)}/???") break @@ -5078,7 +5078,7 @@ def main(): # pragma: no cover except Error as e: msg = e.get_message() tb_log_level = logging.ERROR if e.traceback else logging.DEBUG - tb = '%s\n%s' % (traceback.format_exc(), sysinfo()) + tb = f'{traceback.format_exc()}\n{sysinfo()}' # we might not have logging setup yet, so get out quickly print(msg, file=sys.stderr) if tb_log_level == logging.ERROR: @@ -5091,7 +5091,7 @@ def main(): # pragma: no cover msg = e.get_message() msgid = type(e).__qualname__ tb_log_level = logging.ERROR if e.traceback else logging.DEBUG - tb = "%s\n%s" % (traceback.format_exc(), sysinfo()) + tb = f"{traceback.format_exc()}\n{sysinfo()}" exit_code = e.exit_code except RemoteRepository.RPCError as e: important = e.exception_class not in ('LockTimeout', ) and e.traceback @@ -5108,18 +5108,18 @@ def main(): # pragma: no cover msg = 'Local Exception' msgid = 'Exception' tb_log_level = logging.ERROR - tb = '%s\n%s' % (traceback.format_exc(), sysinfo()) + tb = f'{traceback.format_exc()}\n{sysinfo()}' exit_code = EXIT_ERROR except KeyboardInterrupt: msg = 'Keyboard interrupt' tb_log_level = logging.DEBUG - tb = '%s\n%s' % (traceback.format_exc(), sysinfo()) + tb = f'{traceback.format_exc()}\n{sysinfo()}' exit_code = EXIT_SIGNAL_BASE + 2 except SigTerm: msg = 'Received SIGTERM' msgid = 'Signal.SIGTERM' tb_log_level = logging.DEBUG - tb = '%s\n%s' % (traceback.format_exc(), sysinfo()) + tb = f'{traceback.format_exc()}\n{sysinfo()}' exit_code = EXIT_SIGNAL_BASE + 15 except SigHup: msg = 'Received SIGHUP.' diff --git a/src/borg/cache.py b/src/borg/cache.py index 6f6d87514..92df82e11 100644 --- a/src/borg/cache.py +++ b/src/borg/cache.py @@ -83,7 +83,7 @@ def key_matches(self, key): if not self.known(): return False try: - with open(self.key_type_file, 'r') as fd: + with open(self.key_type_file) as fd: type = fd.read() return type == str(key.TYPE) except OSError as exc: @@ -687,13 +687,13 @@ def cached_archives(): fns = os.listdir(archive_path) # filenames with 64 hex digits == 256bit, # or compact indices which are 64 hex digits + ".compact" - return set(unhexlify(fn) for fn in fns if len(fn) == 64) | \ - set(unhexlify(fn[:64]) for fn in fns if len(fn) == 72 and fn.endswith('.compact')) + return {unhexlify(fn) for fn in fns if len(fn) == 64} | \ + {unhexlify(fn[:64]) for fn in fns if len(fn) == 72 and fn.endswith('.compact')} else: return set() def repo_archives(): - return set(info.id for info in self.manifest.archives.list()) + return {info.id for info in self.manifest.archives.list()} def cleanup_outdated(ids): for id in ids: diff --git a/src/borg/crypto/file_integrity.py b/src/borg/crypto/file_integrity.py index 84b22a7e0..87518a2a7 100644 --- a/src/borg/crypto/file_integrity.py +++ b/src/borg/crypto/file_integrity.py @@ -224,7 +224,7 @@ def integrity_file_path(path): @classmethod def read_integrity_file(cls, path): try: - with open(cls.integrity_file_path(path), 'r') as fd: + with open(cls.integrity_file_path(path)) as fd: return cls.parse_integrity_data(path, fd.read()) except FileNotFoundError: logger.info('No integrity file found for %s', path) diff --git a/src/borg/crypto/key.py b/src/borg/crypto/key.py index ff0aa93cd..0cc487ab8 100644 --- a/src/borg/crypto/key.py +++ b/src/borg/crypto/key.py @@ -379,7 +379,7 @@ def decrypt(self, id, data, decompress=True): try: payload = self.cipher.decrypt(data) except IntegrityError as e: - raise IntegrityError("Chunk %s: Could not decrypt [%s]" % (bin_to_hex(id), str(e))) + raise IntegrityError(f"Chunk {bin_to_hex(id)}: Could not decrypt [{str(e)}]") if not decompress: return payload data = self.decompress(payload) @@ -469,7 +469,7 @@ def getpass(cls, prompt): msg = [] for env_var in 'BORG_PASSPHRASE', 'BORG_PASSCOMMAND': env_var_set = os.environ.get(env_var) is not None - msg.append('%s is %s.' % (env_var, 'set' if env_var_set else 'not set')) + msg.append('{} is {}.'.format(env_var, 'set' if env_var_set else 'not set')) msg.append('Interactive password query failed.') raise NoPassphraseFailure(' '.join(msg)) from None else: @@ -760,7 +760,7 @@ def _get_new_target_in_keys_dir(self, args): return path def load(self, target, passphrase): - with open(target, 'r') as fd: + with open(target) as fd: key_data = ''.join(fd.readlines()[1:]) success = self._load(key_data, passphrase) if success: @@ -775,7 +775,7 @@ def save(self, target, passphrase, create=False): raise Error('Aborting because key in "%s" already exists.' % target) key_data = self._save(passphrase) with SaveFile(target) as fd: - fd.write('%s %s\n' % (self.FILE_ID, bin_to_hex(self.repository_id))) + fd.write(f'{self.FILE_ID} {bin_to_hex(self.repository_id)}\n') fd.write(key_data) fd.write('\n') self.target = target diff --git a/src/borg/crypto/keymanager.py b/src/borg/crypto/keymanager.py index 675c57635..32dd39c04 100644 --- a/src/borg/crypto/keymanager.py +++ b/src/borg/crypto/keymanager.py @@ -52,7 +52,7 @@ def load_keyblob(self): if self.keyblob_storage == KeyBlobStorage.KEYFILE: k = KeyfileKey(self.repository) target = k.find_key() - with open(target, 'r') as fd: + with open(target) as fd: self.keyblob = ''.join(fd.readlines()[1:]) elif self.keyblob_storage == KeyBlobStorage.REPO: @@ -68,7 +68,7 @@ def store_keyblob(self, args): self.repository.save_key(self.keyblob.encode('utf-8')) def get_keyfile_data(self): - data = '%s %s\n' % (KeyfileKey.FILE_ID, bin_to_hex(self.repository.id)) + data = f'{KeyfileKey.FILE_ID} {bin_to_hex(self.repository.id)}\n' data += self.keyblob if not self.keyblob.endswith('\n'): data += '\n' @@ -115,7 +115,7 @@ def grouped(s): lines = (len(binary) + 17) // 18 repoid = bin_to_hex(self.repository.id)[:18] complete_checksum = sha256_truncated(binary, 12) - export += 'id: {0:d} / {1} / {2} - {3}\n'.format(lines, + export += 'id: {:d} / {} / {} - {}\n'.format(lines, grouped(repoid), grouped(complete_checksum), sha256_truncated((str(lines) + '/' + repoid + '/' + complete_checksum).encode('ascii'), 2)) @@ -124,7 +124,7 @@ def grouped(s): idx += 1 binline = binary[:18] checksum = sha256_truncated(idx.to_bytes(2, byteorder='big') + binline, 2) - export += '{0:2d}: {1} - {2}\n'.format(idx, grouped(bin_to_hex(binline)), checksum) + export += f'{idx:2d}: {grouped(bin_to_hex(binline))} - {checksum}\n' binary = binary[18:] with dash_open(path, 'w') as fd: @@ -188,7 +188,7 @@ def import_paperkey(self, args): idx = 1 # body line input while True: - inline = input('{0:2d}: '.format(idx)) + inline = input(f'{idx:2d}: ') inline = inline.replace(' ', '') if inline == '': if yes('Abort import? [yN]:'): @@ -204,7 +204,7 @@ def import_paperkey(self, args): print("only characters 0-9 and a-f and '-' are valid, try again") continue if sha256_truncated(idx.to_bytes(2, byteorder='big') + part, 2) != checksum: - print('line checksum did not match, try line {0} again'.format(idx)) + print(f'line checksum did not match, try line {idx} again') continue result += part if idx == lines: diff --git a/src/borg/crypto/nonces.py b/src/borg/crypto/nonces.py index fe5abc547..12a597484 100644 --- a/src/borg/crypto/nonces.py +++ b/src/borg/crypto/nonces.py @@ -22,7 +22,7 @@ def __init__(self, repository, manifest_nonce): def get_local_free_nonce(self): try: - with open(self.nonce_file, 'r') as fd: + with open(self.nonce_file) as fd: return bytes_to_long(unhexlify(fd.read())) except FileNotFoundError: return None diff --git a/src/borg/fuse.py b/src/borg/fuse.py index 7cecdabe5..04183a008 100644 --- a/src/borg/fuse.py +++ b/src/borg/fuse.py @@ -234,7 +234,7 @@ def iter_archive_items(self, archive_item_ids, filter=None, consider_part_files= self.write_offset = write_offset -class FuseBackend(object): +class FuseBackend: """Virtual filesystem based on archive(s) to provide information to fuse """ diff --git a/src/borg/helpers/manifest.py b/src/borg/helpers/manifest.py index 0703b4123..84871f736 100644 --- a/src/borg/helpers/manifest.py +++ b/src/borg/helpers/manifest.py @@ -233,7 +233,7 @@ def get_all_mandatory_features(self): for operation, requirements in feature_flags.items(): if b'mandatory' in requirements: - result[operation.decode()] = set([feature.decode() for feature in requirements[b'mandatory']]) + result[operation.decode()] = {feature.decode() for feature in requirements[b'mandatory']} return result def write(self): diff --git a/src/borg/helpers/misc.py b/src/borg/helpers/misc.py index bf7ae8065..96eb78993 100644 --- a/src/borg/helpers/misc.py +++ b/src/borg/helpers/misc.py @@ -91,13 +91,13 @@ def sysinfo(): from ..fuse_impl import llfuse, BORG_FUSE_IMPL llfuse_name = llfuse.__name__ if llfuse else 'None' llfuse_version = (' %s' % llfuse.__version__) if llfuse else '' - llfuse_info = '%s%s [%s]' % (llfuse_name, llfuse_version, BORG_FUSE_IMPL) + llfuse_info = f'{llfuse_name}{llfuse_version} [{BORG_FUSE_IMPL}]' info = [] if uname is not None: - info.append('Platform: %s' % (' '.join(uname), )) + info.append('Platform: {}'.format(' '.join(uname))) if linux_distribution is not None: info.append('Linux: %s %s %s' % linux_distribution) - info.append('Borg: %s Python: %s %s msgpack: %s fuse: %s' % ( + info.append('Borg: {} Python: {} {} msgpack: {} fuse: {}'.format( borg_version, python_implementation, python_version, msgpack_version, llfuse_info)) info.append('PID: %d CWD: %s' % (os.getpid(), os.getcwd())) info.append('sys.argv: %r' % sys.argv) diff --git a/src/borg/helpers/parseformat.py b/src/borg/helpers/parseformat.py index bc3359807..ebbc7b526 100644 --- a/src/borg/helpers/parseformat.py +++ b/src/borg/helpers/parseformat.py @@ -80,7 +80,7 @@ def interval(s): # range suffixes in ascending multiplier order ranges = [k for k, v in sorted(multiplier.items(), key=lambda t: t[1])] raise argparse.ArgumentTypeError( - 'Unexpected interval time unit "%s": expected one of %r' % (s[-1], ranges)) + f'Unexpected interval time unit "{s[-1]}": expected one of {ranges!r}') try: hours = int(number) * multiplier[suffix] @@ -117,7 +117,7 @@ def ChunkerParams(s): return CHUNKER_PARAMS # this must stay last as it deals with old-style compat mode (no algorithm, 4 params, buzhash): if algo == CH_BUZHASH and count == 5 or count == 4: # [buzhash, ]chunk_min, chunk_max, chunk_mask, window_size - chunk_min, chunk_max, chunk_mask, window_size = [int(p) for p in params[count - 4:]] + chunk_min, chunk_max, chunk_mask, window_size = (int(p) for p in params[count - 4:]) if not (chunk_min <= chunk_mask <= chunk_max): raise ValueError('required: chunk_min <= chunk_mask <= chunk_max') if chunk_min < 6: @@ -150,7 +150,7 @@ def partial_format(format, mapping): """ for key, value in mapping.items(): key = re.escape(key) - format = re.sub(r'(?" % ( + return "<{}: start={!r} end={!r} timeout={!r} sleep={!r}>".format( self.__class__.__name__, self.start_time, self.end_time, self.timeout_interval, self.sleep_interval) @@ -118,7 +118,7 @@ def __exit__(self, *exc): self.release() def __repr__(self): - return "<%s: %r>" % (self.__class__.__name__, self.unique_name) + return f"<{self.__class__.__name__}: {self.unique_name!r}>" def acquire(self, timeout=None, sleep=None): if timeout is None: @@ -299,7 +299,7 @@ def remove(self): def get(self, key): roster = self.load() - return set(tuple(e) for e in roster.get(key, [])) + return {tuple(e) for e in roster.get(key, [])} def empty(self, *keys): return all(not self.get(key) for key in keys) @@ -307,7 +307,7 @@ def empty(self, *keys): def modify(self, key, op): roster = self.load() try: - elements = set(tuple(e) for e in roster[key]) + elements = {tuple(e) for e in roster[key]} except KeyError: elements = set() if op == ADD: @@ -374,7 +374,7 @@ def __exit__(self, *exc): self.release() def __repr__(self): - return "<%s: %r>" % (self.__class__.__name__, self.id) + return f"<{self.__class__.__name__}: {self.id!r}>" def acquire(self, exclusive=None, remove=None, sleep=None): if exclusive is None: diff --git a/src/borg/logger.py b/src/borg/logger.py index 0fb7a062c..b24eb7711 100644 --- a/src/borg/logger.py +++ b/src/borg/logger.py @@ -46,7 +46,7 @@ def _log_warning(message, category, filename, lineno, file=None, line=None): # for warnings, we just want to use the logging system, not stderr or other files - msg = "{0}:{1}: {2}: {3}".format(filename, lineno, category.__name__, message) + msg = f"{filename}:{lineno}: {category.__name__}: {message}" logger = create_logger(__name__) # Note: the warning will look like coming from here, # but msg contains info about where it really comes from @@ -82,7 +82,7 @@ def setup_logging(stream=None, conf_fname=None, env_var='BORG_LOGGING_CONF', lev logger = logging.getLogger(__name__) borg_logger = logging.getLogger('borg') borg_logger.json = json - logger.debug('using logging configuration read from "{0}"'.format(conf_fname)) + logger.debug(f'using logging configuration read from "{conf_fname}"') warnings.showwarning = _log_warning return None except Exception as err: # XXX be more precise @@ -110,7 +110,7 @@ def setup_logging(stream=None, conf_fname=None, env_var='BORG_LOGGING_CONF', lev configured = True logger = logging.getLogger(__name__) if err_msg: - logger.warning('setup_logging for "{0}" failed with "{1}".'.format(conf_fname, err_msg)) + logger.warning(f'setup_logging for "{conf_fname}" failed with "{err_msg}".') logger.debug('using builtin fallback logging configuration') warnings.showwarning = _log_warning return handler diff --git a/src/borg/patterns.py b/src/borg/patterns.py index a3e34d401..49668ef2b 100644 --- a/src/borg/patterns.py +++ b/src/borg/patterns.py @@ -201,7 +201,7 @@ def match(self, path, normalize=True): return matches def __repr__(self): - return '%s(%s)' % (type(self), self.pattern) + return f'{type(self)}({self.pattern})' def __str__(self): return self.pattern_orig @@ -315,7 +315,7 @@ def _match(self, path): ShellPattern, } -_PATTERN_CLASS_BY_PREFIX = dict((i.PREFIX, i) for i in _PATTERN_CLASSES) +_PATTERN_CLASS_BY_PREFIX = {i.PREFIX: i for i in _PATTERN_CLASSES} CmdTuple = namedtuple('CmdTuple', 'val cmd') @@ -339,7 +339,7 @@ def get_pattern_class(prefix): try: return _PATTERN_CLASS_BY_PREFIX[prefix] except KeyError: - raise ValueError("Unknown pattern style: {}".format(prefix)) from None + raise ValueError(f"Unknown pattern style: {prefix}") from None def parse_pattern(pattern, fallback=FnmatchPattern, recurse_dir=True): @@ -394,7 +394,7 @@ def parse_inclexcl_command(cmd_line_str, fallback=ShellPattern): try: val = get_pattern_class(remainder_str) except ValueError: - raise argparse.ArgumentTypeError("Invalid pattern style: {}".format(remainder_str)) + raise argparse.ArgumentTypeError(f"Invalid pattern style: {remainder_str}") else: # determine recurse_dir based on command type recurse_dir = command_recurses_dir(cmd) diff --git a/src/borg/platform/base.py b/src/borg/platform/base.py index 6d90328e1..1eb929ee2 100644 --- a/src/borg/platform/base.py +++ b/src/borg/platform/base.py @@ -265,7 +265,7 @@ def getfqdn(name=''): name = socket.gethostname() try: addrs = socket.getaddrinfo(name, None, 0, socket.SOCK_DGRAM, 0, socket.AI_CANONNAME) - except socket.error: + except OSError: pass else: for addr in addrs: @@ -288,7 +288,7 @@ def getfqdn(name=''): # thus, we offer BORG_HOST_ID where a user can set an own, unique id for each of his hosts. hostid = os.environ.get('BORG_HOST_ID') if not hostid: - hostid = '%s@%s' % (fqdn, uuid.getnode()) + hostid = f'{fqdn}@{uuid.getnode()}' def get_process_id(): diff --git a/src/borg/remote.py b/src/borg/remote.py index 77d395f5e..fa0772c60 100644 --- a/src/borg/remote.py +++ b/src/borg/remote.py @@ -286,7 +286,7 @@ def serve(self): else: tb_log_level = logging.ERROR msg = '%s Exception in RPC call' % e.__class__.__name__ - tb = '%s\n%s' % (traceback.format_exc(), sysinfo()) + tb = f'{traceback.format_exc()}\n{sysinfo()}' logging.error(msg) logging.log(tb_log_level, tb) exc = 'Remote Exception (see remote log for the traceback)' @@ -470,7 +470,7 @@ def do_rpc(self, *args, **kwargs): if restriction.get('dontcare', False): continue - raise self.RPCServerOutdated("{0} {1}={2!s}".format(f.__name__, name, named[name]), + raise self.RPCServerOutdated(f"{f.__name__} {name}={named[name]!s}", format_version(restriction['since'])) return self.call(f.__name__, named, **extra) @@ -622,7 +622,7 @@ def __del__(self): assert False, 'cleanup happened in Repository.__del__' def __repr__(self): - return '<%s %s>' % (self.__class__.__name__, self.location.canonical_path()) + return f'<{self.__class__.__name__} {self.location.canonical_path()}>' def __enter__(self): return self @@ -697,7 +697,7 @@ def ssh_cmd(self, location): if location.port: args += ['-p', str(location.port)] if location.user: - args.append('%s@%s' % (location.user, location.host)) + args.append(f'{location.user}@{location.host}') else: args.append('%s' % location.host) return args @@ -941,8 +941,7 @@ def get(self, id): return resp def get_many(self, ids, is_preloaded=False): - for resp in self.call_many('get', [{'id': id} for id in ids], is_preloaded=is_preloaded): - yield resp + yield from self.call_many('get', [{'id': id} for id in ids], is_preloaded=is_preloaded) @api(since=parse_version('1.0.0')) def put(self, id, data, wait=True): diff --git a/src/borg/repository.py b/src/borg/repository.py index f9a2c11f6..bb67c5a3f 100644 --- a/src/borg/repository.py +++ b/src/borg/repository.py @@ -190,7 +190,7 @@ def __del__(self): assert False, "cleanup happened in Repository.__del__" def __repr__(self): - return '<%s %s>' % (self.__class__.__name__, self.path) + return f'<{self.__class__.__name__} {self.path}>' def __enter__(self): if self.do_create: @@ -347,7 +347,7 @@ def get_free_nonce(self): nonce_path = os.path.join(self.path, 'nonce') try: - with open(nonce_path, 'r') as fd: + with open(nonce_path) as fd: return int.from_bytes(unhexlify(fd.read()), byteorder='big') except FileNotFoundError: return None @@ -716,7 +716,7 @@ def check_free_space(self): except OSError as os_error: logger.warning('Failed to check free space before committing: ' + str(os_error)) return - logger.debug('check_free_space: required bytes {}, free bytes {}'.format(required_free_space, free_space)) + logger.debug(f'check_free_space: required bytes {required_free_space}, free bytes {free_space}') if free_space < required_free_space: if self.created: logger.error('Not enough free space to initialize repository at this location.') @@ -924,7 +924,7 @@ def _update_index(self, segment, objects, report=None): elif tag == TAG_COMMIT: continue else: - msg = 'Unexpected tag {} in segment {}'.format(tag, segment) + msg = f'Unexpected tag {tag} in segment {segment}' if report is None: raise self.CheckNeeded(msg) else: @@ -1045,7 +1045,7 @@ def report_error(msg): # self.index, self.segments, self.compact now reflect the state of the segment files up to # We might need to add a commit tag if no committed segment is found if repair and segments_transaction_id is None: - report_error('Adding commit tag to segment {}'.format(transaction_id)) + report_error(f'Adding commit tag to segment {transaction_id}') self.io.segment = transaction_id + 1 self.io.write_commit() if not partial: @@ -1484,7 +1484,7 @@ def iter_objects(self, segment, offset=0, include_data=False, read_data=True): # Repository.scan() calls us with segment > 0 when it continues an ongoing iteration # from a marker position - but then we have checked the magic before already. if fd.read(MAGIC_LEN) != MAGIC: - raise IntegrityError('Invalid segment magic [segment {}, offset {}]'.format(segment, 0)) + raise IntegrityError(f'Invalid segment magic [segment {segment}, offset {0}]') offset = MAGIC_LEN header = fd.read(self.header_fmt.size) while header: @@ -1613,7 +1613,7 @@ def write_put(self, id, data, raise_full=False): data_size = len(data) if data_size > MAX_DATA_SIZE: # this would push the segment entry size beyond MAX_OBJECT_SIZE. - raise IntegrityError('More than allowed put data [{} > {}]'.format(data_size, MAX_DATA_SIZE)) + raise IntegrityError(f'More than allowed put data [{data_size} > {MAX_DATA_SIZE}]') fd = self.get_write_fd(want_new=(id == Manifest.MANIFEST_ID), raise_full=raise_full) size = data_size + self.put_header_fmt.size offset = self.offset diff --git a/src/borg/shellpattern.py b/src/borg/shellpattern.py index 899544975..c9447704b 100644 --- a/src/borg/shellpattern.py +++ b/src/borg/shellpattern.py @@ -33,7 +33,7 @@ def translate(pat, match_end=r"\Z"): if i + 1 < n and pat[i] == "*" and pat[i + 1] == sep: # **/ == wildcard for 0+ full (relative) directory names with trailing slashes; the forward slash stands # for the platform-specific path separator - res += r"(?:[^\%s]*\%s)*" % (sep, sep) + res += fr"(?:[^\{sep}]*\{sep})*" i += 2 else: # * == wildcard for name parts (does not cross path separator) diff --git a/src/borg/testsuite/__init__.py b/src/borg/testsuite/__init__.py index aa7b3e882..b1db8aa95 100644 --- a/src/borg/testsuite/__init__.py +++ b/src/borg/testsuite/__init__.py @@ -58,7 +58,7 @@ def unopened_tempfile(): yield os.path.join(tempdir, "file") -@functools.lru_cache() +@functools.lru_cache def are_symlinks_supported(): with unopened_tempfile() as filepath: try: @@ -70,7 +70,7 @@ def are_symlinks_supported(): return False -@functools.lru_cache() +@functools.lru_cache def are_hardlinks_supported(): if not hasattr(os, 'link'): # some pythons do not have os.link @@ -89,7 +89,7 @@ def are_hardlinks_supported(): return False -@functools.lru_cache() +@functools.lru_cache def are_fifos_supported(): with unopened_tempfile() as filepath: try: @@ -104,7 +104,7 @@ def are_fifos_supported(): return False -@functools.lru_cache() +@functools.lru_cache def is_utime_fully_supported(): with unopened_tempfile() as filepath: # Some filesystems (such as SSHFS) don't support utime on symlinks @@ -124,7 +124,7 @@ def is_utime_fully_supported(): return False -@functools.lru_cache() +@functools.lru_cache def is_birthtime_fully_supported(): if not hasattr(os.stat_result, 'st_birthtime'): return False @@ -172,9 +172,9 @@ class BaseTestCase(unittest.TestCase): @contextmanager def assert_creates_file(self, path): - assert not os.path.exists(path), '{} should not exist'.format(path) + assert not os.path.exists(path), f'{path} should not exist' yield - assert os.path.exists(path), '{} should exist'.format(path) + assert os.path.exists(path), f'{path} should exist' def assert_dirs_equal(self, dir1, dir2, **kwargs): diff = filecmp.dircmp(dir1, dir2) @@ -293,7 +293,7 @@ def wait_for_mountstate(self, mountpoint, *, mounted, timeout=5): if os.path.ismount(mountpoint) == mounted: return time.sleep(0.1) - message = 'Waiting for %s of %s' % ('mount' if mounted else 'umount', mountpoint) + message = 'Waiting for {} of {}'.format('mount' if mounted else 'umount', mountpoint) raise TimeoutError(message) @contextmanager diff --git a/src/borg/testsuite/archive.py b/src/borg/testsuite/archive.py index 934d76b61..db9ed573b 100644 --- a/src/borg/testsuite/archive.py +++ b/src/borg/testsuite/archive.py @@ -55,10 +55,10 @@ def tests_stats_progress(stats, monkeypatch, columns=80): def test_stats_format(stats): assert str(stats) == """\ This archive: 20 B 10 B 10 B""" - s = "{0.osize_fmt}".format(stats) + s = f"{stats.osize_fmt}" assert s == "20 B" # kind of redundant, but id is variable so we can't match reliably - assert repr(stats) == ''.format(id(stats)) + assert repr(stats) == f'' class MockCache: diff --git a/src/borg/testsuite/archiver.py b/src/borg/testsuite/archiver.py index 11d83525d..58b760be3 100644 --- a/src/borg/testsuite/archiver.py +++ b/src/borg/testsuite/archiver.py @@ -1867,7 +1867,7 @@ def test_unknown_mandatory_feature_in_cache(self): manifest, key = Manifest.load(repository, Manifest.NO_OPERATION_CHECK) with Cache(repository, key, manifest) as cache: cache.begin_txn() - cache.cache_config.mandatory_features = set(['unknown-feature']) + cache.cache_config.mandatory_features = {'unknown-feature'} cache.commit() if self.FORK_DEFAULT: @@ -1891,7 +1891,7 @@ def wipe_wrapper(*args): repository._location = Location(self.repository_location) manifest, key = Manifest.load(repository, Manifest.NO_OPERATION_CHECK) with Cache(repository, key, manifest) as cache: - assert cache.cache_config.mandatory_features == set([]) + assert cache.cache_config.mandatory_features == set() def test_progress_on(self): self.create_regular_file('file1', size=1024 * 80) @@ -2748,7 +2748,7 @@ def wrapper(self, old_id, new_id): pass with open(assert_data_file, 'rb') as _in: assert_data = pickle.load(_in) - print('\nLock.migrate_lock(): assert_data = %r.' % (assert_data, ), file=sys.stderr, flush=True) + print(f'\nLock.migrate_lock(): assert_data = {assert_data!r}.', file=sys.stderr, flush=True) exception = assert_data['exception'] if exception is not None: extracted_tb = assert_data['exception.extr_tb'] @@ -3089,14 +3089,14 @@ def test_key_export_keyfile(self): repo_id = self._extract_repository_id(self.repository_path) self.cmd('key', 'export', self.repository_location, export_file) - with open(export_file, 'r') as fd: + with open(export_file) as fd: export_contents = fd.read() assert export_contents.startswith('BORG_KEY ' + bin_to_hex(repo_id) + '\n') key_file = self.keys_path + '/' + os.listdir(self.keys_path)[0] - with open(key_file, 'r') as fd: + with open(key_file) as fd: key_contents = fd.read() assert key_contents == export_contents @@ -3105,7 +3105,7 @@ def test_key_export_keyfile(self): self.cmd('key', 'import', self.repository_location, export_file) - with open(key_file, 'r') as fd: + with open(key_file) as fd: key_contents2 = fd.read() assert key_contents2 == key_contents @@ -3117,7 +3117,7 @@ def test_key_import_keyfile_with_borg_key_file(self): self.cmd('key', 'export', self.repository_location, exported_key_file) key_file = os.path.join(self.keys_path, os.listdir(self.keys_path)[0]) - with open(key_file, 'r') as fd: + with open(key_file) as fd: key_contents = fd.read() os.unlink(key_file) @@ -3126,7 +3126,7 @@ def test_key_import_keyfile_with_borg_key_file(self): self.cmd('key', 'import', self.repository_location, exported_key_file) assert not os.path.isfile(key_file), '"borg key import" should respect BORG_KEY_FILE' - with open(imported_key_file, 'r') as fd: + with open(imported_key_file) as fd: imported_key_contents = fd.read() assert imported_key_contents == key_contents @@ -3136,7 +3136,7 @@ def test_key_export_repokey(self): repo_id = self._extract_repository_id(self.repository_path) self.cmd('key', 'export', self.repository_location, export_file) - with open(export_file, 'r') as fd: + with open(export_file) as fd: export_contents = fd.read() assert export_contents.startswith('BORG_KEY ' + bin_to_hex(repo_id) + '\n') @@ -3167,7 +3167,7 @@ def test_key_export_qr(self): repo_id = self._extract_repository_id(self.repository_path) self.cmd('key', 'export', '--qr-html', self.repository_location, export_file) - with open(export_file, 'r', encoding='utf-8') as fd: + with open(export_file, encoding='utf-8') as fd: export_contents = fd.read() assert bin_to_hex(repo_id) in export_contents @@ -3221,7 +3221,7 @@ def test_key_export_paperkey(self): self.cmd('key', 'export', '--paper', self.repository_location, export_file) - with open(export_file, 'r') as fd: + with open(export_file) as fd: export_contents = fd.read() assert export_contents == """To restore key use borg key import --paper /path/to/repo @@ -3284,7 +3284,7 @@ def test_debug_dump_manifest(self): dump_file = self.output_path + '/dump' output = self.cmd('debug', 'dump-manifest', self.repository_location, dump_file) assert output == "" - with open(dump_file, "r") as f: + with open(dump_file) as f: result = json.load(f) assert 'archives' in result assert 'config' in result @@ -3299,7 +3299,7 @@ def test_debug_dump_archive(self): dump_file = self.output_path + '/dump' output = self.cmd('debug', 'dump-archive', self.repository_location + "::test", dump_file) assert output == "" - with open(dump_file, "r") as f: + with open(dump_file) as f: result = json.load(f) assert '_name' in result assert '_manifest_entry' in result @@ -4144,7 +4144,7 @@ def do_asserts(output, can_compare_ids): # File contents changed (deleted and replaced with a new file) change = 'B' if can_compare_ids else '{:<19}'.format('modified') assert 'file_replaced' in output # added to debug #3494 - assert '{} input/file_replaced'.format(change) in output + assert f'{change} input/file_replaced' in output # File unchanged assert 'input/file_unchanged' not in output @@ -4174,9 +4174,9 @@ def do_asserts(output, can_compare_ids): # should notice the changes in both links. However, the symlink # pointing to the file is not changed. change = '0 B' if can_compare_ids else '{:<19}'.format('modified') - assert '{} input/empty'.format(change) in output + assert f'{change} input/empty' in output if are_hardlinks_supported(): - assert '{} input/hardlink_contents_changed'.format(change) in output + assert f'{change} input/hardlink_contents_changed' in output if are_symlinks_supported(): assert 'input/link_target_contents_changed' not in output diff --git a/src/borg/testsuite/compress.py b/src/borg/testsuite/compress.py index 0c284e144..3942c3537 100644 --- a/src/borg/testsuite/compress.py +++ b/src/borg/testsuite/compress.py @@ -147,7 +147,7 @@ def test_obfuscate(): # 2 id bytes compression, 2 id bytes obfuscator. 4 length bytes assert len(data) + 8 <= len(compressed) <= len(data) * 101 + 8 # compressing 100 times the same data should give at least 50 different result sizes - assert len(set(len(compressor.compress(data)) for i in range(100))) > 50 + assert len({len(compressor.compress(data)) for i in range(100)}) > 50 cs = CompressionSpec('obfuscate,2,lz4') assert isinstance(cs.inner.compressor, LZ4) @@ -158,7 +158,7 @@ def test_obfuscate(): min_compress, max_compress = 0.2, 0.001 # estimate compression factor outer boundaries assert max_compress * len(data) + 8 <= len(compressed) <= min_compress * len(data) * 1001 + 8 # compressing 100 times the same data should give multiple different result sizes - assert len(set(len(compressor.compress(data)) for i in range(100))) > 10 + assert len({len(compressor.compress(data)) for i in range(100)}) > 10 cs = CompressionSpec('obfuscate,6,zstd,3') assert isinstance(cs.inner.compressor, ZSTD) @@ -169,7 +169,7 @@ def test_obfuscate(): min_compress, max_compress = 0.2, 0.001 # estimate compression factor outer boundaries assert max_compress * len(data) + 8 <= len(compressed) <= min_compress * len(data) * 10000001 + 8 # compressing 100 times the same data should give multiple different result sizes - assert len(set(len(compressor.compress(data)) for i in range(100))) > 90 + assert len({len(compressor.compress(data)) for i in range(100)}) > 90 cs = CompressionSpec('obfuscate,2,auto,zstd,10') assert isinstance(cs.inner.compressor, Auto) @@ -180,7 +180,7 @@ def test_obfuscate(): min_compress, max_compress = 0.2, 0.001 # estimate compression factor outer boundaries assert max_compress * len(data) + 8 <= len(compressed) <= min_compress * len(data) * 1001 + 8 # compressing 100 times the same data should give multiple different result sizes - assert len(set(len(compressor.compress(data)) for i in range(100))) > 10 + assert len({len(compressor.compress(data)) for i in range(100)}) > 10 cs = CompressionSpec('obfuscate,110,none') assert isinstance(cs.inner.compressor, CNONE) diff --git a/src/borg/testsuite/file_integrity.py b/src/borg/testsuite/file_integrity.py index 6dee247a1..af50f15c0 100644 --- a/src/borg/testsuite/file_integrity.py +++ b/src/borg/testsuite/file_integrity.py @@ -1,4 +1,3 @@ - import pytest from ..crypto.file_integrity import IntegrityCheckedFile, DetachedIntegrityCheckedFile, FileIntegrityError diff --git a/src/borg/testsuite/helpers.py b/src/borg/testsuite/helpers.py index 2e30e36be..5a5df302e 100644 --- a/src/borg/testsuite/helpers.py +++ b/src/borg/testsuite/helpers.py @@ -225,7 +225,7 @@ def test_format_path(self, monkeypatch): monkeypatch.delenv('BORG_REPO', raising=False) test_pid = os.getpid() assert repr(Location('/some/path::archive{pid}')) == \ - "Location(proto='file', user=None, host=None, port=None, path='/some/path', archive='archive{}')".format(test_pid) + f"Location(proto='file', user=None, host=None, port=None, path='/some/path', archive='archive{test_pid}')" location_time1 = Location('/some/path::archive{now:%s}') sleep(1.1) location_time2 = Location('/some/path::archive{now:%s}') @@ -259,11 +259,11 @@ def test_ssh_placeholder(self, monkeypatch): from borg.platform import hostname monkeypatch.setenv('BORG_REPO', 'ssh://user@host:1234/{hostname}') assert repr(Location('::archive')) == \ - "Location(proto='ssh', user='user', host='host', port=1234, path='/{}', archive='archive')".format(hostname) + f"Location(proto='ssh', user='user', host='host', port=1234, path='/{hostname}', archive='archive')" assert repr(Location('::')) == \ - "Location(proto='ssh', user='user', host='host', port=1234, path='/{}', archive=None)".format(hostname) + f"Location(proto='ssh', user='user', host='host', port=1234, path='/{hostname}', archive=None)" assert repr(Location()) == \ - "Location(proto='ssh', user='user', host='host', port=1234, path='/{}', archive=None)".format(hostname) + f"Location(proto='ssh', user='user', host='host', port=1234, path='/{hostname}', archive=None)" def test_file(self, monkeypatch): monkeypatch.setenv('BORG_REPO', 'file:///some/path') @@ -380,7 +380,7 @@ def __init__(self, ts, id): self.id = id def __repr__(self): - return "{0}: {1}".format(self.id, self.ts.isoformat()) + return f"{self.id}: {self.ts.isoformat()}" @pytest.mark.parametrize( diff --git a/src/borg/testsuite/lrucache.py b/src/borg/testsuite/lrucache.py index eea171d64..6d1ab4adf 100644 --- a/src/borg/testsuite/lrucache.py +++ b/src/borg/testsuite/lrucache.py @@ -14,7 +14,7 @@ def test_lrucache(self): for i, x in enumerate('abc'): c[x] = i assert len(c) == 2 - assert c.items() == set([('b', 1), ('c', 2)]) + assert c.items() == {('b', 1), ('c', 2)} assert 'a' not in c assert 'b' in c with pytest.raises(KeyError): diff --git a/src/borg/testsuite/nanorst.py b/src/borg/testsuite/nanorst.py index 065436094..b25336b62 100644 --- a/src/borg/testsuite/nanorst.py +++ b/src/borg/testsuite/nanorst.py @@ -1,4 +1,3 @@ - import pytest from ..nanorst import rst_to_text diff --git a/src/borg/testsuite/nonces.py b/src/borg/testsuite/nonces.py index d0bc85eaf..6d6701631 100644 --- a/src/borg/testsuite/nonces.py +++ b/src/borg/testsuite/nonces.py @@ -37,7 +37,7 @@ def setUp(self): self.repository = None def cache_nonce(self): - with open(os.path.join(get_security_dir(self.repository.id_str), 'nonce'), "r") as fd: + with open(os.path.join(get_security_dir(self.repository.id_str), 'nonce')) as fd: return fd.read() def set_cache_nonce(self, nonce): diff --git a/src/borg/testsuite/patterns.py b/src/borg/testsuite/patterns.py index 543ef7bb1..e26ead1e8 100644 --- a/src/borg/testsuite/patterns.py +++ b/src/borg/testsuite/patterns.py @@ -204,7 +204,7 @@ def use_normalized_unicode(): def _make_test_patterns(pattern): return [PathPrefixPattern(pattern), FnmatchPattern(pattern), - RegexPattern("^{}/foo$".format(pattern)), + RegexPattern(f"^{pattern}/foo$"), ShellPattern(pattern), ] @@ -275,7 +275,7 @@ def test_exclude_patterns_from_file(tmpdir, lines, expected): def evaluate(filename): patterns = [] - load_exclude_file(open(filename, "rt"), patterns) + load_exclude_file(open(filename), patterns) matcher = PatternMatcher(fallback=True) matcher.add_inclexcl(patterns) return [path for path in files if matcher.match(path)] @@ -306,7 +306,7 @@ def test_load_patterns_from_file(tmpdir, lines, expected_roots, expected_numpatt def evaluate(filename): roots = [] inclexclpatterns = [] - load_pattern_file(open(filename, "rt"), roots, inclexclpatterns) + load_pattern_file(open(filename), roots, inclexclpatterns) return roots, len(inclexclpatterns) patternfile = tmpdir.join("patterns.txt") @@ -356,7 +356,7 @@ def test_load_invalid_patterns_from_file(tmpdir, lines): with pytest.raises(argparse.ArgumentTypeError): roots = [] inclexclpatterns = [] - load_pattern_file(open(filename, "rt"), roots, inclexclpatterns) + load_pattern_file(open(filename), roots, inclexclpatterns) @pytest.mark.parametrize("lines, expected", [ @@ -400,7 +400,7 @@ def evaluate(filename): matcher = PatternMatcher(fallback=True) roots = [] inclexclpatterns = [] - load_pattern_file(open(filename, "rt"), roots, inclexclpatterns) + load_pattern_file(open(filename), roots, inclexclpatterns) matcher.add_inclexcl(inclexclpatterns) return [path for path in files if matcher.match(path)] diff --git a/src/borg/testsuite/platform.py b/src/borg/testsuite/platform.py index d0b510db8..659e4376e 100644 --- a/src/borg/testsuite/platform.py +++ b/src/borg/testsuite/platform.py @@ -53,7 +53,7 @@ def user_exists(username): return False -@functools.lru_cache() +@functools.lru_cache def are_acls_working(): with unopened_tempfile() as filepath: open(filepath, 'w').close() @@ -118,12 +118,12 @@ def test_non_ascii_acl(self): # but in practice they seem to be out there and must not make our code explode. file = tempfile.NamedTemporaryFile() self.assert_equal(self.get_acl(file.name), {}) - nothing_special = 'user::rw-\ngroup::r--\nmask::rw-\nother::---\n'.encode('ascii') + nothing_special = b'user::rw-\ngroup::r--\nmask::rw-\nother::---\n' # TODO: can this be tested without having an existing system user übel with uid 666 gid 666? - user_entry = 'user:übel:rw-:666'.encode('utf-8') - user_entry_numeric = 'user:666:rw-:666'.encode('ascii') - group_entry = 'group:übel:rw-:666'.encode('utf-8') - group_entry_numeric = 'group:666:rw-:666'.encode('ascii') + user_entry = 'user:übel:rw-:666'.encode() + user_entry_numeric = b'user:666:rw-:666' + group_entry = 'group:übel:rw-:666'.encode() + group_entry_numeric = b'group:666:rw-:666' acl = b'\n'.join([nothing_special, user_entry, group_entry]) self.set_acl(file.name, access=acl, numeric_ids=False) acl_access = self.get_acl(file.name, numeric_ids=False)['acl_access'] diff --git a/src/borg/testsuite/repository.py b/src/borg/testsuite/repository.py index 580f52e2e..c52820e33 100644 --- a/src/borg/testsuite/repository.py +++ b/src/borg/testsuite/repository.py @@ -528,14 +528,14 @@ def test_commit_nonce_reservation(self): self.repository.commit_nonce_reservation(0x200, 15) self.repository.commit_nonce_reservation(0x200, None) - with open(os.path.join(self.repository.path, "nonce"), "r") as fd: + with open(os.path.join(self.repository.path, "nonce")) as fd: assert fd.read() == "0000000000000200" with pytest.raises(Exception): self.repository.commit_nonce_reservation(0x200, 15) self.repository.commit_nonce_reservation(0x400, 0x200) - with open(os.path.join(self.repository.path, "nonce"), "r") as fd: + with open(os.path.join(self.repository.path, "nonce")) as fd: assert fd.read() == "0000000000000400" @@ -710,7 +710,7 @@ def get_head(self): return sorted(int(n) for n in os.listdir(os.path.join(self.tmppath, 'repository', 'data', '0')) if n.isdigit())[-1] def open_index(self): - return NSIndex.read(os.path.join(self.tmppath, 'repository', 'index.{}'.format(self.get_head()))) + return NSIndex.read(os.path.join(self.tmppath, 'repository', f'index.{self.get_head()}')) def corrupt_object(self, id_): idx = self.open_index() @@ -723,18 +723,18 @@ def delete_segment(self, segment): os.unlink(os.path.join(self.tmppath, 'repository', 'data', '0', str(segment))) def delete_index(self): - os.unlink(os.path.join(self.tmppath, 'repository', 'index.{}'.format(self.get_head()))) + os.unlink(os.path.join(self.tmppath, 'repository', f'index.{self.get_head()}')) def rename_index(self, new_name): - os.rename(os.path.join(self.tmppath, 'repository', 'index.{}'.format(self.get_head())), + os.rename(os.path.join(self.tmppath, 'repository', f'index.{self.get_head()}'), os.path.join(self.tmppath, 'repository', new_name)) def list_objects(self): - return set(int(key) for key in self.repository.list()) + return {int(key) for key in self.repository.list()} def test_repair_corrupted_segment(self): self.add_objects([[1, 2, 3], [4, 5], [6]]) - self.assert_equal(set([1, 2, 3, 4, 5, 6]), self.list_objects()) + self.assert_equal({1, 2, 3, 4, 5, 6}, self.list_objects()) self.check(status=True) self.corrupt_object(5) self.assert_raises(IntegrityError, lambda: self.get_objects(5)) @@ -746,22 +746,22 @@ def test_repair_corrupted_segment(self): self.check(repair=True, status=True) self.get_objects(4) self.check(status=True) - self.assert_equal(set([1, 2, 3, 4, 6]), self.list_objects()) + self.assert_equal({1, 2, 3, 4, 6}, self.list_objects()) def test_repair_missing_segment(self): self.add_objects([[1, 2, 3], [4, 5, 6]]) - self.assert_equal(set([1, 2, 3, 4, 5, 6]), self.list_objects()) + self.assert_equal({1, 2, 3, 4, 5, 6}, self.list_objects()) self.check(status=True) self.delete_segment(2) self.repository.rollback() self.check(repair=True, status=True) - self.assert_equal(set([1, 2, 3]), self.list_objects()) + self.assert_equal({1, 2, 3}, self.list_objects()) def test_repair_missing_commit_segment(self): self.add_objects([[1, 2, 3], [4, 5, 6]]) self.delete_segment(3) self.assert_raises(Repository.ObjectNotFound, lambda: self.get_objects(4)) - self.assert_equal(set([1, 2, 3]), self.list_objects()) + self.assert_equal({1, 2, 3}, self.list_objects()) def test_repair_corrupted_commit_segment(self): self.add_objects([[1, 2, 3], [4, 5, 6]]) @@ -771,7 +771,7 @@ def test_repair_corrupted_commit_segment(self): self.assert_raises(Repository.ObjectNotFound, lambda: self.get_objects(4)) self.check(status=True) self.get_objects(3) - self.assert_equal(set([1, 2, 3]), self.list_objects()) + self.assert_equal({1, 2, 3}, self.list_objects()) def test_repair_no_commits(self): self.add_objects([[1, 2, 3]]) @@ -786,14 +786,14 @@ def test_repair_no_commits(self): self.assert_equal(self.list_indices(), ['index.2']) self.check(status=True) self.get_objects(3) - self.assert_equal(set([1, 2, 3]), self.list_objects()) + self.assert_equal({1, 2, 3}, self.list_objects()) def test_repair_missing_index(self): self.add_objects([[1, 2, 3], [4, 5, 6]]) self.delete_index() self.check(status=True) self.get_objects(4) - self.assert_equal(set([1, 2, 3, 4, 5, 6]), self.list_objects()) + self.assert_equal({1, 2, 3, 4, 5, 6}, self.list_objects()) def test_repair_index_too_new(self): self.add_objects([[1, 2, 3], [4, 5, 6]]) @@ -802,7 +802,7 @@ def test_repair_index_too_new(self): self.check(status=True) self.assert_equal(self.list_indices(), ['index.3']) self.get_objects(4) - self.assert_equal(set([1, 2, 3, 4, 5, 6]), self.list_objects()) + self.assert_equal({1, 2, 3, 4, 5, 6}, self.list_objects()) def test_crash_before_compact(self): self.repository.put(H(0), b'data') diff --git a/src/borg/testsuite/upgrader.py b/src/borg/testsuite/upgrader.py index 9e6cd6ab0..ff921e4b7 100644 --- a/src/borg/testsuite/upgrader.py +++ b/src/borg/testsuite/upgrader.py @@ -54,7 +54,7 @@ def key_valid(path): """ keyfile = os.path.join(get_keys_dir(), os.path.basename(path)) - with open(keyfile, 'r') as f: + with open(keyfile) as f: return f.read().startswith(KeyfileKey.FILE_ID) diff --git a/src/borg/upgrader.py b/src/borg/upgrader.py index fc0851f32..5be0aac0e 100644 --- a/src/borg/upgrader.py +++ b/src/borg/upgrader.py @@ -36,7 +36,7 @@ def upgrade(self, dryrun=True, inplace=False, progress=False): with self: backup = None if not inplace: - backup = '{}.before-upgrade-{:%Y-%m-%d-%H:%M:%S}'.format(self.path, datetime.datetime.now()) + backup = f'{self.path}.before-upgrade-{datetime.datetime.now():%Y-%m-%d-%H:%M:%S}' logger.info('making a hardlink copy in %s', backup) if not dryrun: shutil.copytree(self.path, backup, copy_function=os.link) @@ -144,7 +144,7 @@ def convert_keyfiles(keyfile, dryrun): problem because the keyfiles are small (compared to, say, all the segments).""" logger.info("converting keyfile %s" % keyfile) - with open(keyfile, 'r') as f: + with open(keyfile) as f: data = f.read() data = data.replace(AtticKeyfileKey.FILE_ID, KeyfileKey.FILE_ID, 1) keyfile = os.path.join(get_keys_dir(), os.path.basename(keyfile)) @@ -214,12 +214,12 @@ def copy_cache_file(path): if os.path.exists(borg_file): logger.warning("borg cache file already exists in %s, not copying from Attic", borg_file) else: - logger.info("copying attic cache file from %s to %s" % (attic_file, borg_file)) + logger.info(f"copying attic cache file from {attic_file} to {borg_file}") if not dryrun: shutil.copyfile(attic_file, borg_file) return borg_file else: - logger.warning("no %s cache file found in %s" % (path, attic_file)) + logger.warning(f"no {path} cache file found in {attic_file}") return None # XXX: untested, because generating cache files is a PITA, see @@ -270,7 +270,7 @@ def find_key_file(cls, repository): raise KeyfileNotFoundError(repository.path, keys_dir) for name in os.listdir(keys_dir): filename = os.path.join(keys_dir, name) - with open(filename, 'r') as fd: + with open(filename) as fd: line = fd.readline().strip() if line and line.startswith(cls.FILE_ID) and line[10:] == repository.id_str: return filename @@ -319,7 +319,7 @@ def find_key_file(cls, repository): raise KeyfileNotFoundError(repository.path, keys_dir) for name in os.listdir(keys_dir): filename = os.path.join(keys_dir, name) - with open(filename, 'r') as fd: + with open(filename) as fd: line = fd.readline().strip() if line and line.startswith(cls.FILE_ID) and line[len(cls.FILE_ID) + 1:] == repository.id_str: return filename diff --git a/src/borg/xattr.py b/src/borg/xattr.py index d34339370..8a731340c 100644 --- a/src/borg/xattr.py +++ b/src/borg/xattr.py @@ -91,7 +91,7 @@ def get_all(path, follow_symlinks=False): pass elif e.errno == errno.EPERM: # we were not permitted to read this attribute, still can continue trying to read others - logger.warning('%s: Operation not permitted when reading extended attribute %s' % ( + logger.warning('{}: Operation not permitted when reading extended attribute {}'.format( path_str, name_str)) else: raise