[Python-modules-team] Bug#1002352: python-ftputil: FTBFS: dh_auto_test: error: pybuild --test --test-pytest -i python{version} -p "3.10 3.9" returned exit code 13

Lucas Nussbaum lucas at debian.org
Wed Dec 22 07:55:50 GMT 2021


Source: python-ftputil
Version: 3.4-3
Severity: serious
Justification: FTBFS
Tags: bookworm sid ftbfs
User: lucas at debian.org
Usertags: ftbfs-20211220 ftbfs-bookworm

Hi,

During a rebuild of all packages in sid, your package failed to build
on amd64.


Relevant part (hopefully):
>  debian/rules build
> dh build --with python3 --buildsystem=pybuild
> dh: warning: Compatibility levels before 10 are deprecated (level 9 in use)
>    dh_update_autotools_config -O--buildsystem=pybuild
>    dh_auto_configure -O--buildsystem=pybuild
> dh_auto_configure: warning: Compatibility levels before 10 are deprecated (level 9 in use)
> I: pybuild base:237: python3.10 setup.py config 
> /<<PKGBUILDDIR>>/setup.py:14: DeprecationWarning: The distutils package is deprecated and slated for removal in Python 3.12. Use setuptools or check PEP 632 for potential alternatives
>   from distutils import core
> running config
> I: pybuild base:237: python3.9 setup.py config 
> running config
>    dh_auto_build -O--buildsystem=pybuild
> dh_auto_build: warning: Compatibility levels before 10 are deprecated (level 9 in use)
> I: pybuild base:237: /usr/bin/python3.10 setup.py build 
> /<<PKGBUILDDIR>>/setup.py:14: DeprecationWarning: The distutils package is deprecated and slated for removal in Python 3.12. Use setuptools or check PEP 632 for potential alternatives
>   from distutils import core
> running build
> running build_py
> creating /<<PKGBUILDDIR>>/.pybuild/cpython3_3.10_ftputil/build/ftputil
> copying ftputil/__init__.py -> /<<PKGBUILDDIR>>/.pybuild/cpython3_3.10_ftputil/build/ftputil
> copying ftputil/file_transfer.py -> /<<PKGBUILDDIR>>/.pybuild/cpython3_3.10_ftputil/build/ftputil
> copying ftputil/lrucache.py -> /<<PKGBUILDDIR>>/.pybuild/cpython3_3.10_ftputil/build/ftputil
> copying ftputil/session.py -> /<<PKGBUILDDIR>>/.pybuild/cpython3_3.10_ftputil/build/ftputil
> copying ftputil/stat.py -> /<<PKGBUILDDIR>>/.pybuild/cpython3_3.10_ftputil/build/ftputil
> copying ftputil/sync.py -> /<<PKGBUILDDIR>>/.pybuild/cpython3_3.10_ftputil/build/ftputil
> copying ftputil/compat.py -> /<<PKGBUILDDIR>>/.pybuild/cpython3_3.10_ftputil/build/ftputil
> copying ftputil/socket_file_adapter.py -> /<<PKGBUILDDIR>>/.pybuild/cpython3_3.10_ftputil/build/ftputil
> copying ftputil/path.py -> /<<PKGBUILDDIR>>/.pybuild/cpython3_3.10_ftputil/build/ftputil
> copying ftputil/file.py -> /<<PKGBUILDDIR>>/.pybuild/cpython3_3.10_ftputil/build/ftputil
> copying ftputil/host.py -> /<<PKGBUILDDIR>>/.pybuild/cpython3_3.10_ftputil/build/ftputil
> copying ftputil/stat_cache.py -> /<<PKGBUILDDIR>>/.pybuild/cpython3_3.10_ftputil/build/ftputil
> copying ftputil/session_adapter.py -> /<<PKGBUILDDIR>>/.pybuild/cpython3_3.10_ftputil/build/ftputil
> copying ftputil/version.py -> /<<PKGBUILDDIR>>/.pybuild/cpython3_3.10_ftputil/build/ftputil
> copying ftputil/error.py -> /<<PKGBUILDDIR>>/.pybuild/cpython3_3.10_ftputil/build/ftputil
> copying ftputil/tool.py -> /<<PKGBUILDDIR>>/.pybuild/cpython3_3.10_ftputil/build/ftputil
> I: pybuild base:237: /usr/bin/python3 setup.py build 
> running build
> running build_py
> creating /<<PKGBUILDDIR>>/.pybuild/cpython3_3.9_ftputil/build/ftputil
> copying ftputil/__init__.py -> /<<PKGBUILDDIR>>/.pybuild/cpython3_3.9_ftputil/build/ftputil
> copying ftputil/file_transfer.py -> /<<PKGBUILDDIR>>/.pybuild/cpython3_3.9_ftputil/build/ftputil
> copying ftputil/lrucache.py -> /<<PKGBUILDDIR>>/.pybuild/cpython3_3.9_ftputil/build/ftputil
> copying ftputil/session.py -> /<<PKGBUILDDIR>>/.pybuild/cpython3_3.9_ftputil/build/ftputil
> copying ftputil/stat.py -> /<<PKGBUILDDIR>>/.pybuild/cpython3_3.9_ftputil/build/ftputil
> copying ftputil/sync.py -> /<<PKGBUILDDIR>>/.pybuild/cpython3_3.9_ftputil/build/ftputil
> copying ftputil/compat.py -> /<<PKGBUILDDIR>>/.pybuild/cpython3_3.9_ftputil/build/ftputil
> copying ftputil/socket_file_adapter.py -> /<<PKGBUILDDIR>>/.pybuild/cpython3_3.9_ftputil/build/ftputil
> copying ftputil/path.py -> /<<PKGBUILDDIR>>/.pybuild/cpython3_3.9_ftputil/build/ftputil
> copying ftputil/file.py -> /<<PKGBUILDDIR>>/.pybuild/cpython3_3.9_ftputil/build/ftputil
> copying ftputil/host.py -> /<<PKGBUILDDIR>>/.pybuild/cpython3_3.9_ftputil/build/ftputil
> copying ftputil/stat_cache.py -> /<<PKGBUILDDIR>>/.pybuild/cpython3_3.9_ftputil/build/ftputil
> copying ftputil/session_adapter.py -> /<<PKGBUILDDIR>>/.pybuild/cpython3_3.9_ftputil/build/ftputil
> copying ftputil/version.py -> /<<PKGBUILDDIR>>/.pybuild/cpython3_3.9_ftputil/build/ftputil
> copying ftputil/error.py -> /<<PKGBUILDDIR>>/.pybuild/cpython3_3.9_ftputil/build/ftputil
> copying ftputil/tool.py -> /<<PKGBUILDDIR>>/.pybuild/cpython3_3.9_ftputil/build/ftputil
>    dh_auto_test -O--buildsystem=pybuild
> dh_auto_test: warning: Compatibility levels before 10 are deprecated (level 9 in use)
> I: pybuild base:237: cd /<<PKGBUILDDIR>>/.pybuild/cpython3_3.10_ftputil/build; python3.10 -m pytest test
> ============================= test session starts ==============================
> platform linux -- Python 3.10.1, pytest-6.2.5, py-1.10.0, pluggy-0.13.0
> rootdir: /<<PKGBUILDDIR>>
> collected 129 items
> 
> test/test_error.py ......                                                [  4%]
> test/test_file.py ..................                                     [ 18%]
> test/test_file_transfer.py ....                                          [ 21%]
> test/test_host.py .....F.FFF.F.FF.......F....FFFFF..                     [ 48%]
> test/test_path.py FF..FF.F.FFF                                           [ 57%]
> test/test_session.py ......                                              [ 62%]
> test/test_stat.py ........F.FFFFFFFFFFFF                                 [ 79%]
> test/test_stat_cache.py .........F                                       [ 86%]
> test/test_sync.py ...                                                    [ 89%]
> test/test_tool.py ........                                               [ 95%]
> test/test_with_statement.py ......                                       [100%]
> 
> =================================== FAILURES ===================================
> ________________________ TestSetParser.test_set_parser _________________________
> 
> self = <test.test_host.TestSetParser object at 0x7ff6ae1fe8f0>
> 
>     def test_set_parser(self):
>         """Test if the selected parser is used."""
>         host = test_base.ftp_host_factory()
>         assert host._stat._allow_parser_switching is True
>         trivial_parser = TestSetParser.TrivialParser()
>         host.set_parser(trivial_parser)
> >       stat_result = host.stat("/home")
> 
> test/test_host.py:241: 
> _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
> ftputil/host.py:904: in stat
>     return self._stat._stat(path, _exception_for_missing_path)
> ftputil/stat.py:746: in _stat
>     return self.__call_with_parser_retry(self._real_stat, path,
> ftputil/stat.py:701: in __call_with_parser_retry
>     result = method(*args, **kwargs)
> ftputil/stat.py:668: in _real_stat
>     lstat_result = self._real_lstat(path, _exception_for_missing_path)
> ftputil/stat.py:627: in _real_lstat
>     for stat_result in self._stat_results_from_dir(dirname):
> ftputil/stat.py:541: in _stat_results_from_dir
>     lines = self._host_dir(path)
> ftputil/stat.py:533: in _host_dir
>     return self._host._dir(path)
> ftputil/host.py:854: in _dir
>     lines = self._robust_ftp_command(_FTPHost_dir_command, path,
> ftputil/host.py:608: in _robust_ftp_command
>     return command(self, "")
> ftputil/host.py:848: in _FTPHost_dir_command
>     with ftputil.error.ftplib_error_to_ftp_os_error:
> ftputil/host.py:850: in _FTPHost_dir_command
>     self._session.dir("-a", path, callback)
> _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
> 
> self = <test.mock_ftplib.MockUnixFormatSession object at 0x7ff6ae1fd450>
> args = ('-a', '', <function FTPHost._dir.<locals>._FTPHost_dir_command.<locals>.callback at 0x7ff6ae14c280>)
> 
>     def dir(self, *args):
>         """
>         Provide a callback function for processing each line of a
>         directory listing. Return nothing.
>         """
>         # The callback comes last in `ftplib.FTP.dir`.
> >       if isinstance(args[-1], collections.Callable):
> E       AttributeError: module 'collections' has no attribute 'Callable'
> 
> test/mock_ftplib.py:157: AttributeError
> ___________ TestRecursiveListingForDotAsPath.test_recursive_listing ____________
> 
> self = <test.test_host.TestRecursiveListingForDotAsPath object at 0x7ff6ae0a5210>
> 
>     def test_recursive_listing(self):
>         host = test_base.ftp_host_factory(
>                  session_factory=RecursiveListingForDotAsPathSession)
> >       lines = host._dir(host.curdir)
> 
> test/test_host.py:271: 
> _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
> ftputil/host.py:854: in _dir
>     lines = self._robust_ftp_command(_FTPHost_dir_command, path,
> ftputil/host.py:608: in _robust_ftp_command
>     return command(self, "")
> ftputil/host.py:848: in _FTPHost_dir_command
>     with ftputil.error.ftplib_error_to_ftp_os_error:
> ftputil/host.py:850: in _FTPHost_dir_command
>     self._session.dir("-a", path, callback)
> _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
> 
> self = <test.test_host.RecursiveListingForDotAsPathSession object at 0x7ff6ae0a61d0>
> args = ('-a', '', <function FTPHost._dir.<locals>._FTPHost_dir_command.<locals>.callback at 0x7ff6ae14e680>)
> 
>     def dir(self, *args):
>         """
>         Provide a callback function for processing each line of a
>         directory listing. Return nothing.
>         """
>         # The callback comes last in `ftplib.FTP.dir`.
> >       if isinstance(args[-1], collections.Callable):
> E       AttributeError: module 'collections' has no attribute 'Callable'
> 
> test/mock_ftplib.py:157: AttributeError
> _____________ TestRecursiveListingForDotAsPath.test_plain_listing ______________
> 
> self = <test.test_host.TestRecursiveListingForDotAsPath object at 0x7ff6ae1d6170>
> 
>     def test_plain_listing(self):
>         host = test_base.ftp_host_factory(
>                  session_factory=RecursiveListingForDotAsPathSession)
> >       lines = host._dir("")
> 
> test/test_host.py:280: 
> _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
> ftputil/host.py:854: in _dir
>     lines = self._robust_ftp_command(_FTPHost_dir_command, path,
> ftputil/host.py:608: in _robust_ftp_command
>     return command(self, "")
> ftputil/host.py:848: in _FTPHost_dir_command
>     with ftputil.error.ftplib_error_to_ftp_os_error:
> ftputil/host.py:850: in _FTPHost_dir_command
>     self._session.dir("-a", path, callback)
> _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
> 
> self = <test.test_host.RecursiveListingForDotAsPathSession object at 0x7ff6ae1d6ad0>
> args = ('-a', '', <function FTPHost._dir.<locals>._FTPHost_dir_command.<locals>.callback at 0x7ff6ae14e050>)
> 
>     def dir(self, *args):
>         """
>         Provide a callback function for processing each line of a
>         directory listing. Return nothing.
>         """
>         # The callback comes last in `ftplib.FTP.dir`.
> >       if isinstance(args[-1], collections.Callable):
> E       AttributeError: module 'collections' has no attribute 'Callable'
> 
> test/mock_ftplib.py:157: AttributeError
> _ TestRecursiveListingForDotAsPath.test_empty_string_instead_of_dot_workaround _
> 
> self = <test.test_host.TestRecursiveListingForDotAsPath object at 0x7ff6ae160b80>
> 
>     def test_empty_string_instead_of_dot_workaround(self):
>         host = test_base.ftp_host_factory(
>                  session_factory=RecursiveListingForDotAsPathSession)
> >       files = host.listdir(host.curdir)
> 
> test/test_host.py:289: 
> _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
> ftputil/host.py:871: in listdir
>     items = self._stat._listdir(path)
> ftputil/stat.py:725: in _listdir
>     return self.__call_with_parser_retry(self._real_listdir, path)
> ftputil/stat.py:701: in __call_with_parser_retry
>     result = method(*args, **kwargs)
> ftputil/stat.py:585: in _real_listdir
>     for stat_result in self._stat_results_from_dir(path):
> ftputil/stat.py:541: in _stat_results_from_dir
>     lines = self._host_dir(path)
> ftputil/stat.py:533: in _host_dir
>     return self._host._dir(path)
> ftputil/host.py:854: in _dir
>     lines = self._robust_ftp_command(_FTPHost_dir_command, path,
> ftputil/host.py:608: in _robust_ftp_command
>     return command(self, "")
> ftputil/host.py:848: in _FTPHost_dir_command
>     with ftputil.error.ftplib_error_to_ftp_os_error:
> ftputil/host.py:850: in _FTPHost_dir_command
>     self._session.dir("-a", path, callback)
> _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
> 
> self = <test.test_host.RecursiveListingForDotAsPathSession object at 0x7ff6ae161c30>
> args = ('-a', '', <function FTPHost._dir.<locals>._FTPHost_dir_command.<locals>.callback at 0x7ff6ae14e830>)
> 
>     def dir(self, *args):
>         """
>         Provide a callback function for processing each line of a
>         directory listing. Return nothing.
>         """
>         # The callback comes last in `ftplib.FTP.dir`.
> >       if isinstance(args[-1], collections.Callable):
> E       AttributeError: module 'collections' has no attribute 'Callable'
> 
> test/mock_ftplib.py:157: AttributeError
> ________________ TestUploadAndDownload.test_conditional_upload _________________
> 
> self = <test.test_host.TestUploadAndDownload object at 0x7ff6ae1ff9d0>
> 
>     def test_conditional_upload(self):
>         """Test conditional upload."""
>         local_source = "_test_source_"
>         data = binary_data()
>         self.generate_file(data, local_source)
>         # Target is newer, so don't upload.
>         host = test_base.ftp_host_factory(
>                  ftp_host_class=FailingUploadAndDownloadFTPHost)
> >       flag = host.upload_if_newer(local_source, "/home/newer")
> 
> test/test_host.py:325: 
> _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
> ftputil/host.py:508: in upload_if_newer
>     return ftputil.file_transfer.copy_file(source_file, target_file,
> ftputil/file_transfer.py:177: in copy_file
>     transfer_condition = not target_file.exists() or \
> ftputil/file_transfer.py:79: in exists
>     return self._path.exists(self.name)
> ftputil/path.py:63: in exists
>     lstat_result = self._host.lstat(
> ftputil/host.py:888: in lstat
>     return self._stat._lstat(path, _exception_for_missing_path)
> ftputil/stat.py:735: in _lstat
>     return self.__call_with_parser_retry(self._real_lstat, path,
> ftputil/stat.py:701: in __call_with_parser_retry
>     result = method(*args, **kwargs)
> ftputil/stat.py:620: in _real_lstat
>     if not self._path.isdir(dirname) and not _exception_for_missing_path:
> ftputil/path.py:168: in isdir
>     return self._is_file_system_entity(path, "dir")
> ftputil/path.py:148: in _is_file_system_entity
>     stat_result = self._host.stat(
> ftputil/host.py:904: in stat
>     return self._stat._stat(path, _exception_for_missing_path)
> ftputil/stat.py:746: in _stat
>     return self.__call_with_parser_retry(self._real_stat, path,
> ftputil/stat.py:701: in __call_with_parser_retry
>     result = method(*args, **kwargs)
> ftputil/stat.py:668: in _real_stat
>     lstat_result = self._real_lstat(path, _exception_for_missing_path)
> ftputil/stat.py:627: in _real_lstat
>     for stat_result in self._stat_results_from_dir(dirname):
> ftputil/stat.py:541: in _stat_results_from_dir
>     lines = self._host_dir(path)
> ftputil/stat.py:533: in _host_dir
>     return self._host._dir(path)
> ftputil/host.py:854: in _dir
>     lines = self._robust_ftp_command(_FTPHost_dir_command, path,
> ftputil/host.py:608: in _robust_ftp_command
>     return command(self, "")
> ftputil/host.py:848: in _FTPHost_dir_command
>     with ftputil.error.ftplib_error_to_ftp_os_error:
> ftputil/host.py:850: in _FTPHost_dir_command
>     self._session.dir("-a", path, callback)
> _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
> 
> self = <test.mock_ftplib.MockUnixFormatSession object at 0x7ff6ae6dce20>
> args = ('-a', '', <function FTPHost._dir.<locals>._FTPHost_dir_command.<locals>.callback at 0x7ff6ae14d900>)
> 
>     def dir(self, *args):
>         """
>         Provide a callback function for processing each line of a
>         directory listing. Return nothing.
>         """
>         # The callback comes last in `ftplib.FTP.dir`.
> >       if isinstance(args[-1], collections.Callable):
> E       AttributeError: module 'collections' has no attribute 'Callable'
> 
> test/mock_ftplib.py:157: AttributeError
> ______ TestUploadAndDownload.test_conditional_download_with_older_target _______
> 
> self = <test.test_host.TestUploadAndDownload object at 0x7ff6ae074850>
> 
>     def test_conditional_download_with_older_target(self):
>         """Test conditional binary mode download with newer source file."""
>         local_target = "_test_target_"
>         # Make target file.
>         open(local_target, "w").close()
>         # Source is newer (date in 2020), so download.
>         host = test_base.ftp_host_factory(
>                  session_factory=BinaryDownloadMockSession)
> >       flag = host.download_if_newer("/home/newer", local_target)
> 
> test/test_host.py:376: 
> _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
> ftputil/host.py:557: in download_if_newer
>     return ftputil.file_transfer.copy_file(source_file, target_file,
> ftputil/file_transfer.py:178: in copy_file
>     source_is_newer_than_target(source_file, target_file)
> ftputil/file_transfer.py:124: in source_is_newer_than_target
>     if source_file.mtime_precision() is ftputil.stat.UNKNOWN_PRECISION:
> ftputil/file_transfer.py:90: in mtime_precision
>     return self._host.stat(self.name)._st_mtime_precision
> ftputil/host.py:904: in stat
>     return self._stat._stat(path, _exception_for_missing_path)
> ftputil/stat.py:746: in _stat
>     return self.__call_with_parser_retry(self._real_stat, path,
> ftputil/stat.py:701: in __call_with_parser_retry
>     result = method(*args, **kwargs)
> ftputil/stat.py:668: in _real_stat
>     lstat_result = self._real_lstat(path, _exception_for_missing_path)
> ftputil/stat.py:620: in _real_lstat
>     if not self._path.isdir(dirname) and not _exception_for_missing_path:
> ftputil/path.py:168: in isdir
>     return self._is_file_system_entity(path, "dir")
> ftputil/path.py:148: in _is_file_system_entity
>     stat_result = self._host.stat(
> ftputil/host.py:904: in stat
>     return self._stat._stat(path, _exception_for_missing_path)
> ftputil/stat.py:746: in _stat
>     return self.__call_with_parser_retry(self._real_stat, path,
> ftputil/stat.py:701: in __call_with_parser_retry
>     result = method(*args, **kwargs)
> ftputil/stat.py:668: in _real_stat
>     lstat_result = self._real_lstat(path, _exception_for_missing_path)
> ftputil/stat.py:627: in _real_lstat
>     for stat_result in self._stat_results_from_dir(dirname):
> ftputil/stat.py:541: in _stat_results_from_dir
>     lines = self._host_dir(path)
> ftputil/stat.py:533: in _host_dir
>     return self._host._dir(path)
> ftputil/host.py:854: in _dir
>     lines = self._robust_ftp_command(_FTPHost_dir_command, path,
> ftputil/host.py:608: in _robust_ftp_command
>     return command(self, "")
> ftputil/host.py:848: in _FTPHost_dir_command
>     with ftputil.error.ftplib_error_to_ftp_os_error:
> ftputil/host.py:850: in _FTPHost_dir_command
>     self._session.dir("-a", path, callback)
> _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
> 
> self = <test.test_host.BinaryDownloadMockSession object at 0x7ff6ae0748e0>
> args = ('-a', '', <function FTPHost._dir.<locals>._FTPHost_dir_command.<locals>.callback at 0x7ff6ae14c310>)
> 
>     def dir(self, *args):
>         """
>         Provide a callback function for processing each line of a
>         directory listing. Return nothing.
>         """
>         # The callback comes last in `ftplib.FTP.dir`.
> >       if isinstance(args[-1], collections.Callable):
> E       AttributeError: module 'collections' has no attribute 'Callable'
> 
> test/mock_ftplib.py:157: AttributeError
> ______ TestUploadAndDownload.test_conditional_download_with_newer_target _______
> 
> self = <test.test_host.TestUploadAndDownload object at 0x7ff6adfe8910>
> 
>     def test_conditional_download_with_newer_target(self):
>         """Test conditional binary mode download with older source file."""
>         local_target = "_test_target_"
>         # Make target file.
>         open(local_target, "w").close()
>         # Source is older (date in 1970), so don't download.
>         host = test_base.ftp_host_factory(
>                  ftp_host_class=FailingUploadAndDownloadFTPHost,
>                  session_factory=BinaryDownloadMockSession)
> >       flag = host.download_if_newer("/home/older", local_target)
> 
> test/test_host.py:389: 
> _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
> ftputil/host.py:557: in download_if_newer
>     return ftputil.file_transfer.copy_file(source_file, target_file,
> ftputil/file_transfer.py:178: in copy_file
>     source_is_newer_than_target(source_file, target_file)
> ftputil/file_transfer.py:124: in source_is_newer_than_target
>     if source_file.mtime_precision() is ftputil.stat.UNKNOWN_PRECISION:
> ftputil/file_transfer.py:90: in mtime_precision
>     return self._host.stat(self.name)._st_mtime_precision
> ftputil/host.py:904: in stat
>     return self._stat._stat(path, _exception_for_missing_path)
> ftputil/stat.py:746: in _stat
>     return self.__call_with_parser_retry(self._real_stat, path,
> ftputil/stat.py:701: in __call_with_parser_retry
>     result = method(*args, **kwargs)
> ftputil/stat.py:668: in _real_stat
>     lstat_result = self._real_lstat(path, _exception_for_missing_path)
> ftputil/stat.py:620: in _real_lstat
>     if not self._path.isdir(dirname) and not _exception_for_missing_path:
> ftputil/path.py:168: in isdir
>     return self._is_file_system_entity(path, "dir")
> ftputil/path.py:148: in _is_file_system_entity
>     stat_result = self._host.stat(
> ftputil/host.py:904: in stat
>     return self._stat._stat(path, _exception_for_missing_path)
> ftputil/stat.py:746: in _stat
>     return self.__call_with_parser_retry(self._real_stat, path,
> ftputil/stat.py:701: in __call_with_parser_retry
>     result = method(*args, **kwargs)
> ftputil/stat.py:668: in _real_stat
>     lstat_result = self._real_lstat(path, _exception_for_missing_path)
> ftputil/stat.py:627: in _real_lstat
>     for stat_result in self._stat_results_from_dir(dirname):
> ftputil/stat.py:541: in _stat_results_from_dir
>     lines = self._host_dir(path)
> ftputil/stat.py:533: in _host_dir
>     return self._host._dir(path)
> ftputil/host.py:854: in _dir
>     lines = self._robust_ftp_command(_FTPHost_dir_command, path,
> ftputil/host.py:608: in _robust_ftp_command
>     return command(self, "")
> ftputil/host.py:848: in _FTPHost_dir_command
>     with ftputil.error.ftplib_error_to_ftp_os_error:
> ftputil/host.py:850: in _FTPHost_dir_command
>     self._session.dir("-a", path, callback)
> _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
> 
> self = <test.test_host.BinaryDownloadMockSession object at 0x7ff6adfeb370>
> args = ('-a', '', <function FTPHost._dir.<locals>._FTPHost_dir_command.<locals>.callback at 0x7ff6ae14eb00>)
> 
>     def dir(self, *args):
>         """
>         Provide a callback function for processing each line of a
>         directory listing. Return nothing.
>         """
>         # The callback comes last in `ftplib.FTP.dir`.
> >       if isinstance(args[-1], collections.Callable):
> E       AttributeError: module 'collections' has no attribute 'Callable'
> 
> test/mock_ftplib.py:157: AttributeError
> _________________ TestAcceptEitherUnicodeOrBytes.test_listdir __________________
> 
> self = <test.test_host.TestAcceptEitherUnicodeOrBytes object at 0x7ff6ade864d0>
> 
>     def test_listdir(self):
>         """Test whether `listdir` accepts either unicode or bytes."""
>         host = self.host
>         as_bytes = ftputil.tool.as_bytes
>         host.chdir("/home/file_name_test")
>         # Unicode
> >       items = host.listdir("ä")
> 
> test/test_host.py:529: 
> _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
> ftputil/host.py:871: in listdir
>     items = self._stat._listdir(path)
> ftputil/stat.py:725: in _listdir
>     return self.__call_with_parser_retry(self._real_listdir, path)
> ftputil/stat.py:701: in __call_with_parser_retry
>     result = method(*args, **kwargs)
> ftputil/stat.py:579: in _real_listdir
>     if not self._path.isdir(path):
> ftputil/path.py:168: in isdir
>     return self._is_file_system_entity(path, "dir")
> ftputil/path.py:148: in _is_file_system_entity
>     stat_result = self._host.stat(
> ftputil/host.py:904: in stat
>     return self._stat._stat(path, _exception_for_missing_path)
> ftputil/stat.py:746: in _stat
>     return self.__call_with_parser_retry(self._real_stat, path,
> ftputil/stat.py:701: in __call_with_parser_retry
>     result = method(*args, **kwargs)
> ftputil/stat.py:668: in _real_stat
>     lstat_result = self._real_lstat(path, _exception_for_missing_path)
> ftputil/stat.py:627: in _real_lstat
>     for stat_result in self._stat_results_from_dir(dirname):
> ftputil/stat.py:541: in _stat_results_from_dir
>     lines = self._host_dir(path)
> ftputil/stat.py:533: in _host_dir
>     return self._host._dir(path)
> ftputil/host.py:854: in _dir
>     lines = self._robust_ftp_command(_FTPHost_dir_command, path,
> ftputil/host.py:608: in _robust_ftp_command
>     return command(self, "")
> ftputil/host.py:848: in _FTPHost_dir_command
>     with ftputil.error.ftplib_error_to_ftp_os_error:
> ftputil/host.py:850: in _FTPHost_dir_command
>     self._session.dir("-a", path, callback)
> _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
> 
> self = <test.mock_ftplib.MockUnixFormatSession object at 0x7ff6ade859c0>
> args = ('-a', '', <function FTPHost._dir.<locals>._FTPHost_dir_command.<locals>.callback at 0x7ff6ae14d480>)
> 
>     def dir(self, *args):
>         """
>         Provide a callback function for processing each line of a
>         directory listing. Return nothing.
>         """
>         # The callback comes last in `ftplib.FTP.dir`.
> >       if isinstance(args[-1], collections.Callable):
> E       AttributeError: module 'collections' has no attribute 'Callable'
> 
> test/mock_ftplib.py:157: AttributeError
> __________________ TestAcceptEitherUnicodeOrBytes.test_rmdir ___________________
> 
> self = <test.test_host.TestAcceptEitherUnicodeOrBytes object at 0x7ff6ae0d30d0>
> 
>     def test_rmdir(self):
>         """Test whether `rmdir` accepts either unicode or bytes."""
>         empty_directory_as_required_by_rmdir = "/home/file_name_test/empty_ä"
> >       self._test_method_with_single_path_argument(
>           self.host.rmdir, empty_directory_as_required_by_rmdir)
> 
> test/test_host.py:575: 
> _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
> test/test_host.py:552: in _test_method_with_single_path_argument
>     method(path)
> ftputil/host.py:707: in rmdir
>     if self.listdir(path):
> ftputil/host.py:871: in listdir
>     items = self._stat._listdir(path)
> ftputil/stat.py:725: in _listdir
>     return self.__call_with_parser_retry(self._real_listdir, path)
> ftputil/stat.py:701: in __call_with_parser_retry
>     result = method(*args, **kwargs)
> ftputil/stat.py:579: in _real_listdir
>     if not self._path.isdir(path):
> ftputil/path.py:168: in isdir
>     return self._is_file_system_entity(path, "dir")
> ftputil/path.py:148: in _is_file_system_entity
>     stat_result = self._host.stat(
> ftputil/host.py:904: in stat
>     return self._stat._stat(path, _exception_for_missing_path)
> ftputil/stat.py:746: in _stat
>     return self.__call_with_parser_retry(self._real_stat, path,
> ftputil/stat.py:701: in __call_with_parser_retry
>     result = method(*args, **kwargs)
> ftputil/stat.py:668: in _real_stat
>     lstat_result = self._real_lstat(path, _exception_for_missing_path)
> ftputil/stat.py:620: in _real_lstat
>     if not self._path.isdir(dirname) and not _exception_for_missing_path:
> ftputil/path.py:168: in isdir
>     return self._is_file_system_entity(path, "dir")
> ftputil/path.py:148: in _is_file_system_entity
>     stat_result = self._host.stat(
> ftputil/host.py:904: in stat
>     return self._stat._stat(path, _exception_for_missing_path)
> ftputil/stat.py:746: in _stat
>     return self.__call_with_parser_retry(self._real_stat, path,
> ftputil/stat.py:701: in __call_with_parser_retry
>     result = method(*args, **kwargs)
> ftputil/stat.py:668: in _real_stat
>     lstat_result = self._real_lstat(path, _exception_for_missing_path)
> ftputil/stat.py:620: in _real_lstat
>     if not self._path.isdir(dirname) and not _exception_for_missing_path:
> ftputil/path.py:168: in isdir
>     return self._is_file_system_entity(path, "dir")
> ftputil/path.py:148: in _is_file_system_entity
>     stat_result = self._host.stat(
> ftputil/host.py:904: in stat
>     return self._stat._stat(path, _exception_for_missing_path)
> ftputil/stat.py:746: in _stat
>     return self.__call_with_parser_retry(self._real_stat, path,
> ftputil/stat.py:701: in __call_with_parser_retry
>     result = method(*args, **kwargs)
> ftputil/stat.py:668: in _real_stat
>     lstat_result = self._real_lstat(path, _exception_for_missing_path)
> ftputil/stat.py:627: in _real_lstat
>     for stat_result in self._stat_results_from_dir(dirname):
> ftputil/stat.py:541: in _stat_results_from_dir
>     lines = self._host_dir(path)
> ftputil/stat.py:533: in _host_dir
>     return self._host._dir(path)
> ftputil/host.py:854: in _dir
>     lines = self._robust_ftp_command(_FTPHost_dir_command, path,
> ftputil/host.py:608: in _robust_ftp_command
>     return command(self, "")
> ftputil/host.py:848: in _FTPHost_dir_command
>     with ftputil.error.ftplib_error_to_ftp_os_error:
> ftputil/host.py:850: in _FTPHost_dir_command
>     self._session.dir("-a", path, callback)
> _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
> 
> self = <test.mock_ftplib.MockUnixFormatSession object at 0x7ff6ae0d1f30>
> args = ('-a', '', <function FTPHost._dir.<locals>._FTPHost_dir_command.<locals>.callback at 0x7ff6ae14ea70>)
> 
>     def dir(self, *args):
>         """
>         Provide a callback function for processing each line of a
>         directory listing. Return nothing.
>         """
>         # The callback comes last in `ftplib.FTP.dir`.
> >       if isinstance(args[-1], collections.Callable):
> E       AttributeError: module 'collections' has no attribute 'Callable'
> 
> test/mock_ftplib.py:157: AttributeError
> __________________ TestAcceptEitherUnicodeOrBytes.test_remove __________________
> 
> self = <test.test_host.TestAcceptEitherUnicodeOrBytes object at 0x7ff6ae1fe110>
> 
>     def test_remove(self):
>         """Test whether `remove` accepts either unicode or bytes."""
> >       self._test_method_with_single_path_argument(
>           self.host.remove, "/home/file_name_test/ö")
> 
> test/test_host.py:580: 
> _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
> test/test_host.py:552: in _test_method_with_single_path_argument
>     method(path)
> ftputil/host.py:730: in remove
>     if self.path.isfile(path) or self.path.islink(path) or \
> ftputil/path.py:177: in isfile
>     return self._is_file_system_entity(path, "file")
> ftputil/path.py:148: in _is_file_system_entity
>     stat_result = self._host.stat(
> ftputil/host.py:904: in stat
>     return self._stat._stat(path, _exception_for_missing_path)
> ftputil/stat.py:746: in _stat
>     return self.__call_with_parser_retry(self._real_stat, path,
> ftputil/stat.py:701: in __call_with_parser_retry
>     result = method(*args, **kwargs)
> ftputil/stat.py:668: in _real_stat
>     lstat_result = self._real_lstat(path, _exception_for_missing_path)
> ftputil/stat.py:620: in _real_lstat
>     if not self._path.isdir(dirname) and not _exception_for_missing_path:
> ftputil/path.py:168: in isdir
>     return self._is_file_system_entity(path, "dir")
> ftputil/path.py:148: in _is_file_system_entity
>     stat_result = self._host.stat(
> ftputil/host.py:904: in stat
>     return self._stat._stat(path, _exception_for_missing_path)
> ftputil/stat.py:746: in _stat
>     return self.__call_with_parser_retry(self._real_stat, path,
> ftputil/stat.py:701: in __call_with_parser_retry
>     result = method(*args, **kwargs)
> ftputil/stat.py:668: in _real_stat
>     lstat_result = self._real_lstat(path, _exception_for_missing_path)
> ftputil/stat.py:620: in _real_lstat
>     if not self._path.isdir(dirname) and not _exception_for_missing_path:
> ftputil/path.py:168: in isdir
>     return self._is_file_system_entity(path, "dir")
> ftputil/path.py:148: in _is_file_system_entity
>     stat_result = self._host.stat(
> ftputil/host.py:904: in stat
>     return self._stat._stat(path, _exception_for_missing_path)
> ftputil/stat.py:746: in _stat
>     return self.__call_with_parser_retry(self._real_stat, path,
> ftputil/stat.py:701: in __call_with_parser_retry
>     result = method(*args, **kwargs)
> ftputil/stat.py:668: in _real_stat
>     lstat_result = self._real_lstat(path, _exception_for_missing_path)
> ftputil/stat.py:627: in _real_lstat
>     for stat_result in self._stat_results_from_dir(dirname):
> ftputil/stat.py:541: in _stat_results_from_dir
>     lines = self._host_dir(path)
> ftputil/stat.py:533: in _host_dir
>     return self._host._dir(path)
> ftputil/host.py:854: in _dir
>     lines = self._robust_ftp_command(_FTPHost_dir_command, path,
> ftputil/host.py:608: in _robust_ftp_command
>     return command(self, "")
> ftputil/host.py:848: in _FTPHost_dir_command
>     with ftputil.error.ftplib_error_to_ftp_os_error:
> ftputil/host.py:850: in _FTPHost_dir_command
>     self._session.dir("-a", path, callback)
> _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
> 
> self = <test.mock_ftplib.MockUnixFormatSession object at 0x7ff6ae1fdfc0>
> args = ('-a', '', <function FTPHost._dir.<locals>._FTPHost_dir_command.<locals>.callback at 0x7ff6ae14e710>)
> 
>     def dir(self, *args):
>         """
>         Provide a callback function for processing each line of a
>         directory listing. Return nothing.
>         """
>         # The callback comes last in `ftplib.FTP.dir`.
> >       if isinstance(args[-1], collections.Callable):
> E       AttributeError: module 'collections' has no attribute 'Callable'
> 
> test/mock_ftplib.py:157: AttributeError
> __________________ TestAcceptEitherUnicodeOrBytes.test_rmtree __________________
> 
> self = <test.test_host.TestAcceptEitherUnicodeOrBytes object at 0x7ff6ae113eb0>
> 
>     def test_rmtree(self):
>         """Test whether `rmtree` accepts either unicode or bytes."""
>         empty_directory_as_required_by_rmtree = "/home/file_name_test/empty_ä"
> >       self._test_method_with_single_path_argument(
>           self.host.rmtree, empty_directory_as_required_by_rmtree)
> 
> test/test_host.py:586: 
> _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
> test/test_host.py:552: in _test_method_with_single_path_argument
>     method(path)
> ftputil/host.py:787: in rmtree
>     names = self.listdir(path)
> ftputil/host.py:871: in listdir
>     items = self._stat._listdir(path)
> ftputil/stat.py:725: in _listdir
>     return self.__call_with_parser_retry(self._real_listdir, path)
> ftputil/stat.py:701: in __call_with_parser_retry
>     result = method(*args, **kwargs)
> ftputil/stat.py:579: in _real_listdir
>     if not self._path.isdir(path):
> ftputil/path.py:168: in isdir
>     return self._is_file_system_entity(path, "dir")
> ftputil/path.py:148: in _is_file_system_entity
>     stat_result = self._host.stat(
> ftputil/host.py:904: in stat
>     return self._stat._stat(path, _exception_for_missing_path)
> ftputil/stat.py:746: in _stat
>     return self.__call_with_parser_retry(self._real_stat, path,
> ftputil/stat.py:701: in __call_with_parser_retry
>     result = method(*args, **kwargs)
> ftputil/stat.py:668: in _real_stat
>     lstat_result = self._real_lstat(path, _exception_for_missing_path)
> ftputil/stat.py:620: in _real_lstat
>     if not self._path.isdir(dirname) and not _exception_for_missing_path:
> ftputil/path.py:168: in isdir
>     return self._is_file_system_entity(path, "dir")
> ftputil/path.py:148: in _is_file_system_entity
>     stat_result = self._host.stat(
> ftputil/host.py:904: in stat
>     return self._stat._stat(path, _exception_for_missing_path)
> ftputil/stat.py:746: in _stat
>     return self.__call_with_parser_retry(self._real_stat, path,
> ftputil/stat.py:701: in __call_with_parser_retry
>     result = method(*args, **kwargs)
> ftputil/stat.py:668: in _real_stat
>     lstat_result = self._real_lstat(path, _exception_for_missing_path)
> ftputil/stat.py:620: in _real_lstat
>     if not self._path.isdir(dirname) and not _exception_for_missing_path:
> ftputil/path.py:168: in isdir
>     return self._is_file_system_entity(path, "dir")
> ftputil/path.py:148: in _is_file_system_entity
>     stat_result = self._host.stat(
> ftputil/host.py:904: in stat
>     return self._stat._stat(path, _exception_for_missing_path)
> ftputil/stat.py:746: in _stat
>     return self.__call_with_parser_retry(self._real_stat, path,
> ftputil/stat.py:701: in __call_with_parser_retry
>     result = method(*args, **kwargs)
> ftputil/stat.py:668: in _real_stat
>     lstat_result = self._real_lstat(path, _exception_for_missing_path)
> ftputil/stat.py:627: in _real_lstat
>     for stat_result in self._stat_results_from_dir(dirname):
> ftputil/stat.py:541: in _stat_results_from_dir
>     lines = self._host_dir(path)
> ftputil/stat.py:533: in _host_dir
>     return self._host._dir(path)
> ftputil/host.py:854: in _dir
>     lines = self._robust_ftp_command(_FTPHost_dir_command, path,
> ftputil/host.py:608: in _robust_ftp_command
>     return command(self, "")
> ftputil/host.py:848: in _FTPHost_dir_command
>     with ftputil.error.ftplib_error_to_ftp_os_error:
> ftputil/host.py:850: in _FTPHost_dir_command
>     self._session.dir("-a", path, callback)
> _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
> 
> self = <test.mock_ftplib.MockUnixFormatSession object at 0x7ff6ae1110c0>
> args = ('-a', '', <function FTPHost._dir.<locals>._FTPHost_dir_command.<locals>.callback at 0x7ff6ae14db40>)
> 
>     def dir(self, *args):
>         """
>         Provide a callback function for processing each line of a
>         directory listing. Return nothing.
>         """
>         # The callback comes last in `ftplib.FTP.dir`.
> >       if isinstance(args[-1], collections.Callable):
> E       AttributeError: module 'collections' has no attribute 'Callable'
> 
> test/mock_ftplib.py:157: AttributeError
> __________________ TestAcceptEitherUnicodeOrBytes.test_lstat ___________________
> 
> self = <test.test_host.TestAcceptEitherUnicodeOrBytes object at 0x7ff6ae0fc700>
> 
>     def test_lstat(self):
>         """Test whether `lstat` accepts either unicode or bytes."""
> >       self._test_method_with_single_path_argument(
>           self.host.lstat, "/home/file_name_test/ä")
> 
> test/test_host.py:591: 
> _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
> test/test_host.py:552: in _test_method_with_single_path_argument
>     method(path)
> ftputil/host.py:888: in lstat
>     return self._stat._lstat(path, _exception_for_missing_path)
> ftputil/stat.py:735: in _lstat
>     return self.__call_with_parser_retry(self._real_lstat, path,
> ftputil/stat.py:701: in __call_with_parser_retry
>     result = method(*args, **kwargs)
> ftputil/stat.py:620: in _real_lstat
>     if not self._path.isdir(dirname) and not _exception_for_missing_path:
> ftputil/path.py:168: in isdir
>     return self._is_file_system_entity(path, "dir")
> ftputil/path.py:148: in _is_file_system_entity
>     stat_result = self._host.stat(
> ftputil/host.py:904: in stat
>     return self._stat._stat(path, _exception_for_missing_path)
> ftputil/stat.py:746: in _stat
>     return self.__call_with_parser_retry(self._real_stat, path,
> ftputil/stat.py:701: in __call_with_parser_retry
>     result = method(*args, **kwargs)
> ftputil/stat.py:668: in _real_stat
>     lstat_result = self._real_lstat(path, _exception_for_missing_path)
> ftputil/stat.py:620: in _real_lstat
>     if not self._path.isdir(dirname) and not _exception_for_missing_path:
> ftputil/path.py:168: in isdir
>     return self._is_file_system_entity(path, "dir")
> ftputil/path.py:148: in _is_file_system_entity
>     stat_result = self._host.stat(
> ftputil/host.py:904: in stat
>     return self._stat._stat(path, _exception_for_missing_path)
> ftputil/stat.py:746: in _stat
>     return self.__call_with_parser_retry(self._real_stat, path,
> ftputil/stat.py:701: in __call_with_parser_retry
>     result = method(*args, **kwargs)
> ftputil/stat.py:668: in _real_stat
>     lstat_result = self._real_lstat(path, _exception_for_missing_path)
> ftputil/stat.py:627: in _real_lstat
>     for stat_result in self._stat_results_from_dir(dirname):
> ftputil/stat.py:541: in _stat_results_from_dir
>     lines = self._host_dir(path)
> ftputil/stat.py:533: in _host_dir
>     return self._host._dir(path)
> ftputil/host.py:854: in _dir
>     lines = self._robust_ftp_command(_FTPHost_dir_command, path,
> ftputil/host.py:608: in _robust_ftp_command
>     return command(self, "")
> ftputil/host.py:848: in _FTPHost_dir_command
>     with ftputil.error.ftplib_error_to_ftp_os_error:
> ftputil/host.py:850: in _FTPHost_dir_command
>     self._session.dir("-a", path, callback)
> _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
> 
> self = <test.mock_ftplib.MockUnixFormatSession object at 0x7ff6ae0fd690>
> args = ('-a', '', <function FTPHost._dir.<locals>._FTPHost_dir_command.<locals>.callback at 0x7ff6ae14d6c0>)
> 
>     def dir(self, *args):
>         """
>         Provide a callback function for processing each line of a
>         directory listing. Return nothing.
>         """
>         # The callback comes last in `ftplib.FTP.dir`.
> >       if isinstance(args[-1], collections.Callable):
> E       AttributeError: module 'collections' has no attribute 'Callable'
> 
> test/mock_ftplib.py:157: AttributeError
> ___________________ TestAcceptEitherUnicodeOrBytes.test_stat ___________________
> 
> self = <test.test_host.TestAcceptEitherUnicodeOrBytes object at 0x7ff6adfeb340>
> 
>     def test_stat(self):
>         """Test whether `stat` accepts either unicode or bytes."""
> >       self._test_method_with_single_path_argument(
>           self.host.stat, "/home/file_name_test/ä")
> 
> test/test_host.py:596: 
> _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
> test/test_host.py:552: in _test_method_with_single_path_argument
>     method(path)
> ftputil/host.py:904: in stat
>     return self._stat._stat(path, _exception_for_missing_path)
> ftputil/stat.py:746: in _stat
>     return self.__call_with_parser_retry(self._real_stat, path,
> ftputil/stat.py:701: in __call_with_parser_retry
>     result = method(*args, **kwargs)
> ftputil/stat.py:668: in _real_stat
>     lstat_result = self._real_lstat(path, _exception_for_missing_path)
> ftputil/stat.py:620: in _real_lstat
>     if not self._path.isdir(dirname) and not _exception_for_missing_path:
> ftputil/path.py:168: in isdir
>     return self._is_file_system_entity(path, "dir")
> ftputil/path.py:148: in _is_file_system_entity
>     stat_result = self._host.stat(
> ftputil/host.py:904: in stat
>     return self._stat._stat(path, _exception_for_missing_path)
> ftputil/stat.py:746: in _stat
>     return self.__call_with_parser_retry(self._real_stat, path,
> ftputil/stat.py:701: in __call_with_parser_retry
>     result = method(*args, **kwargs)
> ftputil/stat.py:668: in _real_stat
>     lstat_result = self._real_lstat(path, _exception_for_missing_path)
> ftputil/stat.py:620: in _real_lstat
>     if not self._path.isdir(dirname) and not _exception_for_missing_path:
> ftputil/path.py:168: in isdir
>     return self._is_file_system_entity(path, "dir")
> ftputil/path.py:148: in _is_file_system_entity
>     stat_result = self._host.stat(
> ftputil/host.py:904: in stat
>     return self._stat._stat(path, _exception_for_missing_path)
> ftputil/stat.py:746: in _stat
>     return self.__call_with_parser_retry(self._real_stat, path,
> ftputil/stat.py:701: in __call_with_parser_retry
>     result = method(*args, **kwargs)
> ftputil/stat.py:668: in _real_stat
>     lstat_result = self._real_lstat(path, _exception_for_missing_path)
> ftputil/stat.py:627: in _real_lstat
>     for stat_result in self._stat_results_from_dir(dirname):
> ftputil/stat.py:541: in _stat_results_from_dir
>     lines = self._host_dir(path)
> ftputil/stat.py:533: in _host_dir
>     return self._host._dir(path)
> ftputil/host.py:854: in _dir
>     lines = self._robust_ftp_command(_FTPHost_dir_command, path,
> ftputil/host.py:608: in _robust_ftp_command
>     return command(self, "")
> ftputil/host.py:848: in _FTPHost_dir_command
>     with ftputil.error.ftplib_error_to_ftp_os_error:
> ftputil/host.py:850: in _FTPHost_dir_command
>     self._session.dir("-a", path, callback)
> _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
> 
> self = <test.mock_ftplib.MockUnixFormatSession object at 0x7ff6adfea320>
> args = ('-a', '', <function FTPHost._dir.<locals>._FTPHost_dir_command.<locals>.callback at 0x7ff6ae14c670>)
> 
>     def dir(self, *args):
>         """
>         Provide a callback function for processing each line of a
>         directory listing. Return nothing.
>         """
>         # The callback comes last in `ftplib.FTP.dir`.
> >       if isinstance(args[-1], collections.Callable):
> E       AttributeError: module 'collections' has no attribute 'Callable'
> 
> test/mock_ftplib.py:157: AttributeError
> __________________ TestPath.test_regular_isdir_isfile_islink ___________________
> 
> self = <test.test_path.TestPath object at 0x7ff6ae6d48e0>
> 
>     def test_regular_isdir_isfile_islink(self):
>         """Test regular `FTPHost._Path.isdir/isfile/islink`."""
>         host = test_base.ftp_host_factory()
>         testdir = "/home/sschwarzer"
>         host.chdir(testdir)
>         # Test a path which isn't there.
> >       assert not host.path.isdir("notthere")
> 
> test/test_path.py:47: 
> _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
> ftputil/path.py:168: in isdir
>     return self._is_file_system_entity(path, "dir")
> ftputil/path.py:148: in _is_file_system_entity
>     stat_result = self._host.stat(
> ftputil/host.py:904: in stat
>     return self._stat._stat(path, _exception_for_missing_path)
> ftputil/stat.py:746: in _stat
>     return self.__call_with_parser_retry(self._real_stat, path,
> ftputil/stat.py:701: in __call_with_parser_retry
>     result = method(*args, **kwargs)
> ftputil/stat.py:668: in _real_stat
>     lstat_result = self._real_lstat(path, _exception_for_missing_path)
> ftputil/stat.py:627: in _real_lstat
>     for stat_result in self._stat_results_from_dir(dirname):
> ftputil/stat.py:541: in _stat_results_from_dir
>     lines = self._host_dir(path)
> ftputil/stat.py:533: in _host_dir
>     return self._host._dir(path)
> ftputil/host.py:854: in _dir
>     lines = self._robust_ftp_command(_FTPHost_dir_command, path,
> ftputil/host.py:608: in _robust_ftp_command
>     return command(self, "")
> ftputil/host.py:848: in _FTPHost_dir_command
>     with ftputil.error.ftplib_error_to_ftp_os_error:
> ftputil/host.py:850: in _FTPHost_dir_command
>     self._session.dir("-a", path, callback)
> _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
> 
> self = <test.mock_ftplib.MockUnixFormatSession object at 0x7ff6ae6d5720>
> args = ('-a', '', <function FTPHost._dir.<locals>._FTPHost_dir_command.<locals>.callback at 0x7ff6ae14eb00>)
> 
>     def dir(self, *args):
>         """
>         Provide a callback function for processing each line of a
>         directory listing. Return nothing.
>         """
>         # The callback comes last in `ftplib.FTP.dir`.
> >       if isinstance(args[-1], collections.Callable):
> E       AttributeError: module 'collections' has no attribute 'Callable'
> 
> test/mock_ftplib.py:157: AttributeError
> _____________________ TestPath.test_workaround_for_spaces ______________________
> 
> self = <test.test_path.TestPath object at 0x7ff6ae6f6980>
> 
>     def test_workaround_for_spaces(self):
>         """Test whether the workaround for space-containing paths is used."""
>         host = test_base.ftp_host_factory()
>         testdir = "/home/sschwarzer"
>         host.chdir(testdir)
>         # Test a file name containing spaces.
>         testfile = "/home/dir with spaces/file with spaces"
> >       assert not host.path.isdir(testfile)
> 
> test/test_path.py:77: 
> _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
> ftputil/path.py:168: in isdir
>     return self._is_file_system_entity(path, "dir")
> ftputil/path.py:148: in _is_file_system_entity
>     stat_result = self._host.stat(
> ftputil/host.py:904: in stat
>     return self._stat._stat(path, _exception_for_missing_path)
> ftputil/stat.py:746: in _stat
>     return self.__call_with_parser_retry(self._real_stat, path,
> ftputil/stat.py:701: in __call_with_parser_retry
>     result = method(*args, **kwargs)
> ftputil/stat.py:668: in _real_stat
>     lstat_result = self._real_lstat(path, _exception_for_missing_path)
> ftputil/stat.py:620: in _real_lstat
>     if not self._path.isdir(dirname) and not _exception_for_missing_path:
> ftputil/path.py:168: in isdir
>     return self._is_file_system_entity(path, "dir")
> ftputil/path.py:148: in _is_file_system_entity
>     stat_result = self._host.stat(
> ftputil/host.py:904: in stat
>     return self._stat._stat(path, _exception_for_missing_path)
> ftputil/stat.py:746: in _stat
>     return self.__call_with_parser_retry(self._real_stat, path,
> ftputil/stat.py:701: in __call_with_parser_retry
>     result = method(*args, **kwargs)
> ftputil/stat.py:668: in _real_stat
>     lstat_result = self._real_lstat(path, _exception_for_missing_path)
> ftputil/stat.py:620: in _real_lstat
>     if not self._path.isdir(dirname) and not _exception_for_missing_path:
> ftputil/path.py:168: in isdir
>     return self._is_file_system_entity(path, "dir")
> ftputil/path.py:148: in _is_file_system_entity
>     stat_result = self._host.stat(
> ftputil/host.py:904: in stat
>     return self._stat._stat(path, _exception_for_missing_path)
> ftputil/stat.py:746: in _stat
>     return self.__call_with_parser_retry(self._real_stat, path,
> ftputil/stat.py:701: in __call_with_parser_retry
>     result = method(*args, **kwargs)
> ftputil/stat.py:668: in _real_stat
>     lstat_result = self._real_lstat(path, _exception_for_missing_path)
> ftputil/stat.py:627: in _real_lstat
>     for stat_result in self._stat_results_from_dir(dirname):
> ftputil/stat.py:541: in _stat_results_from_dir
>     lines = self._host_dir(path)
> ftputil/stat.py:533: in _host_dir
>     return self._host._dir(path)
> ftputil/host.py:854: in _dir
>     lines = self._robust_ftp_command(_FTPHost_dir_command, path,
> ftputil/host.py:608: in _robust_ftp_command
>     return command(self, "")
> ftputil/host.py:848: in _FTPHost_dir_command
>     with ftputil.error.ftplib_error_to_ftp_os_error:
> ftputil/host.py:850: in _FTPHost_dir_command
>     self._session.dir("-a", path, callback)
> _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
> 
> self = <test.mock_ftplib.MockUnixFormatSession object at 0x7ff6ae6f5a80>
> args = ('-a', '', <function FTPHost._dir.<locals>._FTPHost_dir_command.<locals>.callback at 0x7ff6ae14c310>)
> 
>     def dir(self, *args):
>         """
>         Provide a callback function for processing each line of a
>         directory listing. Return nothing.
>         """
>         # The callback comes last in `ftplib.FTP.dir`.
> >       if isinstance(args[-1], collections.Callable):
> E       AttributeError: module 'collections' has no attribute 'Callable'
> 
> test/mock_ftplib.py:157: AttributeError
> _____________ TestPath.test_isdir_isfile_with_infinite_link_chain ______________
> 
> self = <test.test_path.TestPath object at 0x7ff6ade87c70>
> 
>     def test_isdir_isfile_with_infinite_link_chain(self):
>         """
>         Test if `isdir` and `isfile` return `False` if they encounter
>         an infinite link chain.
>         """
>         host = test_base.ftp_host_factory()
> >       assert host.path.isdir("/home/bad_link") is False
> 
> test/test_path.py:111: 
> _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
> ftputil/path.py:168: in isdir
>     return self._is_file_system_entity(path, "dir")
> ftputil/path.py:148: in _is_file_system_entity
>     stat_result = self._host.stat(
> ftputil/host.py:904: in stat
>     return self._stat._stat(path, _exception_for_missing_path)
> ftputil/stat.py:746: in _stat
>     return self.__call_with_parser_retry(self._real_stat, path,
> ftputil/stat.py:701: in __call_with_parser_retry
>     result = method(*args, **kwargs)
> ftputil/stat.py:668: in _real_stat
>     lstat_result = self._real_lstat(path, _exception_for_missing_path)
> ftputil/stat.py:620: in _real_lstat
>     if not self._path.isdir(dirname) and not _exception_for_missing_path:
> ftputil/path.py:168: in isdir
>     return self._is_file_system_entity(path, "dir")
> ftputil/path.py:148: in _is_file_system_entity
>     stat_result = self._host.stat(
> ftputil/host.py:904: in stat
>     return self._stat._stat(path, _exception_for_missing_path)
> ftputil/stat.py:746: in _stat
>     return self.__call_with_parser_retry(self._real_stat, path,
> ftputil/stat.py:701: in __call_with_parser_retry
>     result = method(*args, **kwargs)
> ftputil/stat.py:668: in _real_stat
>     lstat_result = self._real_lstat(path, _exception_for_missing_path)
> ftputil/stat.py:627: in _real_lstat
>     for stat_result in self._stat_results_from_dir(dirname):
> ftputil/stat.py:541: in _stat_results_from_dir
>     lines = self._host_dir(path)
> ftputil/stat.py:533: in _host_dir
>     return self._host._dir(path)
> ftputil/host.py:854: in _dir
>     lines = self._robust_ftp_command(_FTPHost_dir_command, path,
> ftputil/host.py:608: in _robust_ftp_command
>     return command(self, "")
> ftputil/host.py:848: in _FTPHost_dir_command
>     with ftputil.error.ftplib_error_to_ftp_os_error:
> ftputil/host.py:850: in _FTPHost_dir_command
>     self._session.dir("-a", path, callback)
> _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
> 
> self = <test.mock_ftplib.MockUnixFormatSession object at 0x7ff6ade845e0>
> args = ('-a', '', <function FTPHost._dir.<locals>._FTPHost_dir_command.<locals>.callback at 0x7ff6ae14ed40>)
> 
>     def dir(self, *args):
>         """
>         Provide a callback function for processing each line of a
>         directory listing. Return nothing.
>         """
>         # The callback comes last in `ftplib.FTP.dir`.
> >       if isinstance(args[-1], collections.Callable):
> E       AttributeError: module 'collections' has no attribute 'Callable'
> 
> test/mock_ftplib.py:157: AttributeError
> _____________________________ TestPath.test_exists _____________________________
> 
> self = <test.test_path.TestPath object at 0x7ff6ae0747c0>
> 
>     def test_exists(self):
>         """Test `FTPHost.path.exists`."""
>         # Regular use of `exists`
>         host = test_base.ftp_host_factory()
>         testdir = "/home/sschwarzer"
>         host.chdir(testdir)
> >       assert host.path.exists("index.html")
> 
> test/test_path.py:120: 
> _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
> ftputil/path.py:63: in exists
>     lstat_result = self._host.lstat(
> ftputil/host.py:888: in lstat
>     return self._stat._lstat(path, _exception_for_missing_path)
> ftputil/stat.py:735: in _lstat
>     return self.__call_with_parser_retry(self._real_lstat, path,
> ftputil/stat.py:701: in __call_with_parser_retry
>     result = method(*args, **kwargs)
> ftputil/stat.py:627: in _real_lstat
>     for stat_result in self._stat_results_from_dir(dirname):
> ftputil/stat.py:541: in _stat_results_from_dir
>     lines = self._host_dir(path)
> ftputil/stat.py:533: in _host_dir
>     return self._host._dir(path)
> ftputil/host.py:854: in _dir
>     lines = self._robust_ftp_command(_FTPHost_dir_command, path,
> ftputil/host.py:608: in _robust_ftp_command
>     return command(self, "")
> ftputil/host.py:848: in _FTPHost_dir_command
>     with ftputil.error.ftplib_error_to_ftp_os_error:
> ftputil/host.py:850: in _FTPHost_dir_command
>     self._session.dir("-a", path, callback)
> _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
> 
> self = <test.mock_ftplib.MockUnixFormatSession object at 0x7ff6ae075240>
> args = ('-a', '', <function FTPHost._dir.<locals>._FTPHost_dir_command.<locals>.callback at 0x7ff6ae14eef0>)
> 
>     def dir(self, *args):
>         """
>         Provide a callback function for processing each line of a
>         directory listing. Return nothing.
>         """
>         # The callback comes last in `ftplib.FTP.dir`.
> >       if isinstance(args[-1], collections.Callable):
> E       AttributeError: module 'collections' has no attribute 'Callable'
> 
> test/mock_ftplib.py:157: AttributeError
> _ TestAcceptEitherBytesOrUnicode.test_methods_that_take_a_string_and_return_a_bool _
> 
> self = <test.test_path.TestAcceptEitherBytesOrUnicode object at 0x7ff6adf3ebf0>
> 
>     def test_methods_that_take_a_string_and_return_a_bool(self):
>         """Test whether the methods accept byte and unicode strings."""
>         host = self.host
>         as_bytes = ftputil.tool.as_bytes
>         host.chdir("/home/file_name_test")
>         # `isabs`
>         assert not host.path.isabs("ä")
>         assert not host.path.isabs(as_bytes("ä"))
>         # `exists`
> >       assert host.path.exists("ä")
> 
> test/test_path.py:161: 
> _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
> ftputil/path.py:63: in exists
>     lstat_result = self._host.lstat(
> ftputil/host.py:888: in lstat
>     return self._stat._lstat(path, _exception_for_missing_path)
> ftputil/stat.py:735: in _lstat
>     return self.__call_with_parser_retry(self._real_lstat, path,
> ftputil/stat.py:701: in __call_with_parser_retry
>     result = method(*args, **kwargs)
> ftputil/stat.py:627: in _real_lstat
>     for stat_result in self._stat_results_from_dir(dirname):
> ftputil/stat.py:541: in _stat_results_from_dir
>     lines = self._host_dir(path)
> ftputil/stat.py:533: in _host_dir
>     return self._host._dir(path)
> ftputil/host.py:854: in _dir
>     lines = self._robust_ftp_command(_FTPHost_dir_command, path,
> ftputil/host.py:608: in _robust_ftp_command
>     return command(self, "")
> ftputil/host.py:848: in _FTPHost_dir_command
>     with ftputil.error.ftplib_error_to_ftp_os_error:
> ftputil/host.py:850: in _FTPHost_dir_command
>     self._session.dir("-a", path, callback)
> _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
> 
> self = <test.mock_ftplib.MockUnixFormatSession object at 0x7ff6adf3c760>
> args = ('-a', '', <function FTPHost._dir.<locals>._FTPHost_dir_command.<locals>.callback at 0x7ff6ae14da20>)
> 
>     def dir(self, *args):
>         """
>         Provide a callback function for processing each line of a
>         directory listing. Return nothing.
>         """
>         # The callback comes last in `ftplib.FTP.dir`.
> >       if isinstance(args[-1], collections.Callable):
> E       AttributeError: module 'collections' has no attribute 'Callable'
> 
> test/mock_ftplib.py:157: AttributeError
> _________________ TestAcceptEitherBytesOrUnicode.test_getmtime _________________
> 
> self = <test.test_path.TestAcceptEitherBytesOrUnicode object at 0x7ff6ae6d4e20>
> 
>     def test_getmtime(self):
>         """
>         Test whether `FTPHost.path.getmtime` accepts byte and unicode
>         paths.
>         """
>         host = self.host
>         as_bytes = ftputil.tool.as_bytes
>         host.chdir("/home/file_name_test")
>         # We don't care about the _exact_ time, so don't bother with
>         # timezone differences. Instead, do a simple sanity check.
>         day = 24 * 60 * 60  # seconds
>         expected_mtime = time.mktime((2000, 5, 29, 0, 0, 0, 0, 0, 0))
>         mtime_makes_sense = (lambda mtime: expected_mtime - day <= mtime <=
>                                            expected_mtime + day)
> >       assert mtime_makes_sense(host.path.getmtime("ä"))
> 
> test/test_path.py:212: 
> _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
> ftputil/path.py:78: in getmtime
>     return self._host.stat(path).st_mtime
> ftputil/host.py:904: in stat
>     return self._stat._stat(path, _exception_for_missing_path)
> ftputil/stat.py:746: in _stat
>     return self.__call_with_parser_retry(self._real_stat, path,
> ftputil/stat.py:701: in __call_with_parser_retry
>     result = method(*args, **kwargs)
> ftputil/stat.py:668: in _real_stat
>     lstat_result = self._real_lstat(path, _exception_for_missing_path)
> ftputil/stat.py:627: in _real_lstat
>     for stat_result in self._stat_results_from_dir(dirname):
> ftputil/stat.py:541: in _stat_results_from_dir
>     lines = self._host_dir(path)
> ftputil/stat.py:533: in _host_dir
>     return self._host._dir(path)
> ftputil/host.py:854: in _dir
>     lines = self._robust_ftp_command(_FTPHost_dir_command, path,
> ftputil/host.py:608: in _robust_ftp_command
>     return command(self, "")
> ftputil/host.py:848: in _FTPHost_dir_command
>     with ftputil.error.ftplib_error_to_ftp_os_error:
> ftputil/host.py:850: in _FTPHost_dir_command
>     self._session.dir("-a", path, callback)
> _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
> 
> self = <test.mock_ftplib.MockUnixFormatSession object at 0x7ff6ae6d63b0>
> args = ('-a', '', <function FTPHost._dir.<locals>._FTPHost_dir_command.<locals>.callback at 0x7ff6ae14e4d0>)
> 
>     def dir(self, *args):
>         """
>         Provide a callback function for processing each line of a
>         directory listing. Return nothing.
>         """
>         # The callback comes last in `ftplib.FTP.dir`.
> >       if isinstance(args[-1], collections.Callable):
> E       AttributeError: module 'collections' has no attribute 'Callable'
> 
> test/mock_ftplib.py:157: AttributeError
> _________________ TestAcceptEitherBytesOrUnicode.test_getsize __________________
> 
> self = <test.test_path.TestAcceptEitherBytesOrUnicode object at 0x7ff6ae261540>
> 
>     def test_getsize(self):
>         """
>         Test whether `FTPHost.path.getsize` accepts byte and unicode paths.
>         """
>         host = self.host
>         as_bytes = ftputil.tool.as_bytes
>         host.chdir("/home/file_name_test")
> >       assert host.path.getsize("ä") == 512
> 
> test/test_path.py:222: 
> _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
> ftputil/path.py:88: in getsize
>     return self._host.stat(path).st_size
> ftputil/host.py:904: in stat
>     return self._stat._stat(path, _exception_for_missing_path)
> ftputil/stat.py:746: in _stat
>     return self.__call_with_parser_retry(self._real_stat, path,
> ftputil/stat.py:701: in __call_with_parser_retry
>     result = method(*args, **kwargs)
> ftputil/stat.py:668: in _real_stat
>     lstat_result = self._real_lstat(path, _exception_for_missing_path)
> ftputil/stat.py:627: in _real_lstat
>     for stat_result in self._stat_results_from_dir(dirname):
> ftputil/stat.py:541: in _stat_results_from_dir
>     lines = self._host_dir(path)
> ftputil/stat.py:533: in _host_dir
>     return self._host._dir(path)
> ftputil/host.py:854: in _dir
>     lines = self._robust_ftp_command(_FTPHost_dir_command, path,
> ftputil/host.py:608: in _robust_ftp_command
>     return command(self, "")
> ftputil/host.py:848: in _FTPHost_dir_command
>     with ftputil.error.ftplib_error_to_ftp_os_error:
> ftputil/host.py:850: in _FTPHost_dir_command
>     self._session.dir("-a", path, callback)
> _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
> 
> self = <test.mock_ftplib.MockUnixFormatSession object at 0x7ff6ae263d60>
> args = ('-a', '', <function FTPHost._dir.<locals>._FTPHost_dir_command.<locals>.callback at 0x7ff6ae14ea70>)
> 
>     def dir(self, *args):
>         """
>         Provide a callback function for processing each line of a
>         directory listing. Return nothing.
>         """
>         # The callback comes last in `ftplib.FTP.dir`.
> >       if isinstance(args[-1], collections.Callable):
> E       AttributeError: module 'collections' has no attribute 'Callable'
> 
> test/mock_ftplib.py:157: AttributeError
> ___________________ TestAcceptEitherBytesOrUnicode.test_walk ___________________
> 
> self = <test.test_path.TestAcceptEitherBytesOrUnicode object at 0x7ff6ae075000>
> 
>     def test_walk(self):
>         """Test whether `FTPHost.path.walk` accepts bytes and unicode paths."""
>         host = self.host
>         as_bytes = ftputil.tool.as_bytes
>         def noop(arg, top, names):
>             del names[:]
> >       host.path.walk("ä", noop, None)
> 
> test/test_path.py:231: 
> _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
> ftputil/path.py:220: in walk
>     names = self._host.listdir(top)
> ftputil/host.py:871: in listdir
>     items = self._stat._listdir(path)
> ftputil/stat.py:725: in _listdir
>     return self.__call_with_parser_retry(self._real_listdir, path)
> ftputil/stat.py:701: in __call_with_parser_retry
>     result = method(*args, **kwargs)
> ftputil/stat.py:579: in _real_listdir
>     if not self._path.isdir(path):
> ftputil/path.py:168: in isdir
>     return self._is_file_system_entity(path, "dir")
> ftputil/path.py:148: in _is_file_system_entity
>     stat_result = self._host.stat(
> ftputil/host.py:904: in stat
>     return self._stat._stat(path, _exception_for_missing_path)
> ftputil/stat.py:746: in _stat
>     return self.__call_with_parser_retry(self._real_stat, path,
> ftputil/stat.py:701: in __call_with_parser_retry
>     result = method(*args, **kwargs)
> ftputil/stat.py:668: in _real_stat
>     lstat_result = self._real_lstat(path, _exception_for_missing_path)
> ftputil/stat.py:627: in _real_lstat
>     for stat_result in self._stat_results_from_dir(dirname):
> ftputil/stat.py:541: in _stat_results_from_dir
>     lines = self._host_dir(path)
> ftputil/stat.py:533: in _host_dir
>     return self._host._dir(path)
> ftputil/host.py:854: in _dir
>     lines = self._robust_ftp_command(_FTPHost_dir_command, path,
> ftputil/host.py:608: in _robust_ftp_command
>     return command(self, "")
> ftputil/host.py:848: in _FTPHost_dir_command
>     with ftputil.error.ftplib_error_to_ftp_os_error:
> ftputil/host.py:850: in _FTPHost_dir_command
>     self._session.dir("-a", path, callback)
> _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
> 
> self = <test.mock_ftplib.MockUnixFormatSession object at 0x7ff6ae074e20>
> args = ('-a', '', <function FTPHost._dir.<locals>._FTPHost_dir_command.<locals>.callback at 0x7ff6ae14d870>)
> 
>     def dir(self, *args):
>         """
>         Provide a callback function for processing each line of a
>         directory listing. Return nothing.
>         """
>         # The callback comes last in `ftplib.FTP.dir`.
> >       if isinstance(args[-1], collections.Callable):
> E       AttributeError: module 'collections' has no attribute 'Callable'
> 
> test/mock_ftplib.py:157: AttributeError
> _____________________ TestLstatAndStat.test_failing_lstat ______________________
> 
> self = <test.test_stat.TestLstatAndStat object at 0x7ff6adef0670>
> 
>     def test_failing_lstat(self):
>         """Test whether `lstat` fails for a nonexistent path."""
>         with pytest.raises(ftputil.error.PermanentError):
> >           self.stat._lstat("/home/sschw/notthere")
> 
> test/test_stat.py:370: 
> _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
> ftputil/stat.py:735: in _lstat
>     return self.__call_with_parser_retry(self._real_lstat, path,
> ftputil/stat.py:701: in __call_with_parser_retry
>     result = method(*args, **kwargs)
> ftputil/stat.py:620: in _real_lstat
>     if not self._path.isdir(dirname) and not _exception_for_missing_path:
> ftputil/path.py:168: in isdir
>     return self._is_file_system_entity(path, "dir")
> ftputil/path.py:148: in _is_file_system_entity
>     stat_result = self._host.stat(
> ftputil/host.py:904: in stat
>     return self._stat._stat(path, _exception_for_missing_path)
> ftputil/stat.py:746: in _stat
>     return self.__call_with_parser_retry(self._real_stat, path,
> ftputil/stat.py:701: in __call_with_parser_retry
>     result = method(*args, **kwargs)
> ftputil/stat.py:668: in _real_stat
>     lstat_result = self._real_lstat(path, _exception_for_missing_path)
> ftputil/stat.py:620: in _real_lstat
>     if not self._path.isdir(dirname) and not _exception_for_missing_path:
> ftputil/path.py:168: in isdir
>     return self._is_file_system_entity(path, "dir")
> ftputil/path.py:148: in _is_file_system_entity
>     stat_result = self._host.stat(
> ftputil/host.py:904: in stat
>     return self._stat._stat(path, _exception_for_missing_path)
> ftputil/stat.py:746: in _stat
>     return self.__call_with_parser_retry(self._real_stat, path,
> ftputil/stat.py:701: in __call_with_parser_retry
>     result = method(*args, **kwargs)
> ftputil/stat.py:668: in _real_stat
>     lstat_result = self._real_lstat(path, _exception_for_missing_path)
> ftputil/stat.py:627: in _real_lstat
>     for stat_result in self._stat_results_from_dir(dirname):
> ftputil/stat.py:541: in _stat_results_from_dir
>     lines = self._host_dir(path)
> ftputil/stat.py:533: in _host_dir
>     return self._host._dir(path)
> ftputil/host.py:854: in _dir
>     lines = self._robust_ftp_command(_FTPHost_dir_command, path,
> ftputil/host.py:608: in _robust_ftp_command
>     return command(self, "")
> ftputil/host.py:848: in _FTPHost_dir_command
>     with ftputil.error.ftplib_error_to_ftp_os_error:
> ftputil/host.py:850: in _FTPHost_dir_command
>     self._session.dir("-a", path, callback)
> _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
> 
> self = <test.mock_ftplib.MockUnixFormatSession object at 0x7ff6adef0fd0>
> args = ('-a', '', <function FTPHost._dir.<locals>._FTPHost_dir_command.<locals>.callback at 0x7ff6ae14e560>)
> 
>     def dir(self, *args):
>         """
>         Provide a callback function for processing each line of a
>         directory listing. Return nothing.
>         """
>         # The callback comes last in `ftplib.FTP.dir`.
> >       if isinstance(args[-1], collections.Callable):
> E       AttributeError: module 'collections' has no attribute 'Callable'
> 
> test/mock_ftplib.py:157: AttributeError
> __________________ TestLstatAndStat.test_lstat_one_unix_file ___________________
> 
> self = <test.test_stat.TestLstatAndStat object at 0x7ff6ae163280>
> 
>     def test_lstat_one_unix_file(self):
>         """Test `lstat` for a file described in Unix-style format."""
> >       stat_result = self.stat._lstat("/home/sschwarzer/index.html")
> 
> test/test_stat.py:390: 
> _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
> ftputil/stat.py:735: in _lstat
>     return self.__call_with_parser_retry(self._real_lstat, path,
> ftputil/stat.py:701: in __call_with_parser_retry
>     result = method(*args, **kwargs)
> ftputil/stat.py:627: in _real_lstat
>     for stat_result in self._stat_results_from_dir(dirname):
> ftputil/stat.py:541: in _stat_results_from_dir
>     lines = self._host_dir(path)
> ftputil/stat.py:533: in _host_dir
>     return self._host._dir(path)
> ftputil/host.py:854: in _dir
>     lines = self._robust_ftp_command(_FTPHost_dir_command, path,
> ftputil/host.py:608: in _robust_ftp_command
>     return command(self, "")
> ftputil/host.py:848: in _FTPHost_dir_command
>     with ftputil.error.ftplib_error_to_ftp_os_error:
> ftputil/host.py:850: in _FTPHost_dir_command
>     self._session.dir("-a", path, callback)
> _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
> 
> self = <test.mock_ftplib.MockUnixFormatSession object at 0x7ff6ae162ec0>
> args = ('-a', '', <function FTPHost._dir.<locals>._FTPHost_dir_command.<locals>.callback at 0x7ff6ae14e3b0>)
> 
>     def dir(self, *args):
>         """
>         Provide a callback function for processing each line of a
>         directory listing. Return nothing.
>         """
>         # The callback comes last in `ftplib.FTP.dir`.
> >       if isinstance(args[-1], collections.Callable):
> E       AttributeError: module 'collections' has no attribute 'Callable'
> 
> test/mock_ftplib.py:157: AttributeError
> ___________________ TestLstatAndStat.test_lstat_one_ms_file ____________________
> 
> self = <test.test_stat.TestLstatAndStat object at 0x7ff6adf3af20>
> 
>     def test_lstat_one_ms_file(self):
>         """Test `lstat` for a file described in DOS-style format."""
>         self.stat = _test_stat(session_factory=mock_ftplib.MockMSFormatSession)
> >       stat_result = self.stat._lstat("/home/msformat/abcd.exe")
> 
> test/test_stat.py:399: 
> _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
> ftputil/stat.py:735: in _lstat
>     return self.__call_with_parser_retry(self._real_lstat, path,
> ftputil/stat.py:701: in __call_with_parser_retry
>     result = method(*args, **kwargs)
> ftputil/stat.py:620: in _real_lstat
>     if not self._path.isdir(dirname) and not _exception_for_missing_path:
> ftputil/path.py:168: in isdir
>     return self._is_file_system_entity(path, "dir")
> ftputil/path.py:148: in _is_file_system_entity
>     stat_result = self._host.stat(
> ftputil/host.py:904: in stat
>     return self._stat._stat(path, _exception_for_missing_path)
> ftputil/stat.py:746: in _stat
>     return self.__call_with_parser_retry(self._real_stat, path,
> ftputil/stat.py:701: in __call_with_parser_retry
>     result = method(*args, **kwargs)
> ftputil/stat.py:668: in _real_stat
>     lstat_result = self._real_lstat(path, _exception_for_missing_path)
> ftputil/stat.py:620: in _real_lstat
>     if not self._path.isdir(dirname) and not _exception_for_missing_path:
> ftputil/path.py:168: in isdir
>     return self._is_file_system_entity(path, "dir")
> ftputil/path.py:148: in _is_file_system_entity
>     stat_result = self._host.stat(
> ftputil/host.py:904: in stat
>     return self._stat._stat(path, _exception_for_missing_path)
> ftputil/stat.py:746: in _stat
>     return self.__call_with_parser_retry(self._real_stat, path,
> ftputil/stat.py:701: in __call_with_parser_retry
>     result = method(*args, **kwargs)
> ftputil/stat.py:668: in _real_stat
>     lstat_result = self._real_lstat(path, _exception_for_missing_path)
> ftputil/stat.py:627: in _real_lstat
>     for stat_result in self._stat_results_from_dir(dirname):
> ftputil/stat.py:541: in _stat_results_from_dir
>     lines = self._host_dir(path)
> ftputil/stat.py:533: in _host_dir
>     return self._host._dir(path)
> ftputil/host.py:854: in _dir
>     lines = self._robust_ftp_command(_FTPHost_dir_command, path,
> ftputil/host.py:608: in _robust_ftp_command
>     return command(self, "")
> ftputil/host.py:848: in _FTPHost_dir_command
>     with ftputil.error.ftplib_error_to_ftp_os_error:
> ftputil/host.py:850: in _FTPHost_dir_command
>     self._session.dir("-a", path, callback)
> _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
> 
> self = <test.mock_ftplib.MockMSFormatSession object at 0x7ff6adf3a2f0>
> args = ('-a', '', <function FTPHost._dir.<locals>._FTPHost_dir_command.<locals>.callback at 0x7ff6ae14e950>)
> 
>     def dir(self, *args):
>         """
>         Provide a callback function for processing each line of a
>         directory listing. Return nothing.
>         """
>         # The callback comes last in `ftplib.FTP.dir`.
> >       if isinstance(args[-1], collections.Callable):
> E       AttributeError: module 'collections' has no attribute 'Callable'
> 
> test/mock_ftplib.py:157: AttributeError
> ___________________ TestLstatAndStat.test_lstat_one_unix_dir ___________________
> 
> self = <test.test_stat.TestLstatAndStat object at 0x7ff6adfd9720>
> 
>     def test_lstat_one_unix_dir(self):
>         """Test `lstat` for a directory described in Unix-style format."""
> >       stat_result = self.stat._lstat("/home/sschwarzer/scios2")
> 
> test/test_stat.py:404: 
> _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
> ftputil/stat.py:735: in _lstat
>     return self.__call_with_parser_retry(self._real_lstat, path,
> ftputil/stat.py:701: in __call_with_parser_retry
>     result = method(*args, **kwargs)
> ftputil/stat.py:627: in _real_lstat
>     for stat_result in self._stat_results_from_dir(dirname):
> ftputil/stat.py:541: in _stat_results_from_dir
>     lines = self._host_dir(path)
> ftputil/stat.py:533: in _host_dir
>     return self._host._dir(path)
> ftputil/host.py:854: in _dir
>     lines = self._robust_ftp_command(_FTPHost_dir_command, path,
> ftputil/host.py:608: in _robust_ftp_command
>     return command(self, "")
> ftputil/host.py:848: in _FTPHost_dir_command
>     with ftputil.error.ftplib_error_to_ftp_os_error:
> ftputil/host.py:850: in _FTPHost_dir_command
>     self._session.dir("-a", path, callback)
> _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
> 
> self = <test.mock_ftplib.MockUnixFormatSession object at 0x7ff6adfdae00>
> args = ('-a', '', <function FTPHost._dir.<locals>._FTPHost_dir_command.<locals>.callback at 0x7ff6ae14e440>)
> 
>     def dir(self, *args):
>         """
>         Provide a callback function for processing each line of a
>         directory listing. Return nothing.
>         """
>         # The callback comes last in `ftplib.FTP.dir`.
> >       if isinstance(args[-1], collections.Callable):
> E       AttributeError: module 'collections' has no attribute 'Callable'
> 
> test/mock_ftplib.py:157: AttributeError
> ____________________ TestLstatAndStat.test_lstat_one_ms_dir ____________________
> 
> self = <test.test_stat.TestLstatAndStat object at 0x7ff6ade83430>
> 
>     def test_lstat_one_ms_dir(self):
>         """Test `lstat` for a directory described in DOS-style format."""
>         self.stat = _test_stat(session_factory=mock_ftplib.MockMSFormatSession)
> >       stat_result = self.stat._lstat("/home/msformat/WindowsXP")
> 
> test/test_stat.py:425: 
> _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
> ftputil/stat.py:735: in _lstat
>     return self.__call_with_parser_retry(self._real_lstat, path,
> ftputil/stat.py:701: in __call_with_parser_retry
>     result = method(*args, **kwargs)
> ftputil/stat.py:620: in _real_lstat
>     if not self._path.isdir(dirname) and not _exception_for_missing_path:
> ftputil/path.py:168: in isdir
>     return self._is_file_system_entity(path, "dir")
> ftputil/path.py:148: in _is_file_system_entity
>     stat_result = self._host.stat(
> ftputil/host.py:904: in stat
>     return self._stat._stat(path, _exception_for_missing_path)
> ftputil/stat.py:746: in _stat
>     return self.__call_with_parser_retry(self._real_stat, path,
> ftputil/stat.py:701: in __call_with_parser_retry
>     result = method(*args, **kwargs)
> ftputil/stat.py:668: in _real_stat
>     lstat_result = self._real_lstat(path, _exception_for_missing_path)
> ftputil/stat.py:620: in _real_lstat
>     if not self._path.isdir(dirname) and not _exception_for_missing_path:
> ftputil/path.py:168: in isdir
>     return self._is_file_system_entity(path, "dir")
> ftputil/path.py:148: in _is_file_system_entity
>     stat_result = self._host.stat(
> ftputil/host.py:904: in stat
>     return self._stat._stat(path, _exception_for_missing_path)
> ftputil/stat.py:746: in _stat
>     return self.__call_with_parser_retry(self._real_stat, path,
> ftputil/stat.py:701: in __call_with_parser_retry
>     result = method(*args, **kwargs)
> ftputil/stat.py:668: in _real_stat
>     lstat_result = self._real_lstat(path, _exception_for_missing_path)
> ftputil/stat.py:627: in _real_lstat
>     for stat_result in self._stat_results_from_dir(dirname):
> ftputil/stat.py:541: in _stat_results_from_dir
>     lines = self._host_dir(path)
> ftputil/stat.py:533: in _host_dir
>     return self._host._dir(path)
> ftputil/host.py:854: in _dir
>     lines = self._robust_ftp_command(_FTPHost_dir_command, path,
> ftputil/host.py:608: in _robust_ftp_command
>     return command(self, "")
> ftputil/host.py:848: in _FTPHost_dir_command
>     with ftputil.error.ftplib_error_to_ftp_os_error:
> ftputil/host.py:850: in _FTPHost_dir_command
>     self._session.dir("-a", path, callback)
> _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
> 
> self = <test.mock_ftplib.MockMSFormatSession object at 0x7ff6ade83e80>
> args = ('-a', '', <function FTPHost._dir.<locals>._FTPHost_dir_command.<locals>.callback at 0x7ff6ae14ee60>)
> 
>     def dir(self, *args):
>         """
>         Provide a callback function for processing each line of a
>         directory listing. Return nothing.
>         """
>         # The callback comes last in `ftplib.FTP.dir`.
> >       if isinstance(args[-1], collections.Callable):
> E       AttributeError: module 'collections' has no attribute 'Callable'
> 
> test/mock_ftplib.py:157: AttributeError
> _________________ TestLstatAndStat.test_lstat_via_stat_module __________________
> 
> self = <test.test_stat.TestLstatAndStat object at 0x7ff6ae039930>
> 
>     def test_lstat_via_stat_module(self):
>         """Test `lstat` indirectly via `stat` module."""
> >       stat_result = self.stat._lstat("/home/sschwarzer/")
> 
> test/test_stat.py:430: 
> _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
> ftputil/stat.py:735: in _lstat
>     return self.__call_with_parser_retry(self._real_lstat, path,
> ftputil/stat.py:701: in __call_with_parser_retry
>     result = method(*args, **kwargs)
> ftputil/stat.py:620: in _real_lstat
>     if not self._path.isdir(dirname) and not _exception_for_missing_path:
> ftputil/path.py:168: in isdir
>     return self._is_file_system_entity(path, "dir")
> ftputil/path.py:148: in _is_file_system_entity
>     stat_result = self._host.stat(
> ftputil/host.py:904: in stat
>     return self._stat._stat(path, _exception_for_missing_path)
> ftputil/stat.py:746: in _stat
>     return self.__call_with_parser_retry(self._real_stat, path,
> ftputil/stat.py:701: in __call_with_parser_retry
>     result = method(*args, **kwargs)
> ftputil/stat.py:668: in _real_stat
>     lstat_result = self._real_lstat(path, _exception_for_missing_path)
> ftputil/stat.py:627: in _real_lstat
>     for stat_result in self._stat_results_from_dir(dirname):
> ftputil/stat.py:541: in _stat_results_from_dir
>     lines = self._host_dir(path)
> ftputil/stat.py:533: in _host_dir
>     return self._host._dir(path)
> ftputil/host.py:854: in _dir
>     lines = self._robust_ftp_command(_FTPHost_dir_command, path,
> ftputil/host.py:608: in _robust_ftp_command
>     return command(self, "")
> ftputil/host.py:848: in _FTPHost_dir_command
>     with ftputil.error.ftplib_error_to_ftp_os_error:
> ftputil/host.py:850: in _FTPHost_dir_command
>     self._session.dir("-a", path, callback)
> _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
> 
> self = <test.mock_ftplib.MockUnixFormatSession object at 0x7ff6ae03b1c0>
> args = ('-a', '', <function FTPHost._dir.<locals>._FTPHost_dir_command.<locals>.callback at 0x7ff6ae14c280>)
> 
>     def dir(self, *args):
>         """
>         Provide a callback function for processing each line of a
>         directory listing. Return nothing.
>         """
>         # The callback comes last in `ftplib.FTP.dir`.
> >       if isinstance(args[-1], collections.Callable):
> E       AttributeError: module 'collections' has no attribute 'Callable'
> 
> test/mock_ftplib.py:157: AttributeError
> __________________ TestLstatAndStat.test_stat_following_link ___________________
> 
> self = <test.test_stat.TestLstatAndStat object at 0x7ff6ade82dd0>
> 
>     def test_stat_following_link(self):
>         """Test `stat` when invoked on a link."""
>         # Simple link
> >       stat_result = self.stat._stat("/home/link")
> 
> test/test_stat.py:436: 
> _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
> ftputil/stat.py:746: in _stat
>     return self.__call_with_parser_retry(self._real_stat, path,
> ftputil/stat.py:701: in __call_with_parser_retry
>     result = method(*args, **kwargs)
> ftputil/stat.py:668: in _real_stat
>     lstat_result = self._real_lstat(path, _exception_for_missing_path)
> ftputil/stat.py:620: in _real_lstat
>     if not self._path.isdir(dirname) and not _exception_for_missing_path:
> ftputil/path.py:168: in isdir
>     return self._is_file_system_entity(path, "dir")
> ftputil/path.py:148: in _is_file_system_entity
>     stat_result = self._host.stat(
> ftputil/host.py:904: in stat
>     return self._stat._stat(path, _exception_for_missing_path)
> ftputil/stat.py:746: in _stat
>     return self.__call_with_parser_retry(self._real_stat, path,
> ftputil/stat.py:701: in __call_with_parser_retry
>     result = method(*args, **kwargs)
> ftputil/stat.py:668: in _real_stat
>     lstat_result = self._real_lstat(path, _exception_for_missing_path)
> ftputil/stat.py:627: in _real_lstat
>     for stat_result in self._stat_results_from_dir(dirname):
> ftputil/stat.py:541: in _stat_results_from_dir
>     lines = self._host_dir(path)
> ftputil/stat.py:533: in _host_dir
>     return self._host._dir(path)
> ftputil/host.py:854: in _dir
>     lines = self._robust_ftp_command(_FTPHost_dir_command, path,
> ftputil/host.py:608: in _robust_ftp_command
>     return command(self, "")
> ftputil/host.py:848: in _FTPHost_dir_command
>     with ftputil.error.ftplib_error_to_ftp_os_error:
> ftputil/host.py:850: in _FTPHost_dir_command
>     self._session.dir("-a", path, callback)
> _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
> 
> self = <test.mock_ftplib.MockUnixFormatSession object at 0x7ff6ade802e0>
> args = ('-a', '', <function FTPHost._dir.<locals>._FTPHost_dir_command.<locals>.callback at 0x7ff6ae14d5a0>)
> 
>     def dir(self, *args):
>         """
>         Provide a callback function for processing each line of a
>         directory listing. Return nothing.
>         """
>         # The callback comes last in `ftplib.FTP.dir`.
> >       if isinstance(args[-1], collections.Callable):
> E       AttributeError: module 'collections' has no attribute 'Callable'
> 
> test/mock_ftplib.py:157: AttributeError
> _________ TestLstatAndStat.test_parser_switching_with_permanent_error __________
> 
> self = <test.test_stat.TestLstatAndStat object at 0x7ff6add91150>
> 
>     def test_parser_switching_with_permanent_error(self):
>         """Test non-switching of parser format with `PermanentError`."""
>         self.stat = _test_stat(session_factory=mock_ftplib.MockMSFormatSession)
>         assert self.stat._allow_parser_switching is True
>         # With these directory contents, we get a `ParserError` for
>         # the Unix parser first, so `_allow_parser_switching` can be
>         # switched off no matter whether we got a `PermanentError`
>         # afterward or not.
>         with pytest.raises(ftputil.error.PermanentError):
> >           self.stat._lstat("/home/msformat/nonexistent")
> 
> test/test_stat.py:461: 
> _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
> ftputil/stat.py:735: in _lstat
>     return self.__call_with_parser_retry(self._real_lstat, path,
> ftputil/stat.py:701: in __call_with_parser_retry
>     result = method(*args, **kwargs)
> ftputil/stat.py:620: in _real_lstat
>     if not self._path.isdir(dirname) and not _exception_for_missing_path:
> ftputil/path.py:168: in isdir
>     return self._is_file_system_entity(path, "dir")
> ftputil/path.py:148: in _is_file_system_entity
>     stat_result = self._host.stat(
> ftputil/host.py:904: in stat
>     return self._stat._stat(path, _exception_for_missing_path)
> ftputil/stat.py:746: in _stat
>     return self.__call_with_parser_retry(self._real_stat, path,
> ftputil/stat.py:701: in __call_with_parser_retry
>     result = method(*args, **kwargs)
> ftputil/stat.py:668: in _real_stat
>     lstat_result = self._real_lstat(path, _exception_for_missing_path)
> ftputil/stat.py:620: in _real_lstat
>     if not self._path.isdir(dirname) and not _exception_for_missing_path:
> ftputil/path.py:168: in isdir
>     return self._is_file_system_entity(path, "dir")
> ftputil/path.py:148: in _is_file_system_entity
>     stat_result = self._host.stat(
> ftputil/host.py:904: in stat
>     return self._stat._stat(path, _exception_for_missing_path)
> ftputil/stat.py:746: in _stat
>     return self.__call_with_parser_retry(self._real_stat, path,
> ftputil/stat.py:701: in __call_with_parser_retry
>     result = method(*args, **kwargs)
> ftputil/stat.py:668: in _real_stat
>     lstat_result = self._real_lstat(path, _exception_for_missing_path)
> ftputil/stat.py:627: in _real_lstat
>     for stat_result in self._stat_results_from_dir(dirname):
> ftputil/stat.py:541: in _stat_results_from_dir
>     lines = self._host_dir(path)
> ftputil/stat.py:533: in _host_dir
>     return self._host._dir(path)
> ftputil/host.py:854: in _dir
>     lines = self._robust_ftp_command(_FTPHost_dir_command, path,
> ftputil/host.py:608: in _robust_ftp_command
>     return command(self, "")
> ftputil/host.py:848: in _FTPHost_dir_command
>     with ftputil.error.ftplib_error_to_ftp_os_error:
> ftputil/host.py:850: in _FTPHost_dir_command
>     self._session.dir("-a", path, callback)
> _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
> 
> self = <test.mock_ftplib.MockMSFormatSession object at 0x7ff6add90310>
> args = ('-a', '', <function FTPHost._dir.<locals>._FTPHost_dir_command.<locals>.callback at 0x7ff6ae14ea70>)
> 
>     def dir(self, *args):
>         """
>         Provide a callback function for processing each line of a
>         directory listing. Return nothing.
>         """
>         # The callback comes last in `ftplib.FTP.dir`.
> >       if isinstance(args[-1], collections.Callable):
> E       AttributeError: module 'collections' has no attribute 'Callable'
> 
> test/mock_ftplib.py:157: AttributeError
> ____________ TestLstatAndStat.test_parser_switching_default_to_unix ____________
> 
> self = <test.test_stat.TestLstatAndStat object at 0x7ff6adef2bf0>
> 
>     def test_parser_switching_default_to_unix(self):
>         """Test non-switching of parser format; stay with Unix."""
>         assert self.stat._allow_parser_switching is True
>         assert isinstance(self.stat._parser, ftputil.stat.UnixParser)
> >       stat_result = self.stat._lstat("/home/sschwarzer/index.html")
> 
> test/test_stat.py:468: 
> _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
> ftputil/stat.py:735: in _lstat
>     return self.__call_with_parser_retry(self._real_lstat, path,
> ftputil/stat.py:701: in __call_with_parser_retry
>     result = method(*args, **kwargs)
> ftputil/stat.py:627: in _real_lstat
>     for stat_result in self._stat_results_from_dir(dirname):
> ftputil/stat.py:541: in _stat_results_from_dir
>     lines = self._host_dir(path)
> ftputil/stat.py:533: in _host_dir
>     return self._host._dir(path)
> ftputil/host.py:854: in _dir
>     lines = self._robust_ftp_command(_FTPHost_dir_command, path,
> ftputil/host.py:608: in _robust_ftp_command
>     return command(self, "")
> ftputil/host.py:848: in _FTPHost_dir_command
>     with ftputil.error.ftplib_error_to_ftp_os_error:
> ftputil/host.py:850: in _FTPHost_dir_command
>     self._session.dir("-a", path, callback)
> _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
> 
> self = <test.mock_ftplib.MockUnixFormatSession object at 0x7ff6adef2380>
> args = ('-a', '', <function FTPHost._dir.<locals>._FTPHost_dir_command.<locals>.callback at 0x7ff6ae14eb00>)
> 
>     def dir(self, *args):
>         """
>         Provide a callback function for processing each line of a
>         directory listing. Return nothing.
>         """
>         # The callback comes last in `ftplib.FTP.dir`.
> >       if isinstance(args[-1], collections.Callable):
> E       AttributeError: module 'collections' has no attribute 'Callable'
> 
> test/mock_ftplib.py:157: AttributeError
> _________________ TestLstatAndStat.test_parser_switching_to_ms _________________
> 
> self = <test.test_stat.TestLstatAndStat object at 0x7ff6ae0d2410>
> 
>     def test_parser_switching_to_ms(self):
>         """Test switching of parser from Unix to MS format."""
>         self.stat = _test_stat(session_factory=mock_ftplib.MockMSFormatSession)
>         assert self.stat._allow_parser_switching is True
>         assert isinstance(self.stat._parser, ftputil.stat.UnixParser)
>         # Parsing the directory `/home/msformat` with the Unix parser
>         # fails, so switch to the MS parser.
> >       stat_result = self.stat._lstat("/home/msformat/abcd.exe")
> 
> test/test_stat.py:480: 
> _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
> ftputil/stat.py:735: in _lstat
>     return self.__call_with_parser_retry(self._real_lstat, path,
> ftputil/stat.py:701: in __call_with_parser_retry
>     result = method(*args, **kwargs)
> ftputil/stat.py:620: in _real_lstat
>     if not self._path.isdir(dirname) and not _exception_for_missing_path:
> ftputil/path.py:168: in isdir
>     return self._is_file_system_entity(path, "dir")
> ftputil/path.py:148: in _is_file_system_entity
>     stat_result = self._host.stat(
> ftputil/host.py:904: in stat
>     return self._stat._stat(path, _exception_for_missing_path)
> ftputil/stat.py:746: in _stat
>     return self.__call_with_parser_retry(self._real_stat, path,
> ftputil/stat.py:701: in __call_with_parser_retry
>     result = method(*args, **kwargs)
> ftputil/stat.py:668: in _real_stat
>     lstat_result = self._real_lstat(path, _exception_for_missing_path)
> ftputil/stat.py:620: in _real_lstat
>     if not self._path.isdir(dirname) and not _exception_for_missing_path:
> ftputil/path.py:168: in isdir
>     return self._is_file_system_entity(path, "dir")
> ftputil/path.py:148: in _is_file_system_entity
>     stat_result = self._host.stat(
> ftputil/host.py:904: in stat
>     return self._stat._stat(path, _exception_for_missing_path)
> ftputil/stat.py:746: in _stat
>     return self.__call_with_parser_retry(self._real_stat, path,
> ftputil/stat.py:701: in __call_with_parser_retry
>     result = method(*args, **kwargs)
> ftputil/stat.py:668: in _real_stat
>     lstat_result = self._real_lstat(path, _exception_for_missing_path)
> ftputil/stat.py:627: in _real_lstat
>     for stat_result in self._stat_results_from_dir(dirname):
> ftputil/stat.py:541: in _stat_results_from_dir
>     lines = self._host_dir(path)
> ftputil/stat.py:533: in _host_dir
>     return self._host._dir(path)
> ftputil/host.py:854: in _dir
>     lines = self._robust_ftp_command(_FTPHost_dir_command, path,
> ftputil/host.py:608: in _robust_ftp_command
>     return command(self, "")
> ftputil/host.py:848: in _FTPHost_dir_command
>     with ftputil.error.ftplib_error_to_ftp_os_error:
> ftputil/host.py:850: in _FTPHost_dir_command
>     self._session.dir("-a", path, callback)
> _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
> 
> self = <test.mock_ftplib.MockMSFormatSession object at 0x7ff6ae0d3490>
> args = ('-a', '', <function FTPHost._dir.<locals>._FTPHost_dir_command.<locals>.callback at 0x7ff6ae14e5f0>)
> 
>     def dir(self, *args):
>         """
>         Provide a callback function for processing each line of a
>         directory listing. Return nothing.
>         """
>         # The callback comes last in `ftplib.FTP.dir`.
> >       if isinstance(args[-1], collections.Callable):
> E       AttributeError: module 'collections' has no attribute 'Callable'
> 
> test/mock_ftplib.py:157: AttributeError
> __________ TestLstatAndStat.test_parser_switching_regarding_empty_dir __________
> 
> self = <test.test_stat.TestLstatAndStat object at 0x7ff6ae0a5630>
> 
>     def test_parser_switching_regarding_empty_dir(self):
>         """Test switching of parser if a directory is empty."""
>         self.stat = _test_stat(session_factory=mock_ftplib.MockMSFormatSession)
>         assert self.stat._allow_parser_switching is True
>         # When the directory we're looking into doesn't give us any
>         # lines we can't decide whether the first parser worked,
>         # because it wasn't applied. So keep the parser for now.
> >       result = self.stat._listdir("/home/msformat/XPLaunch/empty")
> 
> test/test_stat.py:493: 
> _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
> ftputil/stat.py:725: in _listdir
>     return self.__call_with_parser_retry(self._real_listdir, path)
> ftputil/stat.py:701: in __call_with_parser_retry
>     result = method(*args, **kwargs)
> ftputil/stat.py:579: in _real_listdir
>     if not self._path.isdir(path):
> ftputil/path.py:168: in isdir
>     return self._is_file_system_entity(path, "dir")
> ftputil/path.py:148: in _is_file_system_entity
>     stat_result = self._host.stat(
> ftputil/host.py:904: in stat
>     return self._stat._stat(path, _exception_for_missing_path)
> ftputil/stat.py:746: in _stat
>     return self.__call_with_parser_retry(self._real_stat, path,
> ftputil/stat.py:701: in __call_with_parser_retry
>     result = method(*args, **kwargs)
> ftputil/stat.py:668: in _real_stat
>     lstat_result = self._real_lstat(path, _exception_for_missing_path)
> ftputil/stat.py:620: in _real_lstat
>     if not self._path.isdir(dirname) and not _exception_for_missing_path:
> ftputil/path.py:168: in isdir
>     return self._is_file_system_entity(path, "dir")
> ftputil/path.py:148: in _is_file_system_entity
>     stat_result = self._host.stat(
> ftputil/host.py:904: in stat
>     return self._stat._stat(path, _exception_for_missing_path)
> ftputil/stat.py:746: in _stat
>     return self.__call_with_parser_retry(self._real_stat, path,
> ftputil/stat.py:701: in __call_with_parser_retry
>     result = method(*args, **kwargs)
> ftputil/stat.py:668: in _real_stat
>     lstat_result = self._real_lstat(path, _exception_for_missing_path)
> ftputil/stat.py:620: in _real_lstat
>     if not self._path.isdir(dirname) and not _exception_for_missing_path:
> ftputil/path.py:168: in isdir
>     return self._is_file_system_entity(path, "dir")
> ftputil/path.py:148: in _is_file_system_entity
>     stat_result = self._host.stat(
> ftputil/host.py:904: in stat
>     return self._stat._stat(path, _exception_for_missing_path)
> ftputil/stat.py:746: in _stat
>     return self.__call_with_parser_retry(self._real_stat, path,
> ftputil/stat.py:701: in __call_with_parser_retry
>     result = method(*args, **kwargs)
> ftputil/stat.py:668: in _real_stat
>     lstat_result = self._real_lstat(path, _exception_for_missing_path)
> ftputil/stat.py:620: in _real_lstat
>     if not self._path.isdir(dirname) and not _exception_for_missing_path:
> ftputil/path.py:168: in isdir
>     return self._is_file_system_entity(path, "dir")
> ftputil/path.py:148: in _is_file_system_entity
>     stat_result = self._host.stat(
> ftputil/host.py:904: in stat
>     return self._stat._stat(path, _exception_for_missing_path)
> ftputil/stat.py:746: in _stat
>     return self.__call_with_parser_retry(self._real_stat, path,
> ftputil/stat.py:701: in __call_with_parser_retry
>     result = method(*args, **kwargs)
> ftputil/stat.py:668: in _real_stat
>     lstat_result = self._real_lstat(path, _exception_for_missing_path)
> ftputil/stat.py:627: in _real_lstat
>     for stat_result in self._stat_results_from_dir(dirname):
> ftputil/stat.py:541: in _stat_results_from_dir
>     lines = self._host_dir(path)
> ftputil/stat.py:533: in _host_dir
>     return self._host._dir(path)
> ftputil/host.py:854: in _dir
>     lines = self._robust_ftp_command(_FTPHost_dir_command, path,
> ftputil/host.py:608: in _robust_ftp_command
>     return command(self, "")
> ftputil/host.py:848: in _FTPHost_dir_command
>     with ftputil.error.ftplib_error_to_ftp_os_error:
> ftputil/host.py:850: in _FTPHost_dir_command
>     self._session.dir("-a", path, callback)
> _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
> 
> self = <test.mock_ftplib.MockMSFormatSession object at 0x7ff6ae0a4100>
> args = ('-a', '', <function FTPHost._dir.<locals>._FTPHost_dir_command.<locals>.callback at 0x7ff6ae14d870>)
> 
>     def dir(self, *args):
>         """
>         Provide a callback function for processing each line of a
>         directory listing. Return nothing.
>         """
>         # The callback comes last in `ftplib.FTP.dir`.
> >       if isinstance(args[-1], collections.Callable):
> E       AttributeError: module 'collections' has no attribute 'Callable'
> 
> test/mock_ftplib.py:157: AttributeError
> _______________________ TestListdir.test_failing_listdir _______________________
> 
> self = <test.test_stat.TestListdir object at 0x7ff6ae1d6230>
> 
>     def test_failing_listdir(self):
>         """Test failing `FTPHost.listdir`."""
>         with pytest.raises(ftputil.error.PermanentError):
> >           self.stat._listdir("notthere")
> 
> test/test_stat.py:509: 
> _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
> ftputil/stat.py:725: in _listdir
>     return self.__call_with_parser_retry(self._real_listdir, path)
> ftputil/stat.py:701: in __call_with_parser_retry
>     result = method(*args, **kwargs)
> ftputil/stat.py:579: in _real_listdir
>     if not self._path.isdir(path):
> ftputil/path.py:168: in isdir
>     return self._is_file_system_entity(path, "dir")
> ftputil/path.py:148: in _is_file_system_entity
>     stat_result = self._host.stat(
> ftputil/host.py:904: in stat
>     return self._stat._stat(path, _exception_for_missing_path)
> ftputil/stat.py:746: in _stat
>     return self.__call_with_parser_retry(self._real_stat, path,
> ftputil/stat.py:701: in __call_with_parser_retry
>     result = method(*args, **kwargs)
> ftputil/stat.py:668: in _real_stat
>     lstat_result = self._real_lstat(path, _exception_for_missing_path)
> ftputil/stat.py:627: in _real_lstat
>     for stat_result in self._stat_results_from_dir(dirname):
> ftputil/stat.py:541: in _stat_results_from_dir
>     lines = self._host_dir(path)
> ftputil/stat.py:533: in _host_dir
>     return self._host._dir(path)
> ftputil/host.py:854: in _dir
>     lines = self._robust_ftp_command(_FTPHost_dir_command, path,
> ftputil/host.py:608: in _robust_ftp_command
>     return command(self, "")
> ftputil/host.py:848: in _FTPHost_dir_command
>     with ftputil.error.ftplib_error_to_ftp_os_error:
> ftputil/host.py:850: in _FTPHost_dir_command
>     self._session.dir("-a", path, callback)
> _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
> 
> self = <test.mock_ftplib.MockUnixFormatSession object at 0x7ff6ae1d4d60>
> args = ('-a', '', <function FTPHost._dir.<locals>._FTPHost_dir_command.<locals>.callback at 0x7ff6ae14d990>)
> 
>     def dir(self, *args):
>         """
>         Provide a callback function for processing each line of a
>         directory listing. Return nothing.
>         """
>         # The callback comes last in `ftplib.FTP.dir`.
> >       if isinstance(args[-1], collections.Callable):
> E       AttributeError: module 'collections' has no attribute 'Callable'
> 
> test/mock_ftplib.py:157: AttributeError
> _____________________ TestListdir.test_succeeding_listdir ______________________
> 
> self = <test.test_stat.TestListdir object at 0x7ff6ae6d5d50>
> 
>     def test_succeeding_listdir(self):
>         """Test succeeding `FTPHost.listdir`."""
>         # Do we have all expected "files"?
> >       assert len(self.stat._listdir(".")) == 9
> 
> test/test_stat.py:514: 
> _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
> ftputil/stat.py:725: in _listdir
>     return self.__call_with_parser_retry(self._real_listdir, path)
> ftputil/stat.py:701: in __call_with_parser_retry
>     result = method(*args, **kwargs)
> ftputil/stat.py:585: in _real_listdir
>     for stat_result in self._stat_results_from_dir(path):
> ftputil/stat.py:541: in _stat_results_from_dir
>     lines = self._host_dir(path)
> ftputil/stat.py:533: in _host_dir
>     return self._host._dir(path)
> ftputil/host.py:854: in _dir
>     lines = self._robust_ftp_command(_FTPHost_dir_command, path,
> ftputil/host.py:608: in _robust_ftp_command
>     return command(self, "")
> ftputil/host.py:848: in _FTPHost_dir_command
>     with ftputil.error.ftplib_error_to_ftp_os_error:
> ftputil/host.py:850: in _FTPHost_dir_command
>     self._session.dir("-a", path, callback)
> _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
> 
> self = <test.mock_ftplib.MockUnixFormatSession object at 0x7ff6ae6d6890>
> args = ('-a', '', <function FTPHost._dir.<locals>._FTPHost_dir_command.<locals>.callback at 0x7ff6ae14e0e0>)
> 
>     def dir(self, *args):
>         """
>         Provide a callback function for processing each line of a
>         directory listing. Return nothing.
>         """
>         # The callback comes last in `ftplib.FTP.dir`.
> >       if isinstance(args[-1], collections.Callable):
> E       AttributeError: module 'collections' has no attribute 'Callable'
> 
> test/mock_ftplib.py:157: AttributeError
> ______________________ TestStatCache.test_cache_size_zero ______________________
> 
> self = <test.test_stat_cache.TestStatCache object at 0x7ff6add7c190>
> 
>     def test_cache_size_zero(self):
>         host = test_base.ftp_host_factory()
>         with pytest.raises(ValueError):
>             host.stat_cache.resize(0)
>         # If bug #38 was present, this raised an `IndexError`.
> >       items = host.listdir(host.curdir)
> 
> test/test_stat_cache.py:102: 
> _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
> ftputil/host.py:871: in listdir
>     items = self._stat._listdir(path)
> ftputil/stat.py:725: in _listdir
>     return self.__call_with_parser_retry(self._real_listdir, path)
> ftputil/stat.py:701: in __call_with_parser_retry
>     result = method(*args, **kwargs)
> ftputil/stat.py:585: in _real_listdir
>     for stat_result in self._stat_results_from_dir(path):
> ftputil/stat.py:541: in _stat_results_from_dir
>     lines = self._host_dir(path)
> ftputil/stat.py:533: in _host_dir
>     return self._host._dir(path)
> ftputil/host.py:854: in _dir
>     lines = self._robust_ftp_command(_FTPHost_dir_command, path,
> ftputil/host.py:608: in _robust_ftp_command
>     return command(self, "")
> ftputil/host.py:848: in _FTPHost_dir_command
>     with ftputil.error.ftplib_error_to_ftp_os_error:
> ftputil/host.py:850: in _FTPHost_dir_command
>     self._session.dir("-a", path, callback)
> _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
> 
> self = <test.mock_ftplib.MockUnixFormatSession object at 0x7ff6add7c070>
> args = ('-a', '', <function FTPHost._dir.<locals>._FTPHost_dir_command.<locals>.callback at 0x7ff6ae14ef80>)
> 
>     def dir(self, *args):
>         """
>         Provide a callback function for processing each line of a
>         directory listing. Return nothing.
>         """
>         # The callback comes last in `ftplib.FTP.dir`.
> >       if isinstance(args[-1], collections.Callable):
> E       AttributeError: module 'collections' has no attribute 'Callable'
> 
> test/mock_ftplib.py:157: AttributeError
> =============================== warnings summary ===============================
> .pybuild/cpython3_3.10_ftputil/build/test/test_file.py: 18 warnings
> .pybuild/cpython3_3.10_ftputil/build/test/test_host.py: 32 warnings
> .pybuild/cpython3_3.10_ftputil/build/test/test_path.py: 12 warnings
> .pybuild/cpython3_3.10_ftputil/build/test/test_stat.py: 26 warnings
> .pybuild/cpython3_3.10_ftputil/build/test/test_stat_cache.py: 1 warning
> .pybuild/cpython3_3.10_ftputil/build/test/test_with_statement.py: 5 warnings
>   /<<PKGBUILDDIR>>/.pybuild/cpython3_3.10_ftputil/build/test/test_base.py:16: DeprecationWarning: `use_list_a_option` will default to `False` in ftputil 4.x.x
>     return ftp_host_class("dummy_host", "dummy_user", "dummy_password",
> 
> .pybuild/cpython3_3.10_ftputil/build/test/test_file.py: 23 warnings
> .pybuild/cpython3_3.10_ftputil/build/test/test_host.py: 5 warnings
> .pybuild/cpython3_3.10_ftputil/build/test/test_with_statement.py: 3 warnings
>   /<<PKGBUILDDIR>>/.pybuild/cpython3_3.10_ftputil/build/ftputil/host.py:148: DeprecationWarning: `use_list_a_option` will default to `False` in ftputil 4.x.x
>     return self.__class__(*self._args, **self._kwargs)
> 
> .pybuild/cpython3_3.10_ftputil/build/test/test_host.py::TestTimeShift::test_synchronize_times
> .pybuild/cpython3_3.10_ftputil/build/test/test_host.py::TestTimeShift::test_synchronize_times
> .pybuild/cpython3_3.10_ftputil/build/test/test_host.py::TestTimeShift::test_synchronize_times_for_server_in_east
> .pybuild/cpython3_3.10_ftputil/build/test/test_host.py::TestTimeShift::test_synchronize_times_for_server_in_east
>   /<<PKGBUILDDIR>>/.pybuild/cpython3_3.10_ftputil/build/test/test_host.py:165: DeprecationWarning: `use_list_a_option` will default to `False` in ftputil 4.x.x
>     ftputil.FTPHost.__init__(self, *args, **kwargs)
> 
> .pybuild/cpython3_3.10_ftputil/build/test/test_sync.py::TestUploadFromWindows::test_no_mixed_separators
>   /<<PKGBUILDDIR>>/.pybuild/cpython3_3.10_ftputil/build/test/test_sync.py:104: DeprecationWarning: `use_list_a_option` will default to `False` in ftputil 4.x.x
>     super(ArgumentCheckingFTPHost, self).__init__(*args, **kwargs)
> 
> -- Docs: https://docs.pytest.org/en/stable/warnings.html
> =========================== short test summary info ============================
> FAILED test/test_host.py::TestSetParser::test_set_parser - AttributeError: mo...
> FAILED test/test_host.py::TestRecursiveListingForDotAsPath::test_recursive_listing
> FAILED test/test_host.py::TestRecursiveListingForDotAsPath::test_plain_listing
> FAILED test/test_host.py::TestRecursiveListingForDotAsPath::test_empty_string_instead_of_dot_workaround
> FAILED test/test_host.py::TestUploadAndDownload::test_conditional_upload - At...
> FAILED test/test_host.py::TestUploadAndDownload::test_conditional_download_with_older_target
> FAILED test/test_host.py::TestUploadAndDownload::test_conditional_download_with_newer_target
> FAILED test/test_host.py::TestAcceptEitherUnicodeOrBytes::test_listdir - Attr...
> FAILED test/test_host.py::TestAcceptEitherUnicodeOrBytes::test_rmdir - Attrib...
> FAILED test/test_host.py::TestAcceptEitherUnicodeOrBytes::test_remove - Attri...
> FAILED test/test_host.py::TestAcceptEitherUnicodeOrBytes::test_rmtree - Attri...
> FAILED test/test_host.py::TestAcceptEitherUnicodeOrBytes::test_lstat - Attrib...
> FAILED test/test_host.py::TestAcceptEitherUnicodeOrBytes::test_stat - Attribu...
> FAILED test/test_path.py::TestPath::test_regular_isdir_isfile_islink - Attrib...
> FAILED test/test_path.py::TestPath::test_workaround_for_spaces - AttributeErr...
> FAILED test/test_path.py::TestPath::test_isdir_isfile_with_infinite_link_chain
> FAILED test/test_path.py::TestPath::test_exists - AttributeError: module 'col...
> FAILED test/test_path.py::TestAcceptEitherBytesOrUnicode::test_methods_that_take_a_string_and_return_a_bool
> FAILED test/test_path.py::TestAcceptEitherBytesOrUnicode::test_getmtime - Att...
> FAILED test/test_path.py::TestAcceptEitherBytesOrUnicode::test_getsize - Attr...
> FAILED test/test_path.py::TestAcceptEitherBytesOrUnicode::test_walk - Attribu...
> FAILED test/test_stat.py::TestLstatAndStat::test_failing_lstat - AttributeErr...
> FAILED test/test_stat.py::TestLstatAndStat::test_lstat_one_unix_file - Attrib...
> FAILED test/test_stat.py::TestLstatAndStat::test_lstat_one_ms_file - Attribut...
> FAILED test/test_stat.py::TestLstatAndStat::test_lstat_one_unix_dir - Attribu...
> FAILED test/test_stat.py::TestLstatAndStat::test_lstat_one_ms_dir - Attribute...
> FAILED test/test_stat.py::TestLstatAndStat::test_lstat_via_stat_module - Attr...
> FAILED test/test_stat.py::TestLstatAndStat::test_stat_following_link - Attrib...
> FAILED test/test_stat.py::TestLstatAndStat::test_parser_switching_with_permanent_error
> FAILED test/test_stat.py::TestLstatAndStat::test_parser_switching_default_to_unix
> FAILED test/test_stat.py::TestLstatAndStat::test_parser_switching_to_ms - Att...
> FAILED test/test_stat.py::TestLstatAndStat::test_parser_switching_regarding_empty_dir
> FAILED test/test_stat.py::TestListdir::test_failing_listdir - AttributeError:...
> FAILED test/test_stat.py::TestListdir::test_succeeding_listdir - AttributeErr...
> FAILED test/test_stat_cache.py::TestStatCache::test_cache_size_zero - Attribu...
> ================= 35 failed, 94 passed, 130 warnings in 4.27s ==================
> E: pybuild pybuild:355: test: plugin distutils failed with: exit code=1: cd /<<PKGBUILDDIR>>/.pybuild/cpython3_3.10_ftputil/build; python3.10 -m pytest test
> I: pybuild base:237: cd /<<PKGBUILDDIR>>/.pybuild/cpython3_3.9_ftputil/build; python3.9 -m pytest test
> ============================= test session starts ==============================
> platform linux -- Python 3.9.9, pytest-6.2.5, py-1.10.0, pluggy-0.13.0
> rootdir: /<<PKGBUILDDIR>>
> collected 129 items
> 
> test/test_error.py ......                                                [  4%]
> test/test_file.py ..................                                     [ 18%]
> test/test_file_transfer.py ....                                          [ 21%]
> test/test_host.py ..................................                     [ 48%]
> test/test_path.py ............                                           [ 57%]
> test/test_session.py ......                                              [ 62%]
> test/test_stat.py ......................                                 [ 79%]
> test/test_stat_cache.py ..........                                       [ 86%]
> test/test_sync.py ...                                                    [ 89%]
> test/test_tool.py ........                                               [ 95%]
> test/test_with_statement.py ......                                       [100%]
> 
> =============================== warnings summary ===============================
> .pybuild/cpython3_3.9_ftputil/build/test/test_file.py: 18 warnings
> .pybuild/cpython3_3.9_ftputil/build/test/test_host.py: 34 warnings
> .pybuild/cpython3_3.9_ftputil/build/test/test_path.py: 13 warnings
> .pybuild/cpython3_3.9_ftputil/build/test/test_stat.py: 26 warnings
> .pybuild/cpython3_3.9_ftputil/build/test/test_stat_cache.py: 1 warning
> .pybuild/cpython3_3.9_ftputil/build/test/test_with_statement.py: 5 warnings
>   /<<PKGBUILDDIR>>/.pybuild/cpython3_3.9_ftputil/build/test/test_base.py:16: DeprecationWarning: `use_list_a_option` will default to `False` in ftputil 4.x.x
>     return ftp_host_class("dummy_host", "dummy_user", "dummy_password",
> 
> .pybuild/cpython3_3.9_ftputil/build/test/test_file.py: 23 warnings
> .pybuild/cpython3_3.9_ftputil/build/test/test_host.py: 8 warnings
> .pybuild/cpython3_3.9_ftputil/build/test/test_with_statement.py: 3 warnings
>   /<<PKGBUILDDIR>>/.pybuild/cpython3_3.9_ftputil/build/ftputil/host.py:148: DeprecationWarning: `use_list_a_option` will default to `False` in ftputil 4.x.x
>     return self.__class__(*self._args, **self._kwargs)
> 
> .pybuild/cpython3_3.9_ftputil/build/test/test_host.py::TestSetParser::test_set_parser
>   /<<PKGBUILDDIR>>/.pybuild/cpython3_3.9_ftputil/build/test/mock_ftplib.py:157: DeprecationWarning: Using or importing the ABCs from 'collections' instead of from 'collections.abc' is deprecated since Python 3.3, and in 3.10 it will stop working
>     if isinstance(args[-1], collections.Callable):
> 
> .pybuild/cpython3_3.9_ftputil/build/test/test_host.py::TestTimeShift::test_synchronize_times
> .pybuild/cpython3_3.9_ftputil/build/test/test_host.py::TestTimeShift::test_synchronize_times
> .pybuild/cpython3_3.9_ftputil/build/test/test_host.py::TestTimeShift::test_synchronize_times_for_server_in_east
> .pybuild/cpython3_3.9_ftputil/build/test/test_host.py::TestTimeShift::test_synchronize_times_for_server_in_east
>   /<<PKGBUILDDIR>>/.pybuild/cpython3_3.9_ftputil/build/test/test_host.py:165: DeprecationWarning: `use_list_a_option` will default to `False` in ftputil 4.x.x
>     ftputil.FTPHost.__init__(self, *args, **kwargs)
> 
> .pybuild/cpython3_3.9_ftputil/build/test/test_sync.py::TestUploadFromWindows::test_no_mixed_separators
>   /<<PKGBUILDDIR>>/.pybuild/cpython3_3.9_ftputil/build/test/test_sync.py:104: DeprecationWarning: `use_list_a_option` will default to `False` in ftputil 4.x.x
>     super(ArgumentCheckingFTPHost, self).__init__(*args, **kwargs)
> 
> -- Docs: https://docs.pytest.org/en/stable/warnings.html
> ====================== 129 passed, 137 warnings in 2.51s =======================
> dh_auto_test: error: pybuild --test --test-pytest -i python{version} -p "3.10 3.9" returned exit code 13


The full build log is available from:
http://qa-logs.debian.net/2021/12/20/python-ftputil_3.4-3_unstable.log

A list of current common problems and possible solutions is available at
http://wiki.debian.org/qa.debian.org/FTBFS . You're welcome to contribute!

If you reassign this bug to another package, please marking it as 'affects'-ing
this package. See https://www.debian.org/Bugs/server-control#affects

If you fail to reproduce this, please provide a build log and diff it with mine
so that we can identify if something relevant changed in the meantime.



More information about the Python-modules-team mailing list