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. =
&nbsp; Is that also not necessary now? &nbsp;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 &lt;[email protected]&gt; 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. =
&nbsp;But I have a few questions.<div><br></div><div>1. what are the =
non-python requirements? &nbsp; I have the following in previous =
versions, and I am sure that the gnupg2 is needed.</div><div><div>&nbsp; =
&nbsp; &nbsp; &nbsp; librsync2-shlibs (&gt;=3D 2.0),</div><div>&nbsp; =
&nbsp; &nbsp; &nbsp; librsync-bin (&gt;=3D 2.0),</div><div>&nbsp; &nbsp; =
&nbsp; &nbsp; gnupg2,</div><div>&nbsp; &nbsp; &nbsp; &nbsp; =
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>&nbsp; &nbsp; &nbsp; &nbsp; =
ncftp,</div><div>&nbsp; &nbsp; &nbsp; &nbsp; =
lftp,</div><div><br></div></div><div>Are these also no longer part of =
the duplicity backends? &nbsp;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 &lt;[email protected]&gt; =
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.&nbsp; 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 =
.&nbsp; &nbsp;# while in the duplicity =
directory</font></div><div>&nbsp;</div><div>as this will guarantee we're =
using the same environment.&nbsp; 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 &lt;<a =
href=3D"mailto:[email protected]" =
target=3D"_blank">[email protected]</a>&gt; =
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.&nbsp; Trying to adjust my fink-project build system for =
this.&nbsp; I get a couple of failures when running the suite of =
tests.&nbsp; I know the pylint and the black tests are not necessary but =
I dislike failures in my output.&nbsp; Put it down to programmer =
OCD.&nbsp; 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.&nbsp; I am using python 3.10 and pylint =
2.14.5.&nbsp; Now updating pylint (and astroid) to current =
version.<div><br></div><div>1. pylint fails.&nbsp; 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.&nbsp; This of =
course causes all sorts of failures when &nbsp;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.&nbsp; 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.&nbsp; 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 =
&lt;testing.functional.test_regression.RegressionTest =
testMethod=3Dtest_issue908&gt;</div><div><br></div><div>&nbsp; &nbsp; =
@unittest.skipIf(os.path.exists("/.dockerenv"), "Won't work on =
docker")</div><div>&nbsp; &nbsp; def =
test_issue908(self):</div><div>&nbsp; &nbsp; &nbsp; &nbsp; =
"""</div><div>&nbsp; &nbsp; &nbsp; &nbsp; Test issue 908 - gpg: public =
key decryption failed: No passphrase given (3.0.6.2)</div><div>&nbsp; =
&nbsp; &nbsp; &nbsp; """</div><div>&nbsp; &nbsp;&nbsp;</div><div>&nbsp; =
&nbsp; &nbsp; &nbsp; # make sure we test with a clean cache and clean =
output</div><div>&nbsp; &nbsp; &nbsp; &nbsp; =
self.set_environ("FTP_PASSWORD", None)</div><div>&nbsp; &nbsp; &nbsp; =
&nbsp; self.set_environ("PASSPHRASE", None)</div><div>&nbsp; &nbsp; =
&nbsp; &nbsp; self.set_environ("SIGN_PASSPHRASE", None)</div><div>&nbsp; =
&nbsp; &nbsp; &nbsp; self.set_environ("TESTDEBUG", =
None)</div><div>&nbsp; &nbsp; &nbsp; &nbsp; =
shutil.rmtree(f"{_runtest_dir}/testfiles/cache/issue908", =
ignore_errors=3DTrue)</div><div>&nbsp; &nbsp; &nbsp; &nbsp; =
shutil.rmtree(f"{_runtest_dir}/testfiles/output", =
ignore_errors=3DTrue)</div><div>&nbsp; &nbsp;&nbsp;</div><div>&nbsp; =
&nbsp; &nbsp; &nbsp; # do initial full backup with =
passphrase</div><div>&nbsp; &nbsp; &nbsp; &nbsp; =
self.backup(</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; =
"full",</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; =
f"{_runtest_dir}/testfiles/various_file_types",</div><div>&nbsp; &nbsp; =
&nbsp; &nbsp; &nbsp; &nbsp; options=3D["--name=3Dissue908", =
f"--encrypt-key=3D{self.encrypt_key1}"],</div><div>&nbsp; &nbsp; &nbsp; =
&nbsp; )</div><div>&nbsp; &nbsp;&nbsp;</div><div>&nbsp; &nbsp; &nbsp; =
&nbsp; # make sure inc has somthing to do</div><div>&nbsp; &nbsp; &nbsp; =
&nbsp; =
os.unlink(f"{_runtest_dir}/testfiles/various_file_types/executable")</div>=
<div>&nbsp; &nbsp;&nbsp;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; # do =
incremental backup</div><div>&gt; &nbsp; &nbsp; &nbsp; =
self.backup(</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; =
"inc",</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; =
f"{_runtest_dir}/testfiles/various_file_types",</div><div>&nbsp; &nbsp; =
&nbsp; &nbsp; &nbsp; &nbsp; options=3D["--name=3Dissue908", =
f"--encrypt-key=3D{self.encrypt_key1}"],</div><div>&nbsp; &nbsp; &nbsp; =
&nbsp; &nbsp; &nbsp; =
passphrase_input=3D[self.sign_passphrase],</div><div>&nbsp; &nbsp; =
&nbsp; &nbsp; )</div><div><br></div><div>self &nbsp; &nbsp; &nbsp; =3D =
&lt;testing.functional.test_regression.RegressionTest =
testMethod=3Dtest_issue908&gt;</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:&nbsp;</div><div>_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ =
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ =
_&nbsp;</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>&nbsp; =
&nbsp; self.run_duplicity(options=3Doptions, **kwargs)</div><div>&nbsp; =
&nbsp; &nbsp; &nbsp; 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>&nbsp; =
&nbsp; &nbsp; &nbsp; input_dir &nbsp;=3D =
'/var/folders/6b/85yg9bp94rv55dzbdp78thp40000kr/T/testfiles/various_file_t=
ypes'</div><div>&nbsp; &nbsp; &nbsp; &nbsp; kwargs &nbsp; &nbsp; =3D =
{'passphrase_input': ['test']}</div><div>&nbsp; &nbsp; &nbsp; &nbsp; now =
&nbsp; &nbsp; &nbsp; &nbsp;=3D 1781631694.437021</div><div>&nbsp; &nbsp; =
&nbsp; &nbsp; options &nbsp; &nbsp;=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>&nbsp; &nbsp; &nbsp; =
&nbsp; self &nbsp; &nbsp; &nbsp; =3D =
&lt;testing.functional.test_regression.RegressionTest =
testMethod=3Dtest_issue908&gt;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; =
type &nbsp; &nbsp; &nbsp; =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>&nbsp; =
&nbsp; child.expect("passphrase.*:")</div><div>&nbsp; &nbsp; &nbsp; =
&nbsp; child &nbsp; &nbsp; &nbsp;=3D &lt;pexpect.pty_spawn.spawn object =
at 0x10abc27a0&gt;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; cmd_list &nbsp; =
=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>&nbsp; &nbsp; &nbsp; &nbsp; cmdline =
&nbsp; &nbsp;=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>&nbsp; &nbsp; &nbsp; &nbsp; current_time =3D =
None</div><div>&nbsp; &nbsp; &nbsp; &nbsp; dup_env &nbsp; &nbsp;=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>&nbsp; &nbsp; &nbsp; &nbsp; fail &nbsp; &nbsp; &nbsp; =
=3D None</div><div>&nbsp; &nbsp; &nbsp; &nbsp; item &nbsp; &nbsp; &nbsp; =
=3D 'test'</div><div>&nbsp; &nbsp; &nbsp; &nbsp; options &nbsp; &nbsp;=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>&nbsp; &nbsp; &nbsp; =
&nbsp; passphrase =3D 'test'</div><div>&nbsp; &nbsp; &nbsp; &nbsp; =
passphrase_input =3D ['test']</div><div>&nbsp; &nbsp; &nbsp; &nbsp; self =
&nbsp; &nbsp; &nbsp; =3D =
&lt;testing.functional.test_regression.RegressionTest =
testMethod=3Dtest_issue908&gt;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; =
timeout &nbsp; &nbsp;=3D =
None</div><div>/opt/sw/lib/python3.10/site-packages/pexpect/spawnbase.py:3=
43: in expect</div><div>&nbsp; &nbsp; return =
self.expect_list(compiled_pattern_list,</div><div>&nbsp; &nbsp; &nbsp; =
&nbsp; async_ &nbsp; &nbsp; =3D False</div><div>&nbsp; &nbsp; &nbsp; =
&nbsp; compiled_pattern_list =3D [re.compile(b'passphrase.*:', =
re.DOTALL)]</div><div>&nbsp; &nbsp; &nbsp; &nbsp; kw &nbsp; &nbsp; =
&nbsp; &nbsp; =3D {}</div><div>&nbsp; &nbsp; &nbsp; &nbsp; pattern =
&nbsp; &nbsp;=3D 'passphrase.*:'</div><div>&nbsp; &nbsp; &nbsp; &nbsp; =
searchwindowsize =3D -1</div><div>&nbsp; &nbsp; &nbsp; &nbsp; self =
&nbsp; &nbsp; &nbsp; =3D &lt;pexpect.pty_spawn.spawn object at =
0x10abc27a0&gt;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; timeout &nbsp; =
&nbsp;=3D =
-1</div><div>/opt/sw/lib/python3.10/site-packages/pexpect/spawnbase.py:372=
: in expect_list</div><div>&nbsp; &nbsp; return =
exp.expect_loop(timeout)</div><div>&nbsp; &nbsp; &nbsp; &nbsp; async_ =
&nbsp; &nbsp; =3D False</div><div>&nbsp; &nbsp; &nbsp; &nbsp; exp &nbsp; =
&nbsp; &nbsp; &nbsp;=3D &lt;pexpect.expect.Expecter object at =
0x109e4ff40&gt;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; kw &nbsp; &nbsp; =
&nbsp; &nbsp; =3D {}</div><div>&nbsp; &nbsp; &nbsp; &nbsp; pattern_list =
=3D [re.compile(b'passphrase.*:', re.DOTALL)]</div><div>&nbsp; &nbsp; =
&nbsp; &nbsp; searchwindowsize =3D -1</div><div>&nbsp; &nbsp; &nbsp; =
&nbsp; self &nbsp; &nbsp; &nbsp; =3D &lt;pexpect.pty_spawn.spawn object =
at 0x10abc27a0&gt;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; timeout &nbsp; =
&nbsp;=3D =
None</div><div>/opt/sw/lib/python3.10/site-packages/pexpect/expect.py:179:=
 in expect_loop</div><div>&nbsp; &nbsp; return =
self.eof(e)</div><div>&nbsp; &nbsp; &nbsp; &nbsp; idx &nbsp; &nbsp; =
&nbsp; &nbsp;=3D None</div><div>&nbsp; &nbsp; &nbsp; &nbsp; self &nbsp; =
&nbsp; &nbsp; =3D &lt;pexpect.expect.Expecter object at =
0x109e4ff40&gt;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; spawn &nbsp; =
&nbsp; &nbsp;=3D &lt;pexpect.pty_spawn.spawn object at =
0x10abc27a0&gt;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; timeout &nbsp; =
&nbsp;=3D None</div><div>_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ =
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _&nbsp;</div><div><br></div><div>self =3D =
&lt;pexpect.expect.Expecter object at 0x109e4ff40&gt;</div><div>err =3D =
EOF('End Of File (EOF). Empty string style =
platform.')</div><div><br></div><div>&nbsp; &nbsp; def eof(self, =
err=3DNone):</div><div>&nbsp; &nbsp; &nbsp; &nbsp; spawn =3D =
self.spawn</div><div>&nbsp; &nbsp;&nbsp;</div><div>&nbsp; &nbsp; &nbsp; =
&nbsp; spawn.before =3D spawn._before.getvalue()</div><div>&nbsp; &nbsp; =
&nbsp; &nbsp; spawn._buffer =3D spawn.buffer_type()</div><div>&nbsp; =
&nbsp; &nbsp; &nbsp; spawn._before =3D =
spawn.buffer_type()</div><div>&nbsp; &nbsp; &nbsp; &nbsp; spawn.after =3D =
EOF</div><div>&nbsp; &nbsp; &nbsp; &nbsp; index =3D =
self.searcher.eof_index</div><div>&nbsp; &nbsp; &nbsp; &nbsp; if index =
&gt;=3D 0:</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; =
spawn.match =3D EOF</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; =
spawn.match_index =3D index</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; =
&nbsp; return index</div><div>&nbsp; &nbsp; &nbsp; &nbsp; =
else:</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; spawn.match =3D =
None</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; =
spawn.match_index =3D None</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; =
&nbsp; msg =3D str(spawn)</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; =
&nbsp; msg +=3D '\nsearcher: %s' % self.searcher</div><div>&nbsp; &nbsp; =
&nbsp; &nbsp; &nbsp; &nbsp; if err is not None:</div><div>&nbsp; &nbsp; =
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; msg =3D str(err) + '\n' + =
msg</div><div>&nbsp; &nbsp;&nbsp;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; =
&nbsp; &nbsp; exc =3D EOF(msg)</div><div>&nbsp; &nbsp; &nbsp; &nbsp; =
&nbsp; &nbsp; exc.__cause__ =3D None # in Python 3.x we can use "raise =
exc from None"</div><div>&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; raise =
exc</div><div>E &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; =
pexpect.exceptions.EOF: End Of File (EOF). Empty string style =
platform.</div><div>E &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; =
&lt;pexpect.pty_spawn.spawn object at 0x10abc27a0&gt;</div><div>E &nbsp; =
&nbsp; &nbsp; &nbsp; &nbsp; command: /bin/sh</div><div>E &nbsp; &nbsp; =
&nbsp; &nbsp; &nbsp; 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 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; buffer (last =
100 chars): b''</div><div>E &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; before =
(last 100 chars): ''</div><div>E &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; =
after: &lt;class 'pexpect.exceptions.EOF'&gt;</div><div>E &nbsp; &nbsp; =
&nbsp; &nbsp; &nbsp; match: None</div><div>E &nbsp; &nbsp; &nbsp; &nbsp; =
&nbsp; match_index: None</div><div>E &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; =
exitstatus: None</div><div>E &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; =
flag_eof: True</div><div>E &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; pid: =
45404</div><div>E &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; child_fd: =
191</div><div>E &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; closed: =
False</div><div>E &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; timeout: =
None</div><div>E &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; delimiter: &lt;class =
'pexpect.exceptions.EOF'&gt;</div><div>E &nbsp; &nbsp; &nbsp; &nbsp; =
&nbsp; logfile: None</div><div>E &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; =
logfile_read: None</div><div>E &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; =
logfile_send: None</div><div>E &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; =
maxread: 2000</div><div>E &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ignorecase: =
False</div><div>E &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; searchwindowsize: =
None</div><div>E &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; delaybeforesend: =
0.05</div><div>E &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; delayafterclose: =
0.1</div><div>E &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; delayafterterminate: =
0.1</div><div>E &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; searcher: =
searcher_re:</div><div>E &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; =
&nbsp; 0: re.compile(b'passphrase.*:')</div><div><br></div><div>err =
&nbsp; &nbsp; &nbsp; &nbsp;=3D EOF('End Of File (EOF). Empty string =
style platform.')</div><div>exc &nbsp; &nbsp; &nbsp; &nbsp;=3D EOF('End =
Of File (EOF). Empty string style platform.\n&lt;pexpect.pty_spawn.spawn =
object at 0x10abc27a0&gt;\ncommand: /bin/s...: 0.05\ndelayafterclose: =
0.1\ndelayafterterminate: 0.1\nsearcher: searcher_re:\n &nbsp; &nbsp;0: =
re.compile(b\'passphrase.*:\')')</div><div>index &nbsp; &nbsp; &nbsp;=3D =
-1</div><div>msg &nbsp; &nbsp; &nbsp; &nbsp;=3D "End Of File (EOF). =
Empty string style platform.\n&lt;pexpect.pty_spawn.spawn object at =
0x10abc27a0&gt;\ncommand: /bin/sh\na...end: 0.05\ndelayafterclose: =
0.1\ndelayafterterminate: 0.1\nsearcher: searcher_re:\n &nbsp; &nbsp;0: =
re.compile(b'passphrase.*:')"</div><div>self &nbsp; &nbsp; &nbsp; =3D =
&lt;pexpect.expect.Expecter object at 0x109e4ff40&gt;</div><div>spawn =
&nbsp; &nbsp; &nbsp;=3D &lt;pexpect.pty_spawn.spawn object at =
0x10abc27a0&gt;</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' &lt; /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 =
&nbsp;duplicity:log.py:100 TestBackend is not made for production =
use!</div><div>Level 8 &nbsp;duplicity:log.py:100 TestBackend is not =
made for production use!</div><div>Level 8 &nbsp;duplicity:log.py:100 =
TestBackend is not made for production use!</div><div>Level 8 =
&nbsp;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 &lt;<a =
href=3D"mailto:[email protected]" =
target=3D"_blank">[email protected]</a>&gt; =
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==--