Thomas Waldmann 1 year ago
parent
commit
5013121bd8

+ 3 - 11
setup.cfg

@@ -96,30 +96,22 @@ ignore = W503, E203, F405
 per_file_ignores =
 per_file_ignores =
     src/borg/archive.py:E402,E501
     src/borg/archive.py:E402,E501
     src/borg/archiver/__init__.py:E402
     src/borg/archiver/__init__.py:E402
-    src/borg/archiver/_common.py:E501
     src/borg/archiver/help_cmd.py:E501
     src/borg/archiver/help_cmd.py:E501
-    src/borg/archiver/rlist_cmd.py:E501
     src/borg/cache.py:E402,E501
     src/borg/cache.py:E402,E501
     src/borg/fuse.py:E402
     src/borg/fuse.py:E402
-    src/borg/manifest.py:E402,E501
-    src/borg/remote.py:E501
-    src/borg/repository.py:E501
+    src/borg/manifest.py:E402
     src/borg/xattr.py:E402
     src/borg/xattr.py:E402
     src/borg/crypto/key.py:E402
     src/borg/crypto/key.py:E402
     src/borg/helpers/__init__.py:F401
     src/borg/helpers/__init__.py:F401
     src/borg/helpers/misc.py:E402
     src/borg/helpers/misc.py:E402
-    src/borg/helpers/parseformat.py:E402,E501
+    src/borg/helpers/parseformat.py:E402
     src/borg/helpers/process.py:E402
     src/borg/helpers/process.py:E402
-    src/borg/helpers/shellpattern.py:E501
     src/borg/platform/__init__.py:F401
     src/borg/platform/__init__.py:F401
     src/borg/platform/base.py:E402
     src/borg/platform/base.py:E402
     src/borg/testsuite/archiver/disk_full.py:F811
     src/borg/testsuite/archiver/disk_full.py:F811
     src/borg/testsuite/archiver/return_codes.py:F811
     src/borg/testsuite/archiver/return_codes.py:F811
     src/borg/testsuite/benchmark.py:F811
     src/borg/testsuite/benchmark.py:F811
-    src/borg/testsuite/crypto.py:E501
-    src/borg/testsuite/helpers.py:E501
-    src/borg/testsuite/locking.py:E501
-    src/borg/testsuite/platform.py:E501,F811
+    src/borg/testsuite/platform.py:F811
 
 
 max_line_length = 120
 max_line_length = 120
 exclude = build,dist,.git,.idea,.cache,.tox
 exclude = build,dist,.git,.idea,.cache,.tox

+ 2 - 2
src/borg/archive.py

@@ -974,8 +974,8 @@ Duration: {0.duration}
             if not self.noacls:
             if not self.noacls:
                 acl_set(path, item, self.numeric_ids, fd=fd)
                 acl_set(path, item, self.numeric_ids, fd=fd)
             if not self.noxattrs and "xattrs" in item:
             if not self.noxattrs and "xattrs" in item:
-                # chown removes Linux capabilities, so set the extended attributes at the end, after chown, since they include
-                # the Linux capabilities in the "security.capability" attribute.
+                # chown removes Linux capabilities, so set the extended attributes at the end, after chown,
+                # since they include the Linux capabilities in the "security.capability" attribute.
                 warning = xattr.set_all(fd or path, item.xattrs, follow_symlinks=False)
                 warning = xattr.set_all(fd or path, item.xattrs, follow_symlinks=False)
                 if warning:
                 if warning:
                     set_ec(EXIT_WARNING)
                     set_ec(EXIT_WARNING)

+ 2 - 1
src/borg/archiver/_common.py

@@ -85,7 +85,8 @@ def with_repository(
     :param manifest: load manifest and repo_objs (key), pass them as keyword arguments
     :param manifest: load manifest and repo_objs (key), pass them as keyword arguments
     :param cache: open cache, pass it as keyword argument (implies manifest)
     :param cache: open cache, pass it as keyword argument (implies manifest)
     :param secure: do assert_secure after loading manifest
     :param secure: do assert_secure after loading manifest
-    :param compatibility: mandatory if not create and (manifest or cache), specifies mandatory feature categories to check
+    :param compatibility: mandatory if not create and (manifest or cache), specifies mandatory
+           feature categories to check
     """
     """
     # Note: with_repository decorator does not have a "key" argument (yet?)
     # Note: with_repository decorator does not have a "key" argument (yet?)
     compatibility = compat_check(
     compatibility = compat_check(

+ 1 - 1
src/borg/archiver/rlist_cmd.py

@@ -66,7 +66,7 @@ class RListMixIn:
             # Strings are left-aligned, numbers are right-aligned.
             # Strings are left-aligned, numbers are right-aligned.
             # Note: time columns except ``isomtime``, ``isoctime`` and ``isoatime`` cannot be padded.
             # Note: time columns except ``isomtime``, ``isoctime`` and ``isoatime`` cannot be padded.
             $ borg rlist --format '{archive:36} {time} [{id}]{NL}' /path/to/repo
             $ borg rlist --format '{archive:36} {time} [{id}]{NL}' /path/to/repo
-            ArchiveFoo                           Thu, 2021-12-09 10:22:28 [0b8e9a312bef3f2f6e2d0fc110c196827786c15eba0188738e81697a7fa3b274]
+            ArchiveFoo                           Thu, 2021-12-09 10:22:28 [0b8e9...3b274]
             ...
             ...
 
 
         The following keys are always available:
         The following keys are always available:

+ 3 - 2
src/borg/cache.py

@@ -895,8 +895,9 @@ class LocalCache(CacheStatsMixin):
 
 
         self.begin_txn()
         self.begin_txn()
         with cache_if_remote(self.repository, decrypted_cache=self.repo_objs) as decrypted_repository:
         with cache_if_remote(self.repository, decrypted_cache=self.repo_objs) as decrypted_repository:
-            # TEMPORARY HACK: to avoid archive index caching, create a FILE named ~/.cache/borg/REPOID/chunks.archive.d -
-            # this is only recommended if you have a fast, low latency connection to your repo (e.g. if repo is local disk)
+            # TEMPORARY HACK:
+            # to avoid archive index caching, create a FILE named ~/.cache/borg/REPOID/chunks.archive.d -
+            # this is only recommended if you have a fast, low latency connection to your repo (e.g. if repo is local).
             self.do_cache = os.path.isdir(archive_path)
             self.do_cache = os.path.isdir(archive_path)
             self.chunks = create_master_idx(self.chunks)
             self.chunks = create_master_idx(self.chunks)
 
 

+ 1 - 1
src/borg/helpers/parseformat.py

@@ -456,7 +456,7 @@ class Location:
         (?:file://)?                                        # optional file protocol
         (?:file://)?                                        # optional file protocol
         (?P<path>
         (?P<path>
             (?:[a-zA-Z]:)?                                  # Drive letter followed by a colon (optional)
             (?:[a-zA-Z]:)?                                  # Drive letter followed by a colon (optional)
-            (?:[^:]+)                                       # Anything which does not contain a :, at least one character
+            (?:[^:]+)                                       # Anything which does not contain a :, at least one char
         )
         )
         """,
         """,
         re.VERBOSE,
         re.VERBOSE,

+ 3 - 4
src/borg/helpers/shellpattern.py

@@ -6,10 +6,9 @@ from queue import LifoQueue
 def translate(pat, match_end=r"\Z"):
 def translate(pat, match_end=r"\Z"):
     """Translate a shell-style pattern to a regular expression.
     """Translate a shell-style pattern to a regular expression.
 
 
-    The pattern may include ``**<sep>`` (<sep> stands for the platform-specific path separator; "/" on POSIX systems) for
-    matching zero or more directory levels and "*" for matching zero or more arbitrary characters with the exception of
-    any path separator. Wrap meta-characters in brackets for a literal match (i.e. "[?]" to match the literal character
-    "?").
+    The pattern may include ``**<sep>`` (<sep> stands for the platform-specific path separator; "/" on POSIX systems)
+    for matching zero or more directory levels and "*" for matching zero or more arbitrary characters except any path
+    separator. Wrap meta-characters in brackets for a literal match (i.e. "[?]" to match the literal character "?").
 
 
     Using match_end=regex one can give a regular expression that is used to match after the regex that is generated from
     Using match_end=regex one can give a regular expression that is used to match after the regex that is generated from
     the pattern. The default is to match the end of the string.
     the pattern. The default is to match the end of the string.

+ 2 - 1
src/borg/manifest.py

@@ -164,7 +164,8 @@ class Archives(abc.MutableMapping):
         consider_checkpoints = getattr(args, "consider_checkpoints", None)
         consider_checkpoints = getattr(args, "consider_checkpoints", None)
         if name is not None:
         if name is not None:
             raise Error(
             raise Error(
-                "Giving a specific name is incompatible with options --first, --last, -a / --match-archives, and --consider-checkpoints."
+                "Giving a specific name is incompatible with options --first, --last, "
+                "-a / --match-archives, and --consider-checkpoints."
             )
             )
         return self.list(
         return self.list(
             sort_by=args.sort_by.split(","),
             sort_by=args.sort_by.split(","),

+ 1 - 1
src/borg/remote.py

@@ -108,7 +108,7 @@ class UnexpectedRPCDataFormatFromServer(Error):
 # All method calls on the remote repository object must be allowlisted in RepositoryServer.rpc_methods and have api
 # All method calls on the remote repository object must be allowlisted in RepositoryServer.rpc_methods and have api
 # stubs in RemoteRepository. The @api decorator on these stubs is used to set server version requirements.
 # stubs in RemoteRepository. The @api decorator on these stubs is used to set server version requirements.
 #
 #
-# Method parameters are identified only by name and never by position. Unknown parameters are ignored by the server side.
+# Method parameters are identified only by name and never by position. Unknown parameters are ignored by the server.
 # If a new parameter is important and may not be ignored, on the client a parameter specific version requirement needs
 # If a new parameter is important and may not be ignored, on the client a parameter specific version requirement needs
 # to be added.
 # to be added.
 # When parameters are removed, they need to be preserved as defaulted parameters on the client stubs so that older
 # When parameters are removed, they need to be preserved as defaulted parameters on the client stubs so that older

+ 8 - 6
src/borg/repository.py

@@ -881,13 +881,15 @@ class Repository:
                         #
                         #
                         # Now we crash. But only segment 2 gets deleted, while segment 1 is still around. Now key 1
                         # Now we crash. But only segment 2 gets deleted, while segment 1 is still around. Now key 1
                         # is suddenly undeleted (because the delete in segment 2 is now missing).
                         # is suddenly undeleted (because the delete in segment 2 is now missing).
-                        # Again, note the requirement here. We delete these in the correct order that this doesn't happen,
-                        # and only if the FS materialization of these deletes is reordered or parts dropped this can happen.
-                        # In this case it doesn't cause outright corruption, 'just' an index count mismatch, which will be
-                        # fixed by borg-check --repair.
+                        # Again, note the requirement here. We delete these in the correct order that this doesn't
+                        # happen, and only if the FS materialization of these deletes is reordered or parts dropped
+                        # this can happen.
+                        # In this case it doesn't cause outright corruption, 'just' an index count mismatch, which
+                        # will be fixed by borg-check --repair.
                         #
                         #
-                        # Note that in this check the index state is the proxy for a "most definitely settled" repository state,
-                        # i.e. the assumption is that *all* operations on segments <= index state are completed and stable.
+                        # Note that in this check the index state is the proxy for a "most definitely settled"
+                        # repository state, i.e. the assumption is that *all* operations on segments <= index state
+                        # are completed and stable.
                         try:
                         try:
                             new_segment, size = self.io.write_delete(key, raise_full=True)
                             new_segment, size = self.io.write_delete(key, raise_full=True)
                         except LoggedIO.SegmentFull:
                         except LoggedIO.SegmentFull:

+ 4 - 2
src/borg/testsuite/crypto.py

@@ -315,7 +315,8 @@ def test_repo_key_detect_does_not_raise_integrity_error(getpass, monkeypatch):
     This is a regression test for a bug I introduced and fixed:
     This is a regression test for a bug I introduced and fixed:
 
 
     Traceback (most recent call last):
     Traceback (most recent call last):
-      File "/home/user/borg-master/src/borg/testsuite/crypto.py", line 384, in test_repo_key_detect_does_not_raise_integrity_error
+      File "/home/user/borg-master/src/borg/testsuite/crypto.py", line 384,
+                                                                  in test_repo_key_detect_does_not_raise_integrity_error
         RepoKey.detect(repository, manifest_data=None)
         RepoKey.detect(repository, manifest_data=None)
       File "/home/user/borg-master/src/borg/crypto/key.py", line 402, in detect
       File "/home/user/borg-master/src/borg/crypto/key.py", line 402, in detect
         if not key.load(target, passphrase):
         if not key.load(target, passphrase):
@@ -335,7 +336,8 @@ def test_repo_key_detect_does_not_raise_integrity_error(getpass, monkeypatch):
 
 
     1. FlexiKey.decrypt_key_file() is supposed to signal the decryption failure by returning None
     1. FlexiKey.decrypt_key_file() is supposed to signal the decryption failure by returning None
     2. FlexiKey.detect() relies on that interface - it tries an empty passphrase before prompting the user
     2. FlexiKey.detect() relies on that interface - it tries an empty passphrase before prompting the user
-    3. my initial implementation of decrypt_key_file_argon2() was simply passing through the IntegrityError() from AES256_CTR_BASE.decrypt()
+    3. my initial implementation of decrypt_key_file_argon2() was simply passing through the IntegrityError()
+       from AES256_CTR_BASE.decrypt()
     """
     """
     repository = MagicMock(id=b"repository_id")
     repository = MagicMock(id=b"repository_id")
     getpass.return_value = "hello, pass phrase"
     getpass.return_value = "hello, pass phrase"

+ 4 - 2
src/borg/testsuite/helpers.py

@@ -178,11 +178,13 @@ class TestLocationWithoutEnv:
         )
         )
         assert (
         assert (
             repr(Location("ssh://user@[2a02:0001:0002:0003:0004:0005:0006:0007]/some/path"))
             repr(Location("ssh://user@[2a02:0001:0002:0003:0004:0005:0006:0007]/some/path"))
-            == "Location(proto='ssh', user='user', host='2a02:0001:0002:0003:0004:0005:0006:0007', port=None, path='/some/path')"
+            == "Location(proto='ssh', user='user', "
+            "host='2a02:0001:0002:0003:0004:0005:0006:0007', port=None, path='/some/path')"
         )
         )
         assert (
         assert (
             repr(Location("ssh://user@[2a02:0001:0002:0003:0004:0005:0006:0007]:1234/some/path"))
             repr(Location("ssh://user@[2a02:0001:0002:0003:0004:0005:0006:0007]:1234/some/path"))
-            == "Location(proto='ssh', user='user', host='2a02:0001:0002:0003:0004:0005:0006:0007', port=1234, path='/some/path')"
+            == "Location(proto='ssh', user='user', "
+            "host='2a02:0001:0002:0003:0004:0005:0006:0007', port=1234, path='/some/path')"
         )
         )
 
 
     def test_socket(self, monkeypatch, keys_dir):
     def test_socket(self, monkeypatch, keys_dir):

+ 9 - 9
src/borg/testsuite/locking.py

@@ -148,19 +148,19 @@ class TestExclusiveLock:
             while not timer.timed_out():
             while not timer.timed_out():
                 cycle += 1
                 cycle += 1
                 try:
                 try:
-                    with ExclusiveLock(
-                        lockpath, id=id, timeout=timeout / 20, sleep=-1
-                    ):  # This timeout is only for not exceeding the given timeout by more than 5%. With sleep<0 it's constantly polling anyway.
+                    # This timeout is only for not exceeding the given timeout by more than 5%.
+                    # With sleep<0 it's constantly polling anyway.
+                    with ExclusiveLock(lockpath, id=id, timeout=timeout / 20, sleep=-1):
                         lock_owner_count = lock_owner_counter.incr()
                         lock_owner_count = lock_owner_counter.incr()
                         print_locked(
                         print_locked(
-                            "Thread %2d: Acquired the lock. It's my %d. loop cycle. I am the %d. who has the lock concurrently."
-                            % (thread_id, cycle, lock_owner_count)
+                            "Thread %2d: Acquired the lock. It's my %d. loop cycle. "
+                            "I am the %d. who has the lock concurrently." % (thread_id, cycle, lock_owner_count)
                         )
                         )
                         time.sleep(0.005)
                         time.sleep(0.005)
                         lock_owner_count = lock_owner_counter.decr()
                         lock_owner_count = lock_owner_counter.decr()
                         print_locked(
                         print_locked(
-                            "Thread %2d: Releasing the lock, finishing my %d. loop cycle. Currently, %d colleagues still have the lock."
-                            % (thread_id, cycle, lock_owner_count)
+                            "Thread %2d: Releasing the lock, finishing my %d. loop cycle. "
+                            "Currently, %d colleagues still have the lock." % (thread_id, cycle, lock_owner_count)
                         )
                         )
                 except LockTimeout:
                 except LockTimeout:
                     print_locked("Thread %2d: Got LockTimeout, finishing my %d. loop cycle." % (thread_id, cycle))
                     print_locked("Thread %2d: Got LockTimeout, finishing my %d. loop cycle." % (thread_id, cycle))
@@ -168,8 +168,8 @@ class TestExclusiveLock:
                     exception_count = exception_counter.incr()
                     exception_count = exception_counter.incr()
                     e = format_exc()
                     e = format_exc()
                     print_locked(
                     print_locked(
-                        "Thread %2d: Exception thrown, finishing my %d. loop cycle. It's the %d. exception seen until now: %s"
-                        % (thread_id, cycle, exception_count, e)
+                        "Thread %2d: Exception thrown, finishing my %d. loop cycle. "
+                        "It's the %d. exception seen until now: %s" % (thread_id, cycle, exception_count, e)
                     )
                     )
 
 
             print_locked("Thread %2d: Loop timed out--terminating after %d loop cycles." % (thread_id, cycle))
             print_locked("Thread %2d: Loop timed out--terminating after %d loop cycles." % (thread_id, cycle))

+ 6 - 2
src/borg/testsuite/platform.py

@@ -186,7 +186,9 @@ class PlatformDarwinTestCase(BaseTestCase):
         self.assert_equal(self.get_acl(file.name), {})
         self.assert_equal(self.get_acl(file.name), {})
         self.set_acl(
         self.set_acl(
             file.name,
             file.name,
-            b"!#acl 1\ngroup:ABCDEFAB-CDEF-ABCD-EFAB-CDEF00000000:staff:0:allow:read\nuser:FFFFEEEE-DDDD-CCCC-BBBB-AAAA00000000:root:0:allow:read\n",
+            b"!#acl 1\n"
+            b"group:ABCDEFAB-CDEF-ABCD-EFAB-CDEF00000000:staff:0:allow:read\n"
+            b"user:FFFFEEEE-DDDD-CCCC-BBBB-AAAA00000000:root:0:allow:read\n",
             numeric_ids=False,
             numeric_ids=False,
         )
         )
         self.assert_in(
         self.assert_in(
@@ -197,7 +199,9 @@ class PlatformDarwinTestCase(BaseTestCase):
         )
         )
         self.set_acl(
         self.set_acl(
             file2.name,
             file2.name,
-            b"!#acl 1\ngroup:ABCDEFAB-CDEF-ABCD-EFAB-CDEF00000000:staff:0:allow:read\nuser:FFFFEEEE-DDDD-CCCC-BBBB-AAAA00000000:root:0:allow:read\n",
+            b"!#acl 1\n"
+            b"group:ABCDEFAB-CDEF-ABCD-EFAB-CDEF00000000:staff:0:allow:read\n"
+            b"user:FFFFEEEE-DDDD-CCCC-BBBB-AAAA00000000:root:0:allow:read\n",
             numeric_ids=True,
             numeric_ids=True,
         )
         )
         self.assert_in(
         self.assert_in(