Re: Duplicity 3.1.0 Released
Scott Hannahs via Duplicity-talk <[email protected]> Mon, 6 Jul 2026 15:07:42 -0400
| Newsgroups | gmane.comp.sysutils.backup.duplicity.general |
|---|---|
| Message-ID | <[email protected]> |
--===============0859283185533763876== Content-Type: multipart/alternative; boundary="Apple-Mail=_CA0E208F-7C71-45E2-A0A2-52EE33D87FA6" --Apple-Mail=_CA0E208F-7C71-45E2-A0A2-52EE33D87FA6 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset=utf-8 And one more last thing=E2=80=A6. I also had a dependency on the =E2=80=9Clxml2=E2=80=9D python module. = Is that also not necessary now? I think we had an email discussion = about this module a long time ago and concluded that it was necessary = for duplicity itself and not one of the other modules. -Scott > On Jul 6, 2026, at 3:03=E2=80=AFPM, Scott Hannahs via Duplicity-talk = <[email protected]> wrote: >=20 > I have and severely changed my requirements since the last update. = But I have a few questions. >=20 > 1. what are the non-python requirements? I have the following in = previous versions, and I am sure that the gnupg2 is needed. > librsync2-shlibs (>=3D 2.0), > librsync-bin (>=3D 2.0), > gnupg2, > intltool40, > par2, >=20 >=20 > 2. to support ftp backups and other non-python backends I had these = were also required? > ncftp, > lftp, >=20 > Are these also no longer part of the duplicity backends? The = requirements.txt and requirements.dev seem limited. >=20 > -Scott >=20 >> On Jun 28, 2026, at 2:29=E2=80=AFPM, Kenneth Loafman via = Duplicity-talk <[email protected]> wrote: >>=20 >> Hi Scott. >>=20 >> 1. and 2. run fine with pylint=3D=3D4.0.5, black=3D=3D26.31 >>=20 >> 3. I really do not know why it is failing. >>=20 >> Take a look at requirements.dev <http://requirements.dev/> and = requirements.txt. You might want to do: >>=20 >> $ python3 -m pip install --update -r requirements.dev = <http://requirements.dev/> >> $ python3 -m pip install --update -r requirements.txt >> $ python3 -m pip install . # while in the duplicity directory >> =20 >> as this will guarantee we're using the same environment. At least = you can figure out what versions you need. >>=20 >> ...Ken >>=20 >>=20 >> On Fri, Jun 26, 2026 at 10:53=E2=80=AFAM Scott Hannahs via = Duplicity-talk <[email protected] = <mailto:[email protected]>> wrote: >>> Thanks for the update. Trying to adjust my fink-project build = system for this. I get a couple of failures when running the suite of = tests. I know the pylint and the black tests are not necessary but I = dislike failures in my output. Put it down to programmer OCD. I am = sure the tests all passed on your system before you released it, but I = am curious what is different on my system that all but these 3 tests = would pass. I am using python 3.10 and pylint 2.14.5. Now updating = pylint (and astroid) to current version. >>>=20 >>> 1. pylint fails. It seems that building in a deep directory = hierarchy causes python to abbreviate the strings with a =E2=80=98=E2=80=A6= =E2=80=99 ellipsis. This of course causes all sorts of failures when = the command line is called: >>> pylint = --rcfile=3D/opt/sw/src/fink.build/duplicity-3.1.0-1/duplicity-rel.3.1.0/py= project.toml /opt/sw/src/fink.b...l.3.1.0/duplicity/backend.py = /opt/sw/src/fink.build/duplicity-3.1.0-1/duplicity-rel.3.1.0/duplicity/con= fig.py >>>=20 >>> The underlined text should be = '/fink.build/duplicity-3.1.0-1/duplicity-rel.3.1.0/=E2=80=98 but even = when using the full correct path, pylint gives me this error in the toml = file. I assume that the paths are abbreviated just for error logging = and the code is using the full paths? >>> pyproject.toml:1: [W0012(unknown-option-value), ] Unknown option = value for '--disable', expected a valid pylint message and got = 'possibly-used-before-assignment=E2=80=99 >>>=20 >>> Standard error output: >>> ----------------------------- Captured stderr call = ----------------------------- >>> ************* Module = /opt/sw/src/fink.build/duplicity-3.1.0-1/duplicity-rel.3.1.0/pyproject.tom= l >>> = /opt/sw/src/fink.build/duplicity-3.1.0-1/duplicity-rel.3.1.0/pyproject.tom= l:1: [W0012(unknown-option-value), ] Unknown option value for = '--disable', expected a valid pylint message and got = 'possibly-used-before-assignment' >>> ************* Module duplicity.statistics >>> = /opt/sw/src/fink.build/duplicity-3.1.0-1/duplicity-rel.3.1.0/duplicity/sta= tistics.py:154: [E1307(bad-string-format-type), = StatsObj.get_timestats_string] Argument 'builtins.NoneType' does not = match format type 'f' >>> = /opt/sw/src/fink.build/duplicity-3.1.0-1/duplicity-rel.3.1.0/duplicity/sta= tistics.py:162: [E1307(bad-string-format-type), = StatsObj.get_timestats_string] Argument 'builtins.NoneType' does not = match format type 'f' >>> ************* Module duplicity.backends.gdrivebackend >>> = /opt/sw/src/fink.build/duplicity-3.1.0-1/duplicity-rel.3.1.0/duplicity/bac= kends/gdrivebackend.py:102: [E0401(import-error), = GDriveBackend.__init__] Unable to import 'google_auth_oauthlib.flow' >>> = /opt/sw/src/fink.build/duplicity-3.1.0-1/duplicity-rel.3.1.0/duplicity/bac= kends/gdrivebackend.py:103: [E0401(import-error), = GDriveBackend.__init__] Unable to import = 'google.auth.transport.requests' >>> = /opt/sw/src/fink.build/duplicity-3.1.0-1/duplicity-rel.3.1.0/duplicity/bac= kends/gdrivebackend.py:217: [E0401(import-error), = GDriveBackend.file_by_name] Unable to import 'googleapiclient.errors' >>> = /opt/sw/src/fink.build/duplicity-3.1.0-1/duplicity-rel.3.1.0/duplicity/bac= kends/gdrivebackend.py:286: [E0401(import-error), GDriveBackend._put] = Unable to import 'googleapiclient.http' >>> = /opt/sw/src/fink.build/duplicity-3.1.0-1/duplicity-rel.3.1.0/duplicity/bac= kends/gdrivebackend.py:335: [E0401(import-error), GDriveBackend._get] = Unable to import 'googleapiclient.http' >>> = /opt/sw/src/fink.build/duplicity-3.1.0-1/duplicity-rel.3.1.0/duplicity/bac= kends/gdrivebackend.py:402: [E0401(import-error), = GDriveBackend._error_code] Unable to import 'google.auth.exceptions' >>> = /opt/sw/src/fink.build/duplicity-3.1.0-1/duplicity-rel.3.1.0/duplicity/bac= kends/gdrivebackend.py:403: [E0401(import-error), = GDriveBackend._error_code] Unable to import 'googleapiclient.errors' >>> ************* Module duplicity.backends.pydrivebackend >>> = /opt/sw/src/fink.build/duplicity-3.1.0-1/duplicity-rel.3.1.0/duplicity/bac= kends/pydrivebackend.py:279: [E0401(import-error), = PyDriveBackend._error_code] Unable to import 'pydrive2.files' >>> ************* Module duplicity.backends.azurebackend >>> = /opt/sw/src/fink.build/duplicity-3.1.0-1/duplicity-rel.3.1.0/duplicity/bac= kends/azurebackend.py:86: [E0401(import-error), = AzureBackend._get_or_create_container] Unable to import = 'azure.core.exceptions' >>>=20 >>>=20 >>> 2. black fails too, probably for the same reason and I will try to = fix it if I can get a resolution to the pylint issue. >>>=20 >>> 3. This is further on a specific test for a code regression number = 908. I am including the long log here because I am not sure what is = relevant. >>>=20 >>> testing/functional/test_regression.py::RegressionTest::test_issue908 = FAILED [ 72%] >>> =E2=80=94=E2=80=94 >>> _________________________ RegressionTest.test_issue908 = _________________________ >>>=20 >>> self =3D <testing.functional.test_regression.RegressionTest = testMethod=3Dtest_issue908> >>>=20 >>> @unittest.skipIf(os.path.exists("/.dockerenv"), "Won't work on = docker") >>> def test_issue908(self): >>> """ >>> Test issue 908 - gpg: public key decryption failed: No = passphrase given (3.0.6.2) >>> """ >>> =20 >>> # make sure we test with a clean cache and clean output >>> self.set_environ("FTP_PASSWORD", None) >>> self.set_environ("PASSPHRASE", None) >>> self.set_environ("SIGN_PASSPHRASE", None) >>> self.set_environ("TESTDEBUG", None) >>> shutil.rmtree(f"{_runtest_dir}/testfiles/cache/issue908", = ignore_errors=3DTrue) >>> shutil.rmtree(f"{_runtest_dir}/testfiles/output", = ignore_errors=3DTrue) >>> =20 >>> # do initial full backup with passphrase >>> self.backup( >>> "full", >>> f"{_runtest_dir}/testfiles/various_file_types", >>> options=3D["--name=3Dissue908", = f"--encrypt-key=3D{self.encrypt_key1}"], >>> ) >>> =20 >>> # make sure inc has somthing to do >>> = os.unlink(f"{_runtest_dir}/testfiles/various_file_types/executable") >>> =20 >>> # do incremental backup >>> > self.backup( >>> "inc", >>> f"{_runtest_dir}/testfiles/various_file_types", >>> options=3D["--name=3Dissue908", = f"--encrypt-key=3D{self.encrypt_key1}"], >>> passphrase_input=3D[self.sign_passphrase], >>> ) >>>=20 >>> self =3D <testing.functional.test_regression.RegressionTest = testMethod=3Dtest_issue908> >>>=20 >>> = /opt/sw/src/fink.build/duplicity-3.1.0-1/duplicity-rel.3.1.0/testing/funct= ional/test_regression.py:154:=20 >>> _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ = _ _ _ _ _ _=20 >>> = /opt/sw/src/fink.build/duplicity-3.1.0-1/duplicity-rel.3.1.0/testing/funct= ional/__init__.py:197: in backup >>> self.run_duplicity(options=3Doptions, **kwargs) >>> before_files =3D = {b'duplicity-full-signatures.20260616T174134Z.sigtar.gpg', = b'duplicity-full.20260616T174134Z.manifest.gpg', = b'duplicity-full.20260616T174134Z.vol1.difftar.gpg'} >>> input_dir =3D = '/var/folders/6b/85yg9bp94rv55dzbdp78thp40000kr/T/testfiles/various_file_t= ypes' >>> kwargs =3D {'passphrase_input': ['test']} >>> now =3D 1781631694.437021 >>> options =3D ['inc', = '/var/folders/6b/85yg9bp94rv55dzbdp78thp40000kr/T/testfiles/various_file_t= ypes', = 'fortestsonly:///var/folders/6b/85yg9bp94rv55dzbdp78thp40000kr/T/testfiles= /output', '--volsize=3D1', '--name=3Dissue908', = '--encrypt-key=3D839E6A2856538CCF'] >>> self =3D = <testing.functional.test_regression.RegressionTest = testMethod=3Dtest_issue908> >>> type =3D 'inc' >>> = /opt/sw/src/fink.build/duplicity-3.1.0-1/duplicity-rel.3.1.0/testing/funct= ional/__init__.py:159: in run_duplicity >>> child.expect("passphrase.*:") >>> child =3D <pexpect.pty_spawn.spawn object at = 0x10abc27a0> >>> cmd_list =3D ['/opt/sw/bin/python3.10', '-W', 'ignore', = '-u', = '/opt/sw/src/fink.build/duplicity-3.1.0-1/duplicity-rel.3.1.0/duplicity/__= main__.py', 'inc', ...] >>> cmdline =3D "'/opt/sw/bin/python3.10' '-W' 'ignore' '-u' = '/opt/sw/src/fink.build/duplicity-3.1.0-1/duplicity-rel.3.1.0/duplicity/_.= ..538CCF' '-v0' '--no-print-statistics' = '--archive-dir=3D/var/folders/6b/85yg9bp94rv55dzbdp78thp40000kr/T/testfile= s/cache'" >>> current_time =3D None >>> dup_env =3D {'CCACHE_DIR': '/opt/sw/var/ccache', = 'CPPFLAGS': '-I/opt/sw/include', 'DBUS_SESSION_BUS_ADDRESS': = 'launchd:env=3DDBUS_FINK_SESSION_BUS_SOCKET', 'GNUPGHOME': = '/opt/sw/src/fink.build/duplicity-3.1.0-1/duplicity-rel.3.1.0/testing/gnup= g', ...} >>> fail =3D None >>> item =3D 'test' >>> options =3D ['inc', = '/var/folders/6b/85yg9bp94rv55dzbdp78thp40000kr/T/testfiles/various_file_t= ypes', = 'fortestsonly:///var/folders/6b/85yg9bp94rv55dzbdp78thp40000kr/T/testfiles= /output', '--volsize=3D1', '--name=3Dissue908', = '--encrypt-key=3D839E6A2856538CCF'] >>> passphrase =3D 'test' >>> passphrase_input =3D ['test'] >>> self =3D = <testing.functional.test_regression.RegressionTest = testMethod=3Dtest_issue908> >>> timeout =3D None >>> /opt/sw/lib/python3.10/site-packages/pexpect/spawnbase.py:343: in = expect >>> return self.expect_list(compiled_pattern_list, >>> async_ =3D False >>> compiled_pattern_list =3D [re.compile(b'passphrase.*:', = re.DOTALL)] >>> kw =3D {} >>> pattern =3D 'passphrase.*:' >>> searchwindowsize =3D -1 >>> self =3D <pexpect.pty_spawn.spawn object at = 0x10abc27a0> >>> timeout =3D -1 >>> /opt/sw/lib/python3.10/site-packages/pexpect/spawnbase.py:372: in = expect_list >>> return exp.expect_loop(timeout) >>> async_ =3D False >>> exp =3D <pexpect.expect.Expecter object at = 0x109e4ff40> >>> kw =3D {} >>> pattern_list =3D [re.compile(b'passphrase.*:', re.DOTALL)] >>> searchwindowsize =3D -1 >>> self =3D <pexpect.pty_spawn.spawn object at = 0x10abc27a0> >>> timeout =3D None >>> /opt/sw/lib/python3.10/site-packages/pexpect/expect.py:179: in = expect_loop >>> return self.eof(e) >>> idx =3D None >>> self =3D <pexpect.expect.Expecter object at = 0x109e4ff40> >>> spawn =3D <pexpect.pty_spawn.spawn object at = 0x10abc27a0> >>> timeout =3D None >>> _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ = _ _ _ _ _ _=20 >>>=20 >>> self =3D <pexpect.expect.Expecter object at 0x109e4ff40> >>> err =3D EOF('End Of File (EOF). Empty string style platform.') >>>=20 >>> def eof(self, err=3DNone): >>> spawn =3D self.spawn >>> =20 >>> spawn.before =3D spawn._before.getvalue() >>> spawn._buffer =3D spawn.buffer_type() >>> spawn._before =3D spawn.buffer_type() >>> spawn.after =3D EOF >>> index =3D self.searcher.eof_index >>> if index >=3D 0: >>> spawn.match =3D EOF >>> spawn.match_index =3D index >>> return index >>> else: >>> spawn.match =3D None >>> spawn.match_index =3D None >>> msg =3D str(spawn) >>> msg +=3D '\nsearcher: %s' % self.searcher >>> if err is not None: >>> msg =3D str(err) + '\n' + msg >>> =20 >>> exc =3D EOF(msg) >>> exc.__cause__ =3D None # in Python 3.x we can use "raise = exc from None" >>> > raise exc >>> E pexpect.exceptions.EOF: End Of File (EOF). Empty string = style platform. >>> E <pexpect.pty_spawn.spawn object at 0x10abc27a0> >>> E command: /bin/sh >>> E args: ['/bin/sh', '-f', '-c', "'/opt/sw/bin/python3.10' = '-W' 'ignore' '-u' = '/opt/sw/src/fink.build/duplicity-3.1.0-1/duplicity-rel.3.1.0/duplicity/__= main__.py' 'inc' = '/var/folders/6b/85yg9bp94rv55dzbdp78thp40000kr/T/testfiles/various_file_t= ypes' = 'fortestsonly:///var/folders/6b/85yg9bp94rv55dzbdp78thp40000kr/T/testfiles= /output' '--volsize=3D1' '--name=3Dissue908' = '--encrypt-key=3D839E6A2856538CCF' '-v0' '--no-print-statistics' = '--archive-dir=3D/var/folders/6b/85yg9bp94rv55dzbdp78thp40000kr/T/testfile= s/cache'"] >>> E buffer (last 100 chars): b'' >>> E before (last 100 chars): '' >>> E after: <class 'pexpect.exceptions.EOF'> >>> E match: None >>> E match_index: None >>> E exitstatus: None >>> E flag_eof: True >>> E pid: 45404 >>> E child_fd: 191 >>> E closed: False >>> E timeout: None >>> E delimiter: <class 'pexpect.exceptions.EOF'> >>> E logfile: None >>> E logfile_read: None >>> E logfile_send: None >>> E maxread: 2000 >>> E ignorecase: False >>> E searchwindowsize: None >>> E delaybeforesend: 0.05 >>> E delayafterclose: 0.1 >>> E delayafterterminate: 0.1 >>> E searcher: searcher_re: >>> E 0: re.compile(b'passphrase.*:') >>>=20 >>> err =3D EOF('End Of File (EOF). Empty string style = platform.') >>> exc =3D EOF('End Of File (EOF). Empty string style = platform.\n<pexpect.pty_spawn.spawn object at 0x10abc27a0>\ncommand: = /bin/s...: 0.05\ndelayafterclose: 0.1\ndelayafterterminate: = 0.1\nsearcher: searcher_re:\n 0: re.compile(b\'passphrase.*:\')') >>> index =3D -1 >>> msg =3D "End Of File (EOF). Empty string style = platform.\n<pexpect.pty_spawn.spawn object at 0x10abc27a0>\ncommand: = /bin/sh\na...end: 0.05\ndelayafterclose: 0.1\ndelayafterterminate: = 0.1\nsearcher: searcher_re:\n 0: re.compile(b'passphrase.*:')" >>> self =3D <pexpect.expect.Expecter object at 0x109e4ff40> >>> spawn =3D <pexpect.pty_spawn.spawn object at 0x10abc27a0> >>>=20 >>> /opt/sw/lib/python3.10/site-packages/pexpect/expect.py:122: EOF >>> ----------------------------- Captured stdout call = ----------------------------- >>> TestBackend is not made for production use! >>> TestBackend is not made for production use! >>> TestBackend is not made for production use! >>> TestBackend is not made for production use! >>> ----------------------------- Captured stderr call = ----------------------------- >>>=20 >>> ...command: '/opt/sw/bin/python3.10' '-W' 'ignore' '-u' = '/opt/sw/src/fink.build/duplicity-3.1.0-1/duplicity-rel.3.1.0/duplicity/__= main__.py' 'full' = '/var/folders/6b/85yg9bp94rv55dzbdp78thp40000kr/T/testfiles/various_file_t= ypes' = 'fortestsonly:///var/folders/6b/85yg9bp94rv55dzbdp78thp40000kr/T/testfiles= /output' '--volsize=3D1' '--name=3Dissue908' = '--encrypt-key=3D839E6A2856538CCF' '-v0' '--no-print-statistics' = '--archive-dir=3D/var/folders/6b/85yg9bp94rv55dzbdp78thp40000kr/T/testfile= s/cache' < /dev/null >>> ...cwd: /private/var/folders/6b/85yg9bp94rv55dzbdp78thp40000kr/T >>> ...output: >>> ...return_val: 0 >>> ------------------------------ Captured log call = ------------------------------- >>> Level 8 duplicity:log.py:100 TestBackend is not made for production = use! >>> Level 8 duplicity:log.py:100 TestBackend is not made for production = use! >>> Level 8 duplicity:log.py:100 TestBackend is not made for production = use! >>> Level 8 duplicity:log.py:100 TestBackend is not made for production = use! >>> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D short test summary info =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D >>> -Scott >>>=20 >>>> On Jun 16, 2026, at 1:10=E2=80=AFPM, Kenneth Loafman via = Duplicity-talk <[email protected] = <mailto:[email protected]>> wrote: >>>>=20 >>>> Hi everyone, >>>>=20 >>>> I am pleased to announce the release of duplicity version 3.1.0. >>>>=20 >>>> This release follows version 3.0.7 and includes a minor version = bump to reflect a significant new feature. Thanks to elmuz's = contribution, restore operations can now use --include, --exclude, = --include-regexp, and --include-filelist directly from the command line. >>>>=20 >>>> There are many other improvements and bug fixes included in this = update. Please see the CHANGELOG below for full details. >>>>=20 >>>> Thanks, >>>> Ken >>>=20 >>> _______________________________________________ >>> Duplicity-talk mailing list >>> [email protected] <mailto:[email protected]> >>> https://lists.nongnu.org/mailman/listinfo/duplicity-talk >> _______________________________________________ >> Duplicity-talk mailing list >> [email protected] >> https://lists.nongnu.org/mailman/listinfo/duplicity-talk >=20 > _______________________________________________ > Duplicity-talk mailing list > [email protected] > https://lists.nongnu.org/mailman/listinfo/duplicity-talk --Apple-Mail=_CA0E208F-7C71-45E2-A0A2-52EE33D87FA6 Content-Transfer-Encoding: quoted-printable Content-Type: text/html; charset=utf-8 <html aria-label=3D"message body"><head><meta http-equiv=3D"content-type" = content=3D"text/html; charset=3Dutf-8"></head><body = style=3D"overflow-wrap: break-word; -webkit-nbsp-mode: space; = line-break: after-white-space;">And one more last thing=E2=80=A6.<div>I = also had a dependency on the =E2=80=9Clxml2=E2=80=9D python module. = Is that also not necessary now? I think we had an email = discussion about this module a long time ago and concluded that it was = necessary for duplicity itself and not one of the other = modules.</div><div><br></div><div>-Scott</div><div><div><br><blockquote = type=3D"cite"><div>On Jul 6, 2026, at 3:03=E2=80=AFPM, Scott Hannahs via = Duplicity-talk <[email protected]> wrote:</div><br = class=3D"Apple-interchange-newline"><div><meta http-equiv=3D"content-type"= content=3D"text/html; charset=3Dutf-8"><div style=3D"overflow-wrap: = break-word; -webkit-nbsp-mode: space; line-break: after-white-space;">I = have and severely changed my requirements since the last update. = But I have a few questions.<div><br></div><div>1. what are the = non-python requirements? I have the following in previous = versions, and I am sure that the gnupg2 is needed.</div><div><div> = librsync2-shlibs (>=3D 2.0),</div><div> = librsync-bin (>=3D 2.0),</div><div> = gnupg2,</div><div> = intltool40,</div><div><span class=3D"Apple-tab-span" = style=3D"white-space:pre"> = </span>par2,</div><div><br></div><div><br></div><div>2. to support ftp = backups and other non-python backends I had these were also = required?</div><div><div> = ncftp,</div><div> = lftp,</div><div><br></div></div><div>Are these also no longer part of = the duplicity backends? The requirements.txt and requirements.dev = seem = limited.</div><div><br></div><div>-Scott</div><div><br></div><div><blockqu= ote type=3D"cite"><div>On Jun 28, 2026, at 2:29=E2=80=AFPM, Kenneth = Loafman via Duplicity-talk <[email protected]> = wrote:</div><br class=3D"Apple-interchange-newline"><div><div = dir=3D"ltr"><div dir=3D"ltr"><div>Hi Scott.</div><div><br></div><div>1. = and 2. run fine with pylint=3D=3D4.0.5, = black=3D=3D26.31</div><div><br></div><div>3. I really do not know why it = is failing.</div><div><br></div><div>Take a look at <a = href=3D"http://requirements.dev/">requirements.dev</a> and = requirements.txt. You might want to = do:</div><div><br></div><div><font face=3D"monospace" = style=3D"background-color:rgb(238,238,238)">$ python3 -m pip install = --update -r <a = href=3D"http://requirements.dev/">requirements.dev</a></font></div><div><f= ont face=3D"monospace" style=3D"background-color:rgb(238,238,238)">$ = python3 -m pip install --update -r = requirements.txt</font></div><div><font face=3D"monospace" = style=3D"background-color:rgb(238,238,238)">$ python3 -m pip install = . # while in the duplicity = directory</font></div><div> </div><div>as this will guarantee we're = using the same environment. At least you can figure out what = versions you = need.</div><div><br></div><div>...Ken</div><div><br></div><br><div = class=3D"gmail_quote"><div dir=3D"ltr" class=3D"gmail_attr">On Fri, Jun = 26, 2026 at 10:53=E2=80=AFAM Scott Hannahs via Duplicity-talk <<a = href=3D"mailto:[email protected]" = target=3D"_blank">[email protected]</a>> = wrote:<br></div><blockquote class=3D"gmail_quote" style=3D"margin:0px = 0px 0px 0.8ex;border-left:1px solid = rgb(204,204,204);padding-left:1ex"><div><div dir=3D"auto"><div = dir=3D"auto"><div dir=3D"auto"><div dir=3D"auto">Thanks for the = update. Trying to adjust my fink-project build system for = this. I get a couple of failures when running the suite of = tests. I know the pylint and the black tests are not necessary but = I dislike failures in my output. Put it down to programmer = OCD. I am sure the tests all passed on your system before you = released it, but I am curious what is different on my system that all = but these 3 tests would pass. I am using python 3.10 and pylint = 2.14.5. Now updating pylint (and astroid) to current = version.<div><br></div><div>1. pylint fails. It seems that = building in a deep directory hierarchy causes python to abbreviate the = strings with a =E2=80=98=E2=80=A6=E2=80=99 ellipsis. This of = course causes all sorts of failures when the command line is = called:</div><blockquote style=3D"margin:0px 0px 0px = 40px;border-width:medium;border-style:none;border-color:currentcolor;paddi= ng:0px"><div>pylint = --rcfile=3D/opt/sw/src/fink.build/duplicity-3.1.0-1/duplicity-rel.3.1.0/py= project.toml /opt/sw/src/<b = style=3D"font-size:16px"><u>fink.b...l.3.1.0</u></b>/duplicity/backend.py = /opt/sw/src/fink.build/duplicity-3.1.0-1/duplicity-rel.3.1.0/duplicity/con= fig.py</div></blockquote><div><div><br></div><div>The underlined text = should be '/fink.build/duplicity-3.1.0-1/duplicity-rel.3.1.0/=E2=80=98 = but even when using the full correct path, pylint gives me this error in = the toml file. I assume that the paths are abbreviated just for = error logging and the code is using the full = paths?</div></div><blockquote style=3D"margin:0px 0px 0px = 40px;border-width:medium;border-style:none;border-color:currentcolor;paddi= ng:0px"><div><div>pyproject.toml:1: [W0012(unknown-option-value), ] = Unknown option value for '--disable', expected a valid pylint message = and got = 'possibly-used-before-assignment=E2=80=99</div></div><div><br></div></bloc= kquote><div>Standard error output:</div><blockquote style=3D"margin:0px = 0px 0px = 40px;border-width:medium;border-style:none;border-color:currentcolor;paddi= ng:0px"><div><div>----------------------------- Captured stderr call = -----------------------------</div><div>************* Module = /opt/sw/src/fink.build/duplicity-3.1.0-1/duplicity-rel.3.1.0/pyproject.tom= l</div><div = style=3D"font-size:16px"><b>/opt/sw/src/fink.build/duplicity-3.1.0-1/dupli= city-rel.3.1.0/pyproject.toml:1: [W0012(unknown-option-value), ] Unknown = option value for '--disable', expected a valid pylint message and got = 'possibly-used-before-assignment'</b></div><div>************* Module = duplicity.statistics</div><div>/opt/sw/src/fink.build/duplicity-3.1.0-1/du= plicity-rel.3.1.0/duplicity/statistics.py:154: = [E1307(bad-string-format-type), StatsObj.get_timestats_string] Argument = 'builtins.NoneType' does not match format type = 'f'</div><div>/opt/sw/src/fink.build/duplicity-3.1.0-1/duplicity-rel.3.1.0= /duplicity/statistics.py:162: [E1307(bad-string-format-type), = StatsObj.get_timestats_string] Argument 'builtins.NoneType' does not = match format type 'f'</div><div>************* Module = duplicity.backends.gdrivebackend</div><div>/opt/sw/src/fink.build/duplicit= y-3.1.0-1/duplicity-rel.3.1.0/duplicity/backends/gdrivebackend.py:102: = [E0401(import-error), GDriveBackend.__init__] Unable to import = 'google_auth_oauthlib.flow'</div><div>/opt/sw/src/fink.build/duplicity-3.1= .0-1/duplicity-rel.3.1.0/duplicity/backends/gdrivebackend.py:103: = [E0401(import-error), GDriveBackend.__init__] Unable to import = 'google.auth.transport.requests'</div><div>/opt/sw/src/fink.build/duplicit= y-3.1.0-1/duplicity-rel.3.1.0/duplicity/backends/gdrivebackend.py:217: = [E0401(import-error), GDriveBackend.file_by_name] Unable to import = 'googleapiclient.errors'</div><div>/opt/sw/src/fink.build/duplicity-3.1.0-= 1/duplicity-rel.3.1.0/duplicity/backends/gdrivebackend.py:286: = [E0401(import-error), GDriveBackend._put] Unable to import = 'googleapiclient.http'</div><div>/opt/sw/src/fink.build/duplicity-3.1.0-1/= duplicity-rel.3.1.0/duplicity/backends/gdrivebackend.py:335: = [E0401(import-error), GDriveBackend._get] Unable to import = 'googleapiclient.http'</div><div>/opt/sw/src/fink.build/duplicity-3.1.0-1/= duplicity-rel.3.1.0/duplicity/backends/gdrivebackend.py:402: = [E0401(import-error), GDriveBackend._error_code] Unable to import = 'google.auth.exceptions'</div><div>/opt/sw/src/fink.build/duplicity-3.1.0-= 1/duplicity-rel.3.1.0/duplicity/backends/gdrivebackend.py:403: = [E0401(import-error), GDriveBackend._error_code] Unable to import = 'googleapiclient.errors'</div><div>************* Module = duplicity.backends.pydrivebackend</div><div>/opt/sw/src/fink.build/duplici= ty-3.1.0-1/duplicity-rel.3.1.0/duplicity/backends/pydrivebackend.py:279: = [E0401(import-error), PyDriveBackend._error_code] Unable to import = 'pydrive2.files'</div><div>************* Module = duplicity.backends.azurebackend</div><div>/opt/sw/src/fink.build/duplicity= -3.1.0-1/duplicity-rel.3.1.0/duplicity/backends/azurebackend.py:86: = [E0401(import-error), AzureBackend._get_or_create_container] Unable to = import = 'azure.core.exceptions'</div><div><br></div></div></blockquote><div><div><= br></div><div>2. black fails too, probably for the same reason and I = will try to fix it if I can get a resolution to the pylint = issue.</div><div><br></div><div>3. This is further on a specific test = for a code regression number 908. I am including the long log here = because I am not sure what is = relevant.</div></div><div><br></div><blockquote style=3D"margin:0px 0px = 0px = 40px;border-width:medium;border-style:none;border-color:currentcolor;paddi= ng:0px"><div><div>testing/functional/test_regression.py::RegressionTest::t= est_issue908 FAILED [ = 72%]</div></div><div>=E2=80=94=E2=80=94</div><div><div>___________________= ______ RegressionTest.test_issue908 = _________________________</div><div><br></div><div>self =3D = <testing.functional.test_regression.RegressionTest = testMethod=3Dtest_issue908></div><div><br></div><div> = @unittest.skipIf(os.path.exists("/.dockerenv"), "Won't work on = docker")</div><div> def = test_issue908(self):</div><div> = """</div><div> Test issue 908 - gpg: public = key decryption failed: No passphrase given (3.0.6.2)</div><div> = """</div><div> </div><div> = # make sure we test with a clean cache and clean = output</div><div> = self.set_environ("FTP_PASSWORD", None)</div><div> = self.set_environ("PASSPHRASE", None)</div><div> = self.set_environ("SIGN_PASSPHRASE", None)</div><div> = self.set_environ("TESTDEBUG", = None)</div><div> = shutil.rmtree(f"{_runtest_dir}/testfiles/cache/issue908", = ignore_errors=3DTrue)</div><div> = shutil.rmtree(f"{_runtest_dir}/testfiles/output", = ignore_errors=3DTrue)</div><div> </div><div> = # do initial full backup with = passphrase</div><div> = self.backup(</div><div> = "full",</div><div> = f"{_runtest_dir}/testfiles/various_file_types",</div><div> = options=3D["--name=3Dissue908", = f"--encrypt-key=3D{self.encrypt_key1}"],</div><div> = )</div><div> </div><div> = # make sure inc has somthing to do</div><div> = = os.unlink(f"{_runtest_dir}/testfiles/various_file_types/executable")</div>= <div> </div><div> # do = incremental backup</div><div>> = self.backup(</div><div> = "inc",</div><div> = f"{_runtest_dir}/testfiles/various_file_types",</div><div> = options=3D["--name=3Dissue908", = f"--encrypt-key=3D{self.encrypt_key1}"],</div><div> = = passphrase_input=3D[self.sign_passphrase],</div><div> = )</div><div><br></div><div>self =3D = <testing.functional.test_regression.RegressionTest = testMethod=3Dtest_issue908></div><div><br></div><div>/opt/sw/src/fink.b= uild/duplicity-3.1.0-1/duplicity-rel.3.1.0/testing/functional/test_regress= ion.py:154: </div><div>_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ = _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ = _ </div><div><div>/opt/sw/src/fink.build/duplicity-3.1.0-1/duplicity-= rel.3.1.0/testing/functional/__init__.py:197: in backup</div><div> = self.run_duplicity(options=3Doptions, **kwargs)</div><div> = before_files =3D = {b'duplicity-full-signatures.20260616T174134Z.sigtar.gpg', = b'duplicity-full.20260616T174134Z.manifest.gpg', = b'duplicity-full.20260616T174134Z.vol1.difftar.gpg'}</div><div> = input_dir =3D = '/var/folders/6b/85yg9bp94rv55dzbdp78thp40000kr/T/testfiles/various_file_t= ypes'</div><div> kwargs =3D = {'passphrase_input': ['test']}</div><div> now = =3D 1781631694.437021</div><div> = options =3D ['inc', = '/var/folders/6b/85yg9bp94rv55dzbdp78thp40000kr/T/testfiles/various_file_t= ypes', = 'fortestsonly:///var/folders/6b/85yg9bp94rv55dzbdp78thp40000kr/T/testfiles= /output', '--volsize=3D1', '--name=3Dissue908', = '--encrypt-key=3D839E6A2856538CCF']</div><div> = self =3D = <testing.functional.test_regression.RegressionTest = testMethod=3Dtest_issue908></div><div> = type =3D = 'inc'</div><div>/opt/sw/src/fink.build/duplicity-3.1.0-1/duplicity-rel.3.1= .0/testing/functional/__init__.py:159: in run_duplicity</div><div> = child.expect("passphrase.*:")</div><div> = child =3D <pexpect.pty_spawn.spawn object = at 0x10abc27a0></div><div> cmd_list = =3D ['/opt/sw/bin/python3.10', '-W', 'ignore', '-u', = '/opt/sw/src/fink.build/duplicity-3.1.0-1/duplicity-rel.3.1.0/duplicity/__= main__.py', 'inc', ...]</div><div> cmdline = =3D "'/opt/sw/bin/python3.10' '-W' 'ignore' '-u' = '/opt/sw/src/fink.build/duplicity-3.1.0-1/duplicity-rel.3.1.0/duplicity/_.= ..538CCF' '-v0' '--no-print-statistics' = '--archive-dir=3D/var/folders/6b/85yg9bp94rv55dzbdp78thp40000kr/T/testfile= s/cache'"</div><div> current_time =3D = None</div><div> dup_env =3D = {'CCACHE_DIR': '/opt/sw/var/ccache', 'CPPFLAGS': '-I/opt/sw/include', = 'DBUS_SESSION_BUS_ADDRESS': 'launchd:env=3DDBUS_FINK_SESSION_BUS_SOCKET', = 'GNUPGHOME': = '/opt/sw/src/fink.build/duplicity-3.1.0-1/duplicity-rel.3.1.0/testing/gnup= g', ...}</div><div> fail = =3D None</div><div> item = =3D 'test'</div><div> options =3D = ['inc', = '/var/folders/6b/85yg9bp94rv55dzbdp78thp40000kr/T/testfiles/various_file_t= ypes', = 'fortestsonly:///var/folders/6b/85yg9bp94rv55dzbdp78thp40000kr/T/testfiles= /output', '--volsize=3D1', '--name=3Dissue908', = '--encrypt-key=3D839E6A2856538CCF']</div><div> = passphrase =3D 'test'</div><div> = passphrase_input =3D ['test']</div><div> self = =3D = <testing.functional.test_regression.RegressionTest = testMethod=3Dtest_issue908></div><div> = timeout =3D = None</div><div>/opt/sw/lib/python3.10/site-packages/pexpect/spawnbase.py:3= 43: in expect</div><div> return = self.expect_list(compiled_pattern_list,</div><div> = async_ =3D False</div><div> = compiled_pattern_list =3D [re.compile(b'passphrase.*:', = re.DOTALL)]</div><div> kw = =3D {}</div><div> pattern = =3D 'passphrase.*:'</div><div> = searchwindowsize =3D -1</div><div> self = =3D <pexpect.pty_spawn.spawn object at = 0x10abc27a0></div><div> timeout = =3D = -1</div><div>/opt/sw/lib/python3.10/site-packages/pexpect/spawnbase.py:372= : in expect_list</div><div> return = exp.expect_loop(timeout)</div><div> async_ = =3D False</div><div> exp = =3D <pexpect.expect.Expecter object at = 0x109e4ff40></div><div> kw = =3D {}</div><div> pattern_list = =3D [re.compile(b'passphrase.*:', re.DOTALL)]</div><div> = searchwindowsize =3D -1</div><div> = self =3D <pexpect.pty_spawn.spawn object = at 0x10abc27a0></div><div> timeout = =3D = None</div><div>/opt/sw/lib/python3.10/site-packages/pexpect/expect.py:179:= in expect_loop</div><div> return = self.eof(e)</div><div> idx = =3D None</div><div> self = =3D <pexpect.expect.Expecter object at = 0x109e4ff40></div><div> spawn = =3D <pexpect.pty_spawn.spawn object at = 0x10abc27a0></div><div> timeout = =3D None</div><div>_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ = _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ </div><div><br></div><div>self =3D = <pexpect.expect.Expecter object at 0x109e4ff40></div><div>err =3D = EOF('End Of File (EOF). Empty string style = platform.')</div><div><br></div><div> def eof(self, = err=3DNone):</div><div> spawn =3D = self.spawn</div><div> </div><div> = spawn.before =3D spawn._before.getvalue()</div><div> = spawn._buffer =3D spawn.buffer_type()</div><div> = spawn._before =3D = spawn.buffer_type()</div><div> spawn.after =3D = EOF</div><div> index =3D = self.searcher.eof_index</div><div> if index = >=3D 0:</div><div> = spawn.match =3D EOF</div><div> = spawn.match_index =3D index</div><div> = return index</div><div> = else:</div><div> spawn.match =3D = None</div><div> = spawn.match_index =3D None</div><div> = msg =3D str(spawn)</div><div> = msg +=3D '\nsearcher: %s' % self.searcher</div><div> = if err is not None:</div><div> = msg =3D str(err) + '\n' + = msg</div><div> </div><div> = exc =3D EOF(msg)</div><div> = exc.__cause__ =3D None # in Python 3.x we can use "raise = exc from None"</div><div>> raise = exc</div><div>E = pexpect.exceptions.EOF: End Of File (EOF). Empty string style = platform.</div><div>E = <pexpect.pty_spawn.spawn object at 0x10abc27a0></div><div>E = command: /bin/sh</div><div>E = args: ['/bin/sh', '-f', '-c', = "'/opt/sw/bin/python3.10' '-W' 'ignore' '-u' = '/opt/sw/src/fink.build/duplicity-3.1.0-1/duplicity-rel.3.1.0/duplicity/__= main__.py' 'inc' = '/var/folders/6b/85yg9bp94rv55dzbdp78thp40000kr/T/testfiles/various_file_t= ypes' = 'fortestsonly:///var/folders/6b/85yg9bp94rv55dzbdp78thp40000kr/T/testfiles= /output' '--volsize=3D1' '--name=3Dissue908' = '--encrypt-key=3D839E6A2856538CCF' '-v0' '--no-print-statistics' = '--archive-dir=3D/var/folders/6b/85yg9bp94rv55dzbdp78thp40000kr/T/testfile= s/cache'"]</div><div>E buffer (last = 100 chars): b''</div><div>E before = (last 100 chars): ''</div><div>E = after: <class 'pexpect.exceptions.EOF'></div><div>E = match: None</div><div>E = match_index: None</div><div>E = exitstatus: None</div><div>E = flag_eof: True</div><div>E pid: = 45404</div><div>E child_fd: = 191</div><div>E closed: = False</div><div>E timeout: = None</div><div>E delimiter: <class = 'pexpect.exceptions.EOF'></div><div>E = logfile: None</div><div>E = logfile_read: None</div><div>E = logfile_send: None</div><div>E = maxread: 2000</div><div>E ignorecase: = False</div><div>E searchwindowsize: = None</div><div>E delaybeforesend: = 0.05</div><div>E delayafterclose: = 0.1</div><div>E delayafterterminate: = 0.1</div><div>E searcher: = searcher_re:</div><div>E = 0: re.compile(b'passphrase.*:')</div><div><br></div><div>err = =3D EOF('End Of File (EOF). Empty string = style platform.')</div><div>exc =3D EOF('End = Of File (EOF). Empty string style platform.\n<pexpect.pty_spawn.spawn = object at 0x10abc27a0>\ncommand: /bin/s...: 0.05\ndelayafterclose: = 0.1\ndelayafterterminate: 0.1\nsearcher: searcher_re:\n 0: = re.compile(b\'passphrase.*:\')')</div><div>index =3D = -1</div><div>msg =3D "End Of File (EOF). = Empty string style platform.\n<pexpect.pty_spawn.spawn object at = 0x10abc27a0>\ncommand: /bin/sh\na...end: 0.05\ndelayafterclose: = 0.1\ndelayafterterminate: 0.1\nsearcher: searcher_re:\n 0: = re.compile(b'passphrase.*:')"</div><div>self =3D = <pexpect.expect.Expecter object at 0x109e4ff40></div><div>spawn = =3D <pexpect.pty_spawn.spawn object at = 0x10abc27a0></div><div><br></div><div>/opt/sw/lib/python3.10/site-packa= ges/pexpect/expect.py:122: EOF</div><div>----------------------------- = Captured stdout call -----------------------------</div><div>TestBackend = is not made for production use!</div><div>TestBackend is not made for = production use!</div><div>TestBackend is not made for production = use!</div><div>TestBackend is not made for production = use!</div><div>----------------------------- Captured stderr call = -----------------------------</div><div><br></div><div>...command: = '/opt/sw/bin/python3.10' '-W' 'ignore' '-u' = '/opt/sw/src/fink.build/duplicity-3.1.0-1/duplicity-rel.3.1.0/duplicity/__= main__.py' 'full' = '/var/folders/6b/85yg9bp94rv55dzbdp78thp40000kr/T/testfiles/various_file_t= ypes' = 'fortestsonly:///var/folders/6b/85yg9bp94rv55dzbdp78thp40000kr/T/testfiles= /output' '--volsize=3D1' '--name=3Dissue908' = '--encrypt-key=3D839E6A2856538CCF' '-v0' '--no-print-statistics' = '--archive-dir=3D/var/folders/6b/85yg9bp94rv55dzbdp78thp40000kr/T/testfile= s/cache' < /dev/null</div><div>...cwd: = /private/var/folders/6b/85yg9bp94rv55dzbdp78thp40000kr/T</div><div>...outp= ut:</div><div>...return_val: 0</div><div>------------------------------ = Captured log call -------------------------------</div><div>Level 8 = duplicity:log.py:100 TestBackend is not made for production = use!</div><div>Level 8 duplicity:log.py:100 TestBackend is not = made for production use!</div><div>Level 8 duplicity:log.py:100 = TestBackend is not made for production use!</div><div>Level 8 = duplicity:log.py:100 TestBackend is not made for production = use!</div><div>=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D short test summary info = =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D</div></div></div></blockquote><div>-Scott</div><div><div><br><bl= ockquote type=3D"cite"><div>On Jun 16, 2026, at 1:10=E2=80=AFPM, Kenneth = Loafman via Duplicity-talk <<a = href=3D"mailto:[email protected]" = target=3D"_blank">[email protected]</a>> = wrote:</div><br><div><div dir=3D"ltr">Hi everyone,<br><br>I am pleased = to announce the release of duplicity version 3.1.0.<br><br>This release = follows version 3.0.7 and includes a minor version bump to reflect a = significant new feature. Thanks to elmuz's contribution, restore = operations can now use --include, --exclude, --include-regexp, and = --include-filelist directly from the command line.<br><br>There are many = other improvements and bug fixes included in this update. Please see the = CHANGELOG below for full = details.<br><br>Thanks,<br>Ken<br></div></div></blockquote></div><br></div= ></div></div></div></div></div>___________________________________________= ____<br> Duplicity-talk mailing list<br> <a href=3D"mailto:[email protected]" = target=3D"_blank">[email protected]</a><br> <a href=3D"https://lists.nongnu.org/mailman/listinfo/duplicity-talk" = rel=3D"noreferrer" = target=3D"_blank">https://lists.nongnu.org/mailman/listinfo/duplicity-talk= </a><br> </blockquote></div></div> </div> _______________________________________________<br>Duplicity-talk = mailing = list<br>[email protected]<br>https://lists.nongnu.org/mailman/list= info/duplicity-talk<br></div></blockquote></div><br></div></div>__________= _____________________________________<br>Duplicity-talk mailing = list<br>[email protected]<br>https://lists.nongnu.org/mailman/list= info/duplicity-talk<br></div></blockquote></div><br></div></body></html>= --Apple-Mail=_CA0E208F-7C71-45E2-A0A2-52EE33D87FA6-- --===============0859283185533763876== Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: base64 Content-Disposition: inline X19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX18KRHVwbGljaXR5 LXRhbGsgbWFpbGluZyBsaXN0CkR1cGxpY2l0eS10YWxrQG5vbmdudS5vcmcKaHR0cHM6Ly9saXN0 cy5ub25nbnUub3JnL21haWxtYW4vbGlzdGluZm8vZHVwbGljaXR5LXRhbGsK --===============0859283185533763876==--