git: fdcb5e485c27 - main - devel/py-fs: Fix build with setuptools 58.0.0+
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Mon, 07 Mar 2022 18:27:10 UTC
The branch main has been updated by sunpoet:
URL: https://cgit.FreeBSD.org/ports/commit/?id=fdcb5e485c27808fe960aa2c307fb04348f32499
commit fdcb5e485c27808fe960aa2c307fb04348f32499
Author: Po-Chuan Hsieh <sunpoet@FreeBSD.org>
AuthorDate: 2022-03-07 18:07:21 +0000
Commit: Po-Chuan Hsieh <sunpoet@FreeBSD.org>
CommitDate: 2022-03-07 18:13:18 +0000
devel/py-fs: Fix build with setuptools 58.0.0+
- While I'm here, add USES=dos2unix
With hat: python
---
devel/py-fs/Makefile | 2 +-
devel/py-fs/files/patch-2to3 | 5882 ++++++++++++++++++++++++++++++++++++++++++
2 files changed, 5883 insertions(+), 1 deletion(-)
diff --git a/devel/py-fs/Makefile b/devel/py-fs/Makefile
index aba8097c06c6..f1e9fa1377a0 100644
--- a/devel/py-fs/Makefile
+++ b/devel/py-fs/Makefile
@@ -13,7 +13,7 @@ COMMENT= Python filesystem abstraction
LICENSE= BSD3CLAUSE
LICENSE_FILE= ${WRKSRC}/LICENSE.txt
-USES= python:3.6+
+USES= dos2unix python:3.6+
USE_PYTHON= autoplist concurrent distutils
NO_ARCH= yes
diff --git a/devel/py-fs/files/patch-2to3 b/devel/py-fs/files/patch-2to3
new file mode 100644
index 000000000000..5e5874a2a21b
--- /dev/null
+++ b/devel/py-fs/files/patch-2to3
@@ -0,0 +1,5882 @@
+--- fs/appdirfs.py.orig 2015-04-12 17:24:29 UTC
++++ fs/appdirfs.py
+@@ -84,6 +84,6 @@ class UserLogFS(OSFS):
+
+ if __name__ == "__main__":
+ udfs = UserDataFS('exampleapp', appauthor='pyfs')
+- print udfs
++ print(udfs)
+ udfs2 = UserDataFS('exampleapp2', appauthor='pyfs', create=False)
+- print udfs2
++ print(udfs2)
+--- fs/appdirs.py.orig 2022-03-04 17:14:43 UTC
++++ fs/appdirs.py
+@@ -21,7 +21,7 @@ import os
+ PY3 = sys.version_info[0] == 3
+
+ if PY3:
+- unicode = str
++ str = str
+
+ class AppDirsError(Exception):
+ pass
+@@ -248,7 +248,7 @@ def _get_win_folder_from_registry(csidl_name):
+ registry for this guarantees us the correct answer for all CSIDL_*
+ names.
+ """
+- import _winreg
++ import winreg
+
+ shell_folder_name = {
+ "CSIDL_APPDATA": "AppData",
+@@ -256,9 +256,9 @@ def _get_win_folder_from_registry(csidl_name):
+ "CSIDL_LOCAL_APPDATA": "Local AppData",
+ }[csidl_name]
+
+- key = _winreg.OpenKey(_winreg.HKEY_CURRENT_USER,
++ key = winreg.OpenKey(winreg.HKEY_CURRENT_USER,
+ r"Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders")
+- dir, type = _winreg.QueryValueEx(key, shell_folder_name)
++ dir, type = winreg.QueryValueEx(key, shell_folder_name)
+ return dir
+
+ def _get_win_folder_with_pywin32(csidl_name):
+@@ -268,7 +268,7 @@ def _get_win_folder_with_pywin32(csidl_name):
+ # not return unicode strings when there is unicode data in the
+ # path.
+ try:
+- dir = unicode(dir)
++ dir = str(dir)
+
+ # Downgrade to short path name if have highbit chars. See
+ # <http://bugs.activestate.com/show_bug.cgi?id=85099>.
+@@ -337,9 +337,9 @@ if __name__ == "__main__":
+ print("-- app dirs (without optional 'version')")
+ dirs = AppDirs(appname, appauthor, version="1.0")
+ for prop in props:
+- print("%s: %s" % (prop, getattr(dirs, prop)))
++ print(("%s: %s" % (prop, getattr(dirs, prop))))
+
+ print("\n-- app dirs (with optional 'version')")
+ dirs = AppDirs(appname, appauthor)
+ for prop in props:
+- print("%s: %s" % (prop, getattr(dirs, prop)))
++ print(("%s: %s" % (prop, getattr(dirs, prop))))
+--- fs/base.py.orig 2022-03-04 17:14:43 UTC
++++ fs/base.py
+@@ -12,8 +12,8 @@ For more information regarding implementing a working
+
+ """
+
+-from __future__ import with_statement
+
++
+ __all__ = ['DummyLock',
+ 'silence_fserrors',
+ 'NullFile',
+@@ -109,7 +109,7 @@ class NullFile(object):
+ def flush(self):
+ pass
+
+- def next(self):
++ def __next__(self):
+ raise StopIteration
+
+ def readline(self, *args, **kwargs):
+@@ -900,7 +900,7 @@ class FS(object):
+ chunk_size=1024 * 64,
+ progress_callback=progress_callback,
+ finished_callback=finished_callback)
+- except Exception, e:
++ except Exception as e:
+ if error_callback is not None:
+ error_callback(e)
+ finally:
+@@ -1156,7 +1156,7 @@ class FS(object):
+ def _shutil_copyfile(cls, src_syspath, dst_syspath):
+ try:
+ shutil.copyfile(src_syspath, dst_syspath)
+- except IOError, e:
++ except IOError as e:
+ # shutil reports ENOENT when a parent directory is missing
+ if getattr(e, "errno", None) == errno.ENOENT:
+ if not os.path.exists(dirname(dst_syspath)):
+--- fs/browsewin.py.orig 2022-03-04 17:14:43 UTC
++++ fs/browsewin.py
+@@ -24,7 +24,7 @@ class InfoFrame(wx.Frame):
+
+ self.SetTitle("FS Object info - %s (%s)" % (path, desc))
+
+- keys = info.keys()
++ keys = list(info.keys())
+ keys.sort()
+
+ self.list_ctrl = wx.ListCtrl(self, -1, style=wx.LC_REPORT|wx.SUNKEN_BORDER)
+@@ -36,7 +36,7 @@ class InfoFrame(wx.Frame):
+ self.list_ctrl.SetColumnWidth(1, 300)
+
+ for key in sorted(keys, key=lambda k:k.lower()):
+- self.list_ctrl.Append((key, unicode(info.get(key))))
++ self.list_ctrl.Append((key, str(info.get(key))))
+
+ self.Center()
+
+@@ -50,7 +50,7 @@ class BrowseFrame(wx.Frame):
+
+ self.fs = fs
+ self.hide_dotfiles = hide_dotfiles
+- self.SetTitle("FS Browser - " + unicode(fs))
++ self.SetTitle("FS Browser - " + str(fs))
+
+ self.tree = wx.gizmos.TreeListCtrl(self, -1, style=wx.TR_DEFAULT_STYLE | wx.TR_HIDE_ROOT)
+
+@@ -105,7 +105,7 @@ class BrowseFrame(wx.Frame):
+ try:
+ paths = ( [(True, p) for p in self.fs.listdir(path, absolute=True, dirs_only=True)] +
+ [(False, p) for p in self.fs.listdir(path, absolute=True, files_only=True)] )
+- except FSError, e:
++ except FSError as e:
+ msg = "Failed to get directory listing for %s\n\nThe following error was reported:\n\n%s" % (path, e)
+ wx.MessageDialog(self, msg, "Error listing directory", wx.OK).ShowModal()
+ paths = []
+@@ -194,6 +194,6 @@ def browse(fs, hide_dotfiles=False):
+
+
+ if __name__ == "__main__":
+- from osfs import OSFS
++ from .osfs import OSFS
+ home_fs = OSFS("~/")
+ browse(home_fs, True)
+--- fs/commands/fscp.py.orig 2022-03-04 17:14:43 UTC
++++ fs/commands/fscp.py
+@@ -3,7 +3,7 @@ from fs.utils import copyfile, copyfile_non_atomic
+ from fs.path import pathjoin, iswildcard
+ from fs.commands.runner import Command
+ import sys
+-import Queue as queue
++import queue as queue
+ import time
+ import threading
+
+@@ -31,7 +31,7 @@ class FileOpThread(threading.Thread):
+ self.dest_fs.makedir(path, recursive=True, allow_recreate=True)
+ else:
+ self.action(fs, path, self.dest_fs, dest_path, overwrite=True)
+- except Exception, e:
++ except Exception as e:
+ self.on_error(e)
+ self.queue.task_done()
+ break
+@@ -147,7 +147,7 @@ Copy SOURCE to DESTINATION"""
+ file_queue,
+ self.on_done,
+ self.on_error)
+- for i in xrange(options.threads)]
++ for i in range(options.threads)]
+
+ for thread in threads:
+ thread.start()
+@@ -188,7 +188,7 @@ Copy SOURCE to DESTINATION"""
+
+ if self.action_errors:
+ for error in self.action_errors:
+- self.error(self.wrap_error(unicode(error)) + '\n')
++ self.error(self.wrap_error(str(error)) + '\n')
+ sys.stdout.flush()
+ else:
+ if complete and options.progress:
+@@ -204,9 +204,9 @@ Copy SOURCE to DESTINATION"""
+ try:
+ if self.options.verbose:
+ if path_type == self.DIR:
+- print "mkdir %s" % dst_fs.desc(dst_path)
++ print("mkdir %s" % dst_fs.desc(dst_path))
+ else:
+- print "%s -> %s" % (src_fs.desc(src_path), dst_fs.desc(dst_path))
++ print("%s -> %s" % (src_fs.desc(src_path), dst_fs.desc(dst_path)))
+ elif self.options.progress:
+ self.done_files += 1
+ sys.stdout.write(self.progress_bar(self.total_files, self.done_files, self.get_verb()))
+--- fs/commands/fsinfo.py.orig 2022-03-04 17:14:43 UTC
++++ fs/commands/fsinfo.py
+@@ -31,12 +31,12 @@ Display information regarding an FS resource"""
+ return val
+
+ def make_printable(text):
+- if not isinstance(text, basestring):
++ if not isinstance(text, str):
+ try:
+ text = str(text)
+ except:
+ try:
+- text = unicode(text)
++ text = str(text)
+ except:
+ text = repr(text)
+ return text
+@@ -48,16 +48,16 @@ Display information regarding an FS resource"""
+ dirs_only=options.dirsonly):
+ if not options.omit:
+ if options.simple:
+- file_line = u'%s\n' % self.wrap_filename(path)
++ file_line = '%s\n' % self.wrap_filename(path)
+ else:
+- file_line = u'[%s] %s\n' % (self.wrap_filename(path), self.wrap_faded(fs.desc(path)))
++ file_line = '[%s] %s\n' % (self.wrap_filename(path), self.wrap_faded(fs.desc(path)))
+ self.output(file_line)
+ info = fs.getinfo(path)
+
+- for k, v in info.items():
++ for k, v in list(info.items()):
+ if k.startswith('_'):
+ del info[k]
+- elif not isinstance(v, (basestring, int, long, float, bool, datetime)):
++ elif not isinstance(v, (str, int, float, bool, datetime)):
+ del info[k]
+
+ if keys:
+--- fs/commands/fsls.py.orig 2022-03-04 17:14:43 UTC
++++ fs/commands/fsls.py
+@@ -37,7 +37,7 @@ List contents of [PATH]"""
+ output = self.output
+
+ if not args:
+- args = [u'.']
++ args = ['.']
+
+ dir_paths = []
+ file_paths = []
+@@ -75,13 +75,13 @@ List contents of [PATH]"""
+
+ if options.syspath:
+ # Path without a syspath, just won't be displayed
+- dir_paths = filter(None, [fs.getsyspath(path, allow_none=True) for path in dir_paths])
+- file_paths = filter(None, [fs.getsyspath(path, allow_none=True) for path in file_paths])
++ dir_paths = [_f for _f in [fs.getsyspath(path, allow_none=True) for path in dir_paths] if _f]
++ file_paths = [_f for _f in [fs.getsyspath(path, allow_none=True) for path in file_paths] if _f]
+
+ if options.url:
+ # Path without a syspath, just won't be displayed
+- dir_paths = filter(None, [fs.getpathurl(path, allow_none=True) for path in dir_paths])
+- file_paths = filter(None, [fs.getpathurl(path, allow_none=True) for path in file_paths])
++ dir_paths = [_f for _f in [fs.getpathurl(path, allow_none=True) for path in dir_paths] if _f]
++ file_paths = [_f for _f in [fs.getpathurl(path, allow_none=True) for path in file_paths] if _f]
+
+ dirs = frozenset(dir_paths)
+ paths = sorted(dir_paths + file_paths, key=lambda p: p.lower())
+@@ -95,7 +95,7 @@ List contents of [PATH]"""
+ def columnize(paths, num_columns):
+
+ col_height = (len(paths) + num_columns - 1) / num_columns
+- columns = [[] for _ in xrange(num_columns)]
++ columns = [[] for _ in range(num_columns)]
+ col_no = 0
+ col_pos = 0
+ for path in paths:
+@@ -128,11 +128,11 @@ List contents of [PATH]"""
+
+ def condense_columns(columns):
+ max_column_height = max([len(col) for col in columns])
+- lines = [[] for _ in xrange(max_column_height)]
++ lines = [[] for _ in range(max_column_height)]
+ for column in columns:
+ for line, path in zip(lines, column):
+ line.append(path)
+- return '\n'.join(u' '.join(line) for line in lines)
++ return '\n'.join(' '.join(line) for line in lines)
+
+ if options.long:
+ for path in paths:
+@@ -151,7 +151,7 @@ List contents of [PATH]"""
+ while num_cols:
+ col_height = (num_paths + num_cols - 1) // num_cols
+ line_width = 0
+- for col_no in xrange(num_cols):
++ for col_no in range(num_cols):
+ try:
+ col_width = max(path_widths[col_no * col_height: (col_no + 1) * col_height])
+ except ValueError:
+--- fs/commands/fsserve.py.orig 2015-04-12 17:24:29 UTC
++++ fs/commands/fsserve.py
+@@ -82,7 +82,7 @@ Serves the contents of PATH with one of a number of me
+ try:
+ self.output("Starting sftp server on %s:%i\n" % (options.addr, port), verbose=True)
+ server.serve_forever()
+- except Exception, e:
++ except Exception as e:
+ pass
+ finally:
+ server.server_close()
+@@ -90,7 +90,7 @@ Serves the contents of PATH with one of a number of me
+ else:
+ self.error("Server type '%s' not recognised\n" % options.type)
+
+- except IOError, e:
++ except IOError as e:
+ if e.errno == errno.EACCES:
+ self.error('Permission denied\n')
+ return 1
+--- fs/commands/fstree.py.orig 2022-03-04 17:14:43 UTC
++++ fs/commands/fstree.py
+@@ -34,7 +34,7 @@ Recursively display the contents of PATH in an ascii t
+
+ for fs, path, is_dir in self.get_resources(args, single=True):
+ if not is_dir:
+- self.error(u"'%s' is not a dir\n" % path)
++ self.error("'%s' is not a dir\n" % path)
+ return 1
+ fs.cache_hint(True)
+ if options.gui:
+--- fs/commands/runner.py.orig 2022-03-04 17:14:43 UTC
++++ fs/commands/runner.py
+@@ -68,7 +68,7 @@ else:
+
+
+ def _unicode(text):
+- if not isinstance(text, unicode):
++ if not isinstance(text, str):
+ return text.decode('ascii', 'replace')
+ return text
+
+@@ -128,17 +128,17 @@ class Command(object):
+ text = _unicode(text)
+ if not self.terminal_colors:
+ return text
+- return u'\x1b[2m%s\x1b[0m' % text
++ return '\x1b[2m%s\x1b[0m' % text
+
+ def wrap_link(self, text):
+ if not self.terminal_colors:
+ return text
+- return u'\x1b[1;33m%s\x1b[0m' % text
++ return '\x1b[1;33m%s\x1b[0m' % text
+
+ def wrap_strong(self, text):
+ if not self.terminal_colors:
+ return text
+- return u'\x1b[1m%s\x1b[0m' % text
++ return '\x1b[1m%s\x1b[0m' % text
+
+ def wrap_table_header(self, name):
+ if not self.terminal_colors:
+@@ -215,10 +215,10 @@ class Command(object):
+ return resources
+
+ def ask(self, msg):
+- return raw_input('%s: %s ' % (self.name, msg))
++ return input('%s: %s ' % (self.name, msg))
+
+ def text_encode(self, text):
+- if not isinstance(text, unicode):
++ if not isinstance(text, str):
+ text = text.decode('ascii', 'replace')
+ text = text.encode(self.encoding, 'replace')
+ return text
+@@ -226,7 +226,7 @@ class Command(object):
+ def output(self, msgs, verbose=False):
+ if verbose and not self.options.verbose:
+ return
+- if isinstance(msgs, basestring):
++ if isinstance(msgs, str):
+ msgs = (msgs,)
+ for msg in msgs:
+ self.output_file.write(self.text_encode(msg))
+@@ -276,7 +276,7 @@ class Command(object):
+
+ opener_table = []
+
+- for fs_opener in opener.openers.itervalues():
++ for fs_opener in opener.openers.values():
+ names = fs_opener.names
+ desc = getattr(fs_opener, 'desc', '')
+ opener_table.append((names, desc))
+@@ -346,12 +346,12 @@ class Command(object):
+ opener.add(new_opener)
+
+ if not six.PY3:
+- args = [unicode(arg, sys.getfilesystemencoding()) for arg in args]
++ args = [str(arg, sys.getfilesystemencoding()) for arg in args]
+ self.verbose = options.verbose
+ try:
+ return self.do_run(options, args) or 0
+- except FSError, e:
+- self.error(self.wrap_error(unicode(e)) + '\n')
++ except FSError as e:
++ self.error(self.wrap_error(str(e)) + '\n')
+ if options.debug:
+ raise
+ return 1
+@@ -361,8 +361,8 @@ class Command(object):
+ return 0
+ except SystemExit:
+ return 0
+- except Exception, e:
+- self.error(self.wrap_error('Error - %s\n' % unicode(e)))
++ except Exception as e:
++ self.error(self.wrap_error('Error - %s\n' % str(e)))
+ if options.debug:
+ raise
+ return 1
+--- fs/contrib/archivefs.py.orig 2022-03-04 17:14:43 UTC
++++ fs/contrib/archivefs.py
+@@ -62,7 +62,7 @@ class ArchiveFS(FS):
+ :param thread_synchronize: set to True (default) to enable thread-safety
+ """
+ super(ArchiveFS, self).__init__(thread_synchronize=thread_synchronize)
+- if isinstance(f, basestring):
++ if isinstance(f, str):
+ self.fileobj = None
+ self.root_path = f
+ else:
+@@ -83,7 +83,7 @@ class ArchiveFS(FS):
+ return "<ArchiveFS: %s>" % self.root_path
+
+ def __unicode__(self):
+- return u"<ArchiveFS: %s>" % self.root_path
++ return "<ArchiveFS: %s>" % self.root_path
+
+ def getmeta(self, meta_name, default=NoDefaultMeta):
+ if meta_name == 'read_only':
+@@ -446,7 +446,7 @@ class ArchiveMountFS(mountfs.MountFS):
+ else:
+ listing = self.listdir(path, *args, **kwargs)
+ if dirs_only:
+- listing = filter(isdir, listing)
++ listing = list(filter(isdir, listing))
+ return listing
+
+ if wildcard is None:
+--- fs/contrib/bigfs/__init__.py.orig 2022-03-04 17:14:43 UTC
++++ fs/contrib/bigfs/__init__.py
+@@ -149,7 +149,7 @@ class _ExceptionProxy(object):
+ def __setattr__(self, name, value):
+ raise ValueError("File has been closed")
+
+- def __nonzero__(self):
++ def __bool__(self):
+ return False
+
+
+@@ -193,7 +193,7 @@ class BigFS(FS):
+ return "<BigFS: %s>" % self.big_path
+
+ def __unicode__(self):
+- return unicode(self.__str__())
++ return str(self.__str__())
+
+
+ def _parse_resource_list(self, g):
+--- fs/contrib/bigfs/subrangefile.py.orig 2022-03-04 17:14:43 UTC
++++ fs/contrib/bigfs/subrangefile.py
+@@ -33,7 +33,7 @@ class SubrangeFile:
+ return "<SubrangeFile: %s@%d size=%d>" % (self.name, self.startOffset, self.fileSize)
+
+ def __unicode__(self):
+- return unicode(self.__str__())
++ return str(self.__str__())
+
+ def size(self):
+ return self.fileSize
+--- fs/contrib/davfs/__init__.py.orig 2015-04-12 17:24:29 UTC
++++ fs/contrib/davfs/__init__.py
+@@ -16,21 +16,21 @@ Requires the dexml module:
+ # Copyright (c) 2009-2010, Cloud Matrix Pty. Ltd.
+ # All rights reserved; available under the terms of the MIT License.
+
+-from __future__ import with_statement
+
++
+ import os
+ import sys
+-import httplib
++import http.client
+ import socket
+-from urlparse import urlparse
++from urllib.parse import urlparse
+ import stat as statinfo
+-from urllib import quote as urlquote
+-from urllib import unquote as urlunquote
++from urllib.parse import quote as urlquote
++from urllib.parse import unquote as urlunquote
+ import base64
+ import re
+ import time
+ import datetime
+-import cookielib
++import http.cookiejar
+ import fnmatch
+ import xml.dom.pulldom
+ import threading
+@@ -78,8 +78,8 @@ class DAVFS(FS):
+ """
+
+ connection_classes = {
+- "http": httplib.HTTPConnection,
+- "https": httplib.HTTPSConnection,
++ "http": http.client.HTTPConnection,
++ "https": http.client.HTTPSConnection,
+ }
+
+ _DEFAULT_PORT_NUMBERS = {
+@@ -116,7 +116,7 @@ class DAVFS(FS):
+ self._connections = []
+ self._free_connections = {}
+ self._connection_lock = threading.Lock()
+- self._cookiejar = cookielib.CookieJar()
++ self._cookiejar = http.cookiejar.CookieJar()
+ super(DAVFS,self).__init__(thread_synchronize=thread_synchronize)
+ # Check that the server speaks WebDAV, and normalize the URL
+ # after any redirects have been followed.
+@@ -221,14 +221,14 @@ class DAVFS(FS):
+ self._free_connections = {}
+ self._connection_lock = threading.Lock()
+ self._url_p = urlparse(self.url)
+- self._cookiejar = cookielib.CookieJar()
++ self._cookiejar = http.cookiejar.CookieJar()
+
+ def getpathurl(self, path, allow_none=False):
+ """Convert a client-side path into a server-side URL."""
+ path = relpath(normpath(path))
+ if path.endswith("/"):
+ path = path[:-1]
+- if isinstance(path,unicode):
++ if isinstance(path,str):
+ path = path.encode("utf8")
+ return self.url + urlquote(path)
+
+@@ -291,7 +291,7 @@ class DAVFS(FS):
+ """Perform a single HTTP request, without any error handling."""
+ if self.closed:
+ raise RemoteConnectionError("",msg="FS is closed")
+- if isinstance(url,basestring):
++ if isinstance(url,str):
+ url = urlparse(url)
+ if self.credentials is not None:
+ username = self.credentials.get("username","")
+@@ -310,7 +310,7 @@ class DAVFS(FS):
+ if hasattr(body,"md5"):
+ md5 = body.md5.decode("hex").encode("base64")
+ con.putheader("Content-MD5",md5)
+- for hdr,val in headers.iteritems():
++ for hdr,val in headers.items():
+ con.putheader(hdr,val)
+ self._cookiejar.add_cookie_header(FakeReq(con,url.scheme,url.path))
+ con.endheaders()
+@@ -332,7 +332,7 @@ class DAVFS(FS):
+ self._give_connection(url,con)
+ resp.close = new_close
+ return resp
+- except socket.error, e:
++ except socket.error as e:
+ if not fresh:
+ return self._raw_request(url,method,body,headers,num_tries)
+ if e.args[0] in _RETRYABLE_ERRORS:
+@@ -479,7 +479,7 @@ class DAVFS(FS):
+ if not entry_ok:
+ continue
+ if wildcard is not None:
+- if isinstance(wildcard,basestring):
++ if isinstance(wildcard,str):
+ if not fnmatch.fnmatch(nm,wildcard):
+ continue
+ else:
+@@ -530,7 +530,7 @@ class DAVFS(FS):
+ if not entry_ok:
+ continue
+ if wildcard is not None:
+- if isinstance(wildcard,basestring):
++ if isinstance(wildcard,str):
+ if not fnmatch.fnmatch(nm,wildcard):
+ continue
+ else:
+@@ -610,7 +610,7 @@ class DAVFS(FS):
+ if self._isurl(path,res.href):
+ info.update(self._info_from_propfind(res))
+ if "st_mode" not in info:
+- info["st_mode"] = 0700 | statinfo.S_IFREG
++ info["st_mode"] = 0o700 | statinfo.S_IFREG
+ return info
+ finally:
+ response.close()
+@@ -647,7 +647,7 @@ class DAVFS(FS):
+ # TODO: should check for status of the propfind first...
+ # check for directory indicator
+ if findElements("DAV:","collection"):
+- info["st_mode"] = 0700 | statinfo.S_IFDIR
++ info["st_mode"] = 0o700 | statinfo.S_IFDIR
+ # check for content length
+ cl = findElements("DAV:","getcontentlength")
+ if cl:
+@@ -674,7 +674,7 @@ class DAVFS(FS):
+ if etag:
+ info["etag"] = etag
+ if "st_mode" not in info:
+- info["st_mode"] = 0700 | statinfo.S_IFREG
++ info["st_mode"] = 0o700 | statinfo.S_IFREG
+ return info
+
+
+--- fs/contrib/davfs/util.py.orig 2022-03-04 17:14:43 UTC
++++ fs/contrib/davfs/util.py
+@@ -8,7 +8,7 @@
+
+ import os
+ import re
+-import cookielib
++import http.cookiejar
+
+
+ def get_fileno(file):
+@@ -130,7 +130,7 @@ class FakeResp:
+ # is a tweaked version of the cookielib function of the same name.
+ #
+ _test_cookie = "sessionid=e9c9b002befa93bd865ce155270307ef; Domain=.cloud.me; expires=Wed, 10-Feb-2010 03:27:20 GMT; httponly; Max-Age=1209600; Path=/, sessionid_https=None; Domain=.cloud.me; expires=Wed, 10-Feb-2010 03:27:20 GMT; httponly; Max-Age=1209600; Path=/; secure"
+-if len(cookielib.parse_ns_headers([_test_cookie])) != 2:
++if len(http.cookiejar.parse_ns_headers([_test_cookie])) != 2:
+ def parse_ns_headers(ns_headers):
+ """Improved parser for netscape-style cookies.
+
+@@ -170,13 +170,13 @@ if len(cookielib.parse_ns_headers([_test_cookie])) !=
+ # convert expires date to seconds since epoch
+ if v.startswith('"'): v = v[1:]
+ if v.endswith('"'): v = v[:-1]
+- v = cookielib.http2time(v) # None if invalid
++ v = http.cookiejar.http2time(v) # None if invalid
+ pairs.append((k, v))
+ if pairs:
+ if not version_set:
+ pairs.append(("version", "0"))
+ result.append(pairs)
+ return result
+- cookielib.parse_ns_headers = parse_ns_headers
+- assert len(cookielib.parse_ns_headers([_test_cookie])) == 2
++ http.cookiejar.parse_ns_headers = parse_ns_headers
++ assert len(http.cookiejar.parse_ns_headers([_test_cookie])) == 2
+
+--- fs/contrib/davfs/xmlobj.py.orig 2022-03-04 17:14:43 UTC
++++ fs/contrib/davfs/xmlobj.py
+@@ -9,9 +9,9 @@ of dexml.Model subclasses.
+
+ """
+
+-from urlparse import urlparse, urlunparse
++from urllib.parse import urlparse, urlunparse
+
+-from httplib import responses as STATUS_CODE_TEXT
++from http.client import responses as STATUS_CODE_TEXT
+ STATUS_CODE_TEXT[207] = "Multi-Status"
+
+ import dexml
+@@ -86,7 +86,7 @@ class StatusField(fields.Value):
+ return val
+
+ def __set__(self,instance,value):
+- if isinstance(value,basestring):
++ if isinstance(value,str):
+ # sanity check it
+ bits = value.split(" ")
+ if len(bits) < 3 or bits[0] != "HTTP/1.1":
+--- fs/contrib/sqlitefs.py.orig 2015-04-12 17:24:29 UTC
++++ fs/contrib/sqlitefs.py
+@@ -24,7 +24,7 @@ def fetchone(cursor):
+ '''
+ row = None
+ try:
+- row = cursor.next()
++ row = next(cursor)
+ except:
+ pass
+ return(row)
+@@ -62,7 +62,7 @@ class SqliteFsFileBase(object):
+ __repr__ = __str__
+
+ def __unicode__(self):
+- return u"<SqliteFS File in %s %s>" % (self.fs, self.path)
++ return "<SqliteFS File in %s %s>" % (self.fs, self.path)
+
+ def __del__(self):
+ if not self.closed:
+@@ -74,7 +74,7 @@ class SqliteFsFileBase(object):
+ def __iter__(self):
+ raise OperationFailedError('__iter__', self.path)
+
+- def next(self):
++ def __next__(self):
+ raise OperationFailedError('next', self.path)
+
+ def readline(self, *args, **kwargs):
+@@ -139,8 +139,8 @@ class SqliteReadableFile(SqliteFsFileBase):
+ def __iter__(self):
+ return iter(self.real_stream)
+
+- def next(self):
+- return self.real_stream.next()
++ def __next__(self):
++ return next(self.real_stream)
+
+ def readline(self, *args, **kwargs):
+ return self.real_stream.readline(*args, **kwargs)
+@@ -438,7 +438,7 @@ class SqliteFS(FS):
+ get the directory information dictionary.
+ '''
+ info = dict()
+- info['st_mode'] = 0755
++ info['st_mode'] = 0o755
+ return info
+
+ def _get_file_info(self, path):
+@@ -460,7 +460,7 @@ class SqliteFS(FS):
+ info['created'] = row[2]
+ info['last_modified'] = row[3]
+ info['last_accessed'] = row[4]
+- info['st_mode'] = 0666
++ info['st_mode'] = 0o666
+ return(info)
+
+ def _isfile(self,path):
+@@ -551,7 +551,7 @@ class SqliteFS(FS):
+ pass
+
+ if( absolute == False):
+- pathlist = map(lambda dpath:frombase(path,dpath), pathlist)
++ pathlist = [frombase(path,dpath) for dpath in pathlist]
+
+ return(pathlist)
+
+--- fs/contrib/tahoelafs/__init__.py.orig 2022-03-04 17:14:43 UTC
++++ fs/contrib/tahoelafs/__init__.py
+@@ -70,8 +70,8 @@ from fs import _thread_synchronize_default, SEEK_END
+ from fs.remote import CacheFSMixin, RemoteFileBuffer
+ from fs.base import fnmatch, NoDefaultMeta
+
+-from util import TahoeUtil
+-from connection import Connection
++from .util import TahoeUtil
++from .connection import Connection
+
+ from six import b
+
+@@ -240,7 +240,7 @@ class _TahoeLAFS(FS):
+ continue
+
+ if wildcard is not None:
+- if isinstance(wildcard,basestring):
++ if isinstance(wildcard,str):
+ if not fnmatch.fnmatch(item['name'], wildcard):
+ continue
+ else:
+@@ -269,7 +269,7 @@ class _TahoeLAFS(FS):
+
+ try:
+ self.tahoeutil.unlink(self.dircap, path)
+- except Exception, e:
++ except Exception as e:
+ raise errors.ResourceInvalidError(path)
+
+ @_fix_path
+@@ -341,8 +341,8 @@ class _TahoeLAFS(FS):
+
+ def _log(self, level, message):
+ if not logger.isEnabledFor(level): return
+- logger.log(level, u'(%d) %s' % (id(self),
+- unicode(message).encode('ASCII', 'replace')))
++ logger.log(level, '(%d) %s' % (id(self),
++ str(message).encode('ASCII', 'replace')))
+
+ @_fix_path
+ def getpathurl(self, path, allow_none=False, webapi=None):
+@@ -353,11 +353,11 @@ class _TahoeLAFS(FS):
+ webapi = self.connection.webapi
+ self._log(DEBUG, "Retrieving URL for %s over %s" % (path, webapi))
+ path = self.tahoeutil.fixwinpath(path, False)
+- return u"%s/uri/%s%s" % (webapi, self.dircap, path)
++ return "%s/uri/%s%s" % (webapi, self.dircap, path)
+
+ @_fix_path
+ def getrange(self, path, offset, length=None):
+- return self.connection.get(u'/uri/%s%s' % (self.dircap, path),
++ return self.connection.get('/uri/%s%s' % (self.dircap, path),
+ offset=offset, length=length)
+
+ @_fix_path
+@@ -379,10 +379,10 @@ class _TahoeLAFS(FS):
+ file.seek(0)
+
+ if size > self.largefilesize:
+- self.connection.put(u'/uri/%s%s' % (self.dircap, path),
++ self.connection.put('/uri/%s%s' % (self.dircap, path),
+ "PyFilesystem.TahoeLAFS: Upload started, final size %d" % size)
+
+- self.connection.put(u'/uri/%s%s' % (self.dircap, path), file, size=size)
++ self.connection.put('/uri/%s%s' % (self.dircap, path), file, size=size)
+
+ @_fix_path
+ def getinfo(self, path):
+--- fs/contrib/tahoelafs/connection.py.orig 2015-04-12 17:24:29 UTC
++++ fs/contrib/tahoelafs/connection.py
+@@ -10,17 +10,19 @@ if python3:
+ from urllib.parse import urlencode, pathname2url, quote
+ from urllib.request import Request, urlopen
+ else:
+- from urllib import urlencode, pathname2url
+- from urllib2 import Request, urlopen, quote
++ from urllib.parse import urlencode
++ from urllib.request import pathname2url
++ from urllib.request import Request, urlopen
++ from urllib.parse import quote
+
+ class PutRequest(Request):
+ def __init__(self, *args, **kwargs):
+- self.get_method = lambda: u'PUT'
++ self.get_method = lambda: 'PUT'
+ Request.__init__(self, *args, **kwargs)
+
+ class DeleteRequest(Request):
+ def __init__(self, *args, **kwargs):
+- self.get_method = lambda: u'DELETE'
++ self.get_method = lambda: 'DELETE'
+ Request.__init__(self, *args, **kwargs)
+
+ class Connection:
+@@ -32,7 +34,7 @@ class Connection:
+ '''
+ Retrieve length of string or file object and prepare HTTP headers.
+ '''
+- if isinstance(f, basestring):
++ if isinstance(f, str):
+ # Just set up content length
+ size = len(f)
+ elif getattr(f, 'read', None):
+@@ -50,20 +52,20 @@ class Connection:
+
+ def _urlencode(self, data):
+ _data = {}
+- for k, v in data.items():
++ for k, v in list(data.items()):
+ _data[k.encode('utf-8')] = v.encode('utf-8')
+ return urlencode(_data)
+
+ def _quotepath(self, path, params={}):
+ q = quote(path.encode('utf-8'), safe='/')
+ if params:
+- return u"%s?%s" % (q, self._urlencode(params))
++ return "%s?%s" % (q, self._urlencode(params))
+ return q
+
+ def _urlopen(self, req):
+ try:
+ return urlopen(req)
+- except Exception, e:
++ except Exception as e:
+ if not getattr(e, 'getcode', None):
+ raise errors.RemoteConnectionError(str(e))
+ code = e.getcode()
+@@ -85,7 +87,7 @@ class Connection:
+ data = self._urlencode(data)
+ path = self._quotepath(path)
+ if data:
+- path = u'?'.join([path, data])
++ path = '?'.join([path, data])
+
+ headers = {}
+ headers.update(self.headers)
+--- fs/contrib/tahoelafs/test_tahoelafs.py.orig 2022-03-04 17:14:43 UTC
++++ fs/contrib/tahoelafs/test_tahoelafs.py
+@@ -35,7 +35,7 @@ class TestTahoeLAFS(unittest.TestCase,FSTestCases):#,T
+
+ def test_dircap(self):
+ # Is dircap in correct format?
+- self.assert_(self.dircap.startswith('URI:DIR2:') and len(self.dircap) > 50)
++ self.assertTrue(self.dircap.startswith('URI:DIR2:') and len(self.dircap) > 50)
+
+ def test_concurrent_copydir(self):
+ # makedir() on TahoeLAFS is currently not atomic
+--- fs/contrib/tahoelafs/util.py.orig 2022-03-04 17:14:43 UTC
++++ fs/contrib/tahoelafs/util.py
+@@ -19,7 +19,7 @@ except ImportError:
+ try:
+ import json
+ except ImportError:
+- print "simplejson (http://pypi.python.org/pypi/simplejson/) required"
++ print("simplejson (http://pypi.python.org/pypi/simplejson/) required")
+ raise
+
+ from .connection import Connection
+@@ -29,22 +29,22 @@ python3 = int(platform.python_version_tuple()[0]) > 2
+ if python3:
+ from urllib.error import HTTPError
+ else:
+- from urllib2 import HTTPError
++ from urllib.error import HTTPError
+
+ class TahoeUtil:
+ def __init__(self, webapi):
+ self.connection = Connection(webapi)
+
+ def createdircap(self):
+- return self.connection.post(u'/uri', params={u't': u'mkdir'}).read()
++ return self.connection.post('/uri', params={'t': 'mkdir'}).read()
+
+ def unlink(self, dircap, path=None):
+ path = self.fixwinpath(path, False)
+- self.connection.delete(u'/uri/%s%s' % (dircap, path))
++ self.connection.delete('/uri/%s%s' % (dircap, path))
+
+ def info(self, dircap, path):
+ path = self.fixwinpath(path, False)
+- meta = json.load(self.connection.get(u'/uri/%s%s' % (dircap, path), {u't': u'json'}))
++ meta = json.load(self.connection.get('/uri/%s%s' % (dircap, path), {'t': 'json'}))
+ return self._info(path, meta)
+
+ def fixwinpath(self, path, direction=True):
+@@ -74,7 +74,7 @@ class TahoeUtil:
+ if type == 'unknown':
+ raise errors.ResourceNotFoundError(path)
+
+- info = {'name': unicode(self.fixwinpath(path, True)),
++ info = {'name': str(self.fixwinpath(path, True)),
+ 'type': type,
+ 'size': data.get('size', 0),
+ 'ctime': None,
+@@ -83,22 +83,22 @@ class TahoeUtil:
+ info['ctime'] = data['metadata'].get('ctime')
+
+ if info['type'] == 'dirnode':
+- info['st_mode'] = 0777 | statinfo.S_IFDIR
++ info['st_mode'] = 0o777 | statinfo.S_IFDIR
+ else:
+- info['st_mode'] = 0644
*** 4934 LINES SKIPPED ***