Hello community,

here is the log from the commit of package python-asyncssh for openSUSE:Factory 
checked in at 2019-04-02 09:22:46
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-asyncssh (Old)
 and      /work/SRC/openSUSE:Factory/.python-asyncssh.new.25356 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-asyncssh"

Tue Apr  2 09:22:46 2019 rev:5 rq:690377 version:1.16.1

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-asyncssh/python-asyncssh.changes  
2019-03-22 15:00:58.473803190 +0100
+++ 
/work/SRC/openSUSE:Factory/.python-asyncssh.new.25356/python-asyncssh.changes   
    2019-04-02 09:22:51.184731969 +0200
@@ -1,0 +2,27 @@
+Mon Apr  1 13:23:08 UTC 2019 - Ondřej Súkup <[email protected]>
+
+- update to 1.16.1
+- drop 194.patch
+* Added channel, connection, and env properties to SFTPServer instances,
+  so connection and channel information can be used to influence the
+  SFTP server's behavior. Previously, connection information was made
+  avaiable through the constructor, but channel and environment
+  information was not. Now, all of these are available as properties
+  on the SFTPServer instance without the need to explicitly store anything
+  in a custom constructor.
+* Optimized SFTP glob matching when the glob pattern contains directory
+  names without glob characters in them. Thanks go to Mikhail Terekhov
+  for contributing this improvement!
+* Added support for PurePath in a few places that were missed when this
+  support was originally added. Once again, thanks go to Mikhail Terehkov
+  for these fixes.
+* Fixed bug in SFTP parallel I/O file reader where it sometimes returned
+  EOF prematurely. Thanks go to David G for reporting this problem and
+  providing a reproducible test case.
+* Fixed test failures seen on Fedora Rawhide. Thanks go to Georg Sauthof
+  for reporting this issue and providing a test environment to help debug
+  it.
+* Updated Ed25519/448 and Curve25519/448 tests to only run when these
+  algorithms are available.
+
+-------------------------------------------------------------------
@@ -6 +32,0 @@
-

Old:
----
  194.patch
  asyncssh-1.16.0.tar.gz

New:
----
  asyncssh-1.16.1.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python-asyncssh.spec ++++++
--- /var/tmp/diff_new_pack.ttwLl2/_old  2019-04-02 09:22:51.704732318 +0200
+++ /var/tmp/diff_new_pack.ttwLl2/_new  2019-04-02 09:22:51.704732318 +0200
@@ -19,14 +19,13 @@
 %{?!python_module:%define python_module() python-%{**} python3-%{**}}
 %define skip_python2 1
 Name:           python-asyncssh
-Version:        1.16.0
+Version:        1.16.1
 Release:        0
 Summary:        Asynchronous SSHv2 client and server library
 License:        EPL-2.0 OR GPL-2.0-or-later
 Group:          Development/Languages/Python
 Url:            http://asyncssh.timeheart.net
 Source:         
https://files.pythonhosted.org/packages/source/a/asyncssh/asyncssh-%{version}.tar.gz
-Patch0:         194.patch
 BuildRequires:  %{python_module bcrypt >= 3.1.3}
 BuildRequires:  %{python_module cryptography >= 2.6.1}
 BuildRequires:  %{python_module gssapi >= 1.2.0}
@@ -53,7 +52,6 @@
 
 %prep
 %setup -q -n asyncssh-%{version}
-%autopatch -p1
 
 %build
 %python_build

++++++ asyncssh-1.16.0.tar.gz -> asyncssh-1.16.1.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/asyncssh-1.16.0/PKG-INFO new/asyncssh-1.16.1/PKG-INFO
--- old/asyncssh-1.16.0/PKG-INFO        2019-03-03 08:34:30.000000000 +0100
+++ new/asyncssh-1.16.1/PKG-INFO        2019-03-31 03:59:06.000000000 +0200
@@ -1,6 +1,6 @@
 Metadata-Version: 2.1
 Name: asyncssh
-Version: 1.16.0
+Version: 1.16.1
 Summary: AsyncSSH: Asynchronous SSHv2 client and server library
 Home-page: http://asyncssh.timeheart.net
 Author: Ron Frederick
@@ -217,8 +217,8 @@
 Classifier: Topic :: Security :: Cryptography
 Classifier: Topic :: Software Development :: Libraries :: Python Modules
 Classifier: Topic :: System :: Networking
-Provides-Extra: libnacl
-Provides-Extra: pyOpenSSL
 Provides-Extra: gssapi
-Provides-Extra: bcrypt
+Provides-Extra: pyOpenSSL
 Provides-Extra: pypiwin32
+Provides-Extra: libnacl
+Provides-Extra: bcrypt
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/asyncssh-1.16.0/asyncssh/connection.py 
new/asyncssh-1.16.1/asyncssh/connection.py
--- old/asyncssh-1.16.0/asyncssh/connection.py  2019-03-03 06:11:20.000000000 
+0100
+++ new/asyncssh-1.16.1/asyncssh/connection.py  2019-03-30 22:01:08.000000000 
+0100
@@ -3670,7 +3670,8 @@
             raise
 
     @async_context_manager
-    def start_sftp_client(self, path_encoding='utf-8', path_errors='strict'):
+    def start_sftp_client(self, env=None, path_encoding='utf-8',
+                          path_errors='strict'):
         """Start an SFTP client
 
            This method is a coroutine which attempts to start a secure
@@ -3684,6 +3685,17 @@
            will be left as bytes rather than being converted to & from
            strings.
 
+           :param env: (optional)
+               The set of environment variables to set for this SFTP
+               session. Keys and values passed in here will be converted
+               to Unicode strings encoded as UTF-8 (ISO 10646) for
+               transmission.
+
+               .. note:: Many SSH servers restrict which environment
+                         variables a client is allowed to set. The
+                         server's configuration may need to be edited
+                         before environment variables can be
+                         successfully set in the remote environment.
            :param path_encoding:
                The Unicode encoding to apply when sending and receiving
                remote pathnames
@@ -3699,6 +3711,7 @@
         """
 
         writer, reader, _ = yield from self.open_session(subsystem='sftp',
+                                                         env=env or {},
                                                          encoding=None)
 
         return (yield from start_sftp_client(self, self._loop, reader, writer,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/asyncssh-1.16.0/asyncssh/scp.py 
new/asyncssh-1.16.1/asyncssh/scp.py
--- old/asyncssh-1.16.0/asyncssh/scp.py 2018-11-29 06:11:31.000000000 +0100
+++ new/asyncssh-1.16.1/asyncssh/scp.py 2019-03-30 22:01:08.000000000 +0100
@@ -25,6 +25,7 @@
 import argparse
 import asyncio
 import posixpath
+from pathlib import PurePath
 import shlex
 import stat
 
@@ -69,7 +70,7 @@
         conn, path = path.split(':')
     elif isinstance(path, bytes) and b':' in path:
         conn, path = path.split(b':')
-    elif isinstance(path, (str, bytes)):
+    elif isinstance(path, (str, bytes, PurePath)):
         conn = None
     else:
         conn = path
@@ -91,6 +92,9 @@
 def _start_remote(conn, source, must_be_dir, preserve, recurse, path):
     """Start remote SCP server"""
 
+    if isinstance(path, PurePath):
+        path = str(path)
+
     if isinstance(path, str):
         path = path.encode('utf-8')
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/asyncssh-1.16.0/asyncssh/sftp.py 
new/asyncssh-1.16.1/asyncssh/sftp.py
--- old/asyncssh-1.16.0/asyncssh/sftp.py        2019-03-03 06:11:20.000000000 
+0100
+++ new/asyncssh-1.16.1/asyncssh/sftp.py        2019-03-30 22:01:08.000000000 
+0100
@@ -147,44 +147,76 @@
         os.utime(path, times=(attrs.atime, attrs.mtime))
 
 
+def _split_path_by_globs(pattern):
+    """Split path grouping parts without glob pattern"""
+
+    basedir, patlist, plain = None, [], []
+
+    for current in pattern.split(b'/'):
+        if any(c in current for c in b'*?[]'):
+            if plain:
+                if patlist:
+                    patlist.append(plain)
+                else:
+                    basedir = b'/'.join(plain) or b'/'
+
+                plain = []
+
+            patlist.append(current)
+        else:
+            plain.append(current)
+
+    if plain:
+        patlist.append(plain)
+
+    return basedir, patlist
+
+
 @asyncio.coroutine
 def _glob(fs, basedir, patlist, result):
     """Recursively match a glob pattern"""
 
     pattern, newpatlist = patlist[0], patlist[1:]
 
-    if not pattern and not newpatlist:
-        result.append(basedir)
-        return
+    names = yield from fs.listdir(basedir or b'.')
 
-    if pattern == b'**':
-        yield from _glob(fs, basedir, newpatlist, result)
+    if isinstance(pattern, list):
+        if len(pattern) == 1 and not pattern[0] and not newpatlist:
+            result.append(basedir)
+            return
 
-    names = yield from fs.listdir(basedir or b'.')
+        for name in names:
+            if name == pattern[0]:
+                newbase = posixpath.join(basedir or b'', *pattern)
+                yield from fs.stat(newbase)
 
-    for name in names:
-        if pattern != name and name in (b'.', b'..'):
-            continue
-
-        if name[:1] == b'.' and not pattern[:1] == b'.':
-            continue
-
-        if fnmatch(name, pattern):
-            if basedir:
-                newbase = posixpath.join(basedir, name)
-            else:
-                newbase = name
+                if not newpatlist:
+                    result.append(newbase)
+                else:
+                    yield from _glob(fs, newbase, newpatlist, result)
+                break
+    else:
+        if pattern == b'**':
+            yield from _glob(fs, basedir, newpatlist, result)
 
-            if not newpatlist:
-                result.append(newbase)
-            else:
-                attrs = yield from fs.stat(newbase)
+        for name in names:
+            if name in (b'.', b'..'):
+                continue
+
+            if fnmatch(name, pattern):
+                newbase = posixpath.join(basedir or b'', name)
 
-                if stat.S_ISDIR(attrs.permissions):
-                    if pattern == b'**':
-                        yield from _glob(fs, newbase, patlist, result)
-                    else:
-                        yield from _glob(fs, newbase, newpatlist, result)
+                if not newpatlist or (len(newpatlist) == 1 and
+                                      not newpatlist[0]):
+                    result.append(newbase)
+                else:
+                    attrs = yield from fs.stat(newbase)
+
+                    if stat.S_ISDIR(attrs.permissions):
+                        if pattern == b'**':
+                            yield from _glob(fs, newbase, patlist, result)
+                        else:
+                            yield from _glob(fs, newbase, newpatlist, result)
 
 
 @asyncio.coroutine
@@ -195,14 +227,7 @@
 
     try:
         if any(c in pattern for c in b'*?[]'):
-            patlist = pattern.split(b'/')
-
-            if not patlist[0]:
-                basedir = b'/'
-                patlist = patlist[1:]
-            else:
-                basedir = None
-
+            basedir, patlist = _split_path_by_globs(pattern)
             yield from _glob(fs, basedir, patlist, names)
 
             if not names:
@@ -427,7 +452,7 @@
                 for task in done:
                     exc = task.exception()
 
-                    if exc:
+                    if exc and exc.code != FX_EOF:
                         exceptions.append(exc)
 
                 if exceptions:
@@ -2037,7 +2062,7 @@
         if dstpath:
             dstpath = dstfs.encode(dstpath)
 
-        if isinstance(srcpaths, (str, bytes)):
+        if isinstance(srcpaths, (str, bytes, PurePath)):
             srcpaths = [srcpaths]
         elif not dst_isdir:
             raise SFTPError(FX_FAILURE, '%s must be a directory' %
@@ -4004,24 +4029,67 @@
     def __init__(self, conn, chroot=None):
         # pylint: disable=unused-argument
 
-        self._logger = None
-
         if chroot:
             self._chroot = _from_local_path(os.path.realpath(chroot))
         else:
             self._chroot = None
 
+    @classmethod
+    def new(cls, chan):
+        """Allocate a new SFTP server"""
+
+        # Make channel, connection, and env available as properties on
+        # this SFTP server even before __init__ is called, but continue
+        # to pass "conn" as an explicit argument for backward compatibility
+        # with older code which is expecting that.
+
+        sftp_server = cls.__new__(cls)
+        sftp_server.channel = chan
+
+        sftp_server.__init__(chan.get_connection())
+
+        return sftp_server
+
     @property
-    def logger(self):
-        """A logger associated with this SFTP server"""
+    def channel(self):
+        """The channel associated with this SFTP server session"""
 
-        return self._logger
+        return self._chan
+
+    @channel.setter
+    def channel(self, chan):
+        """Set the channel associated with this SFTP server session"""
 
-    @logger.setter
-    def logger(self, logger):
-        """Set the logger associated with this SFTP server"""
+        # pylint: disable=attribute-defined-outside-init
 
-        self._logger = logger
+        self._chan = chan
+
+    @property
+    def connection(self):
+        """The channel associated with this SFTP server session"""
+
+        return self._chan.get_connection()
+
+    @property
+    def env(self):
+        """The environment associated with this SFTP server session
+
+           This method returns the environment set by the client
+           when this SFTP session was opened.
+
+           :returns: A dictionary containing the environment variables
+                     set by the client
+
+        """
+
+
+        return self._chan.get_environment()
+
+    @property
+    def logger(self):
+        """A logger associated with this SFTP server"""
+
+        return self._chan.logger
 
     def format_user(self, uid):
         """Return the user name associated with a uid
@@ -4820,8 +4888,6 @@
 def run_sftp_server(sftp_server, reader, writer):
     """Return a handler for an SFTP server session"""
 
-    sftp_server.logger = reader.logger
-
     handler = SFTPServerHandler(sftp_server, reader, writer)
 
     handler.logger.info('Starting SFTP server')
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/asyncssh-1.16.0/asyncssh/stream.py 
new/asyncssh-1.16.1/asyncssh/stream.py
--- old/asyncssh-1.16.0/asyncssh/stream.py      2019-03-03 06:11:20.000000000 
+0100
+++ new/asyncssh-1.16.1/asyncssh/stream.py      2019-03-30 22:01:08.000000000 
+0100
@@ -628,13 +628,13 @@
             self._chan.set_encoding(None)
             self._encoding = None
 
-            handler = run_sftp_server(self._sftp_factory(self._conn),
+            handler = run_sftp_server(self._sftp_factory.new(self._chan),
                                       stdin, stdout)
         elif self._allow_scp and command and command.startswith('scp '):
             self._chan.set_encoding(None)
             self._encoding = None
 
-            handler = run_scp_server(self._sftp_factory(self._conn),
+            handler = run_scp_server(self._sftp_factory.new(self._chan),
                                      command, stdin, stdout, stderr)
         else:
             handler = self._session_factory(stdin, stdout, stderr)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/asyncssh-1.16.0/asyncssh/version.py 
new/asyncssh-1.16.1/asyncssh/version.py
--- old/asyncssh-1.16.0/asyncssh/version.py     2019-03-03 07:05:25.000000000 
+0100
+++ new/asyncssh-1.16.1/asyncssh/version.py     2019-03-30 22:01:26.000000000 
+0100
@@ -26,4 +26,4 @@
 
 __url__ = 'http://asyncssh.timeheart.net'
 
-__version__ = '1.16.0'
+__version__ = '1.16.1'
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/asyncssh-1.16.0/asyncssh.egg-info/PKG-INFO 
new/asyncssh-1.16.1/asyncssh.egg-info/PKG-INFO
--- old/asyncssh-1.16.0/asyncssh.egg-info/PKG-INFO      2019-03-03 
08:34:30.000000000 +0100
+++ new/asyncssh-1.16.1/asyncssh.egg-info/PKG-INFO      2019-03-31 
03:59:06.000000000 +0200
@@ -1,6 +1,6 @@
 Metadata-Version: 2.1
 Name: asyncssh
-Version: 1.16.0
+Version: 1.16.1
 Summary: AsyncSSH: Asynchronous SSHv2 client and server library
 Home-page: http://asyncssh.timeheart.net
 Author: Ron Frederick
@@ -217,8 +217,8 @@
 Classifier: Topic :: Security :: Cryptography
 Classifier: Topic :: Software Development :: Libraries :: Python Modules
 Classifier: Topic :: System :: Networking
-Provides-Extra: libnacl
-Provides-Extra: pyOpenSSL
 Provides-Extra: gssapi
-Provides-Extra: bcrypt
+Provides-Extra: pyOpenSSL
 Provides-Extra: pypiwin32
+Provides-Extra: libnacl
+Provides-Extra: bcrypt
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/asyncssh-1.16.0/pylintrc new/asyncssh-1.16.1/pylintrc
--- old/asyncssh-1.16.0/pylintrc        2019-03-03 06:11:20.000000000 +0100
+++ new/asyncssh-1.16.1/pylintrc        2019-03-30 22:01:08.000000000 +0100
@@ -205,6 +205,12 @@
 expected-line-ending-format=
 
 
+[REFACTORING]
+
+# Maximum number of nested blocks for function / method body
+max-nested-blocks=10
+
+
 [LOGGING]
 
 # Logging modules to check that the string format arguments are in logging
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/asyncssh-1.16.0/tests/test_agent.py 
new/asyncssh-1.16.1/tests/test_agent.py
--- old/asyncssh-1.16.0/tests/test_agent.py     2018-09-08 23:52:10.000000000 
+0200
+++ new/asyncssh-1.16.1/tests/test_agent.py     2019-03-30 22:01:08.000000000 
+0100
@@ -30,9 +30,10 @@
 import asyncssh
 
 from asyncssh.agent import SSH_AGENT_SUCCESS, SSH_AGENT_FAILURE
+from asyncssh.crypto import ed25519_available
 from asyncssh.packet import Byte, String
 
-from .util import AsyncTestCase, asynctest, libnacl_available, run
+from .util import AsyncTestCase, asynctest, run
 
 
 def agent_test(func):
@@ -175,7 +176,7 @@
 
         algs = ['ssh-dss', 'ssh-rsa', 'ecdsa-sha2-nistp256']
 
-        if libnacl_available: # pragma: no branch
+        if ed25519_available: # pragma: no branch
             algs.append('ssh-ed25519')
 
         for alg_name in algs:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/asyncssh-1.16.0/tests/test_kex.py 
new/asyncssh-1.16.1/tests/test_kex.py
--- old/asyncssh-1.16.0/tests/test_kex.py       2019-03-03 06:11:20.000000000 
+0100
+++ new/asyncssh-1.16.1/tests/test_kex.py       2019-03-30 22:01:08.000000000 
+0100
@@ -27,6 +27,7 @@
 
 import asyncssh
 
+from asyncssh.crypto import curve25519_available, curve448_available
 from asyncssh.kex_dh import MSG_KEXDH_INIT, MSG_KEXDH_REPLY
 from asyncssh.kex_dh import MSG_KEX_DH_GEX_REQUEST, MSG_KEX_DH_GEX_GROUP
 from asyncssh.kex_dh import MSG_KEX_DH_GEX_INIT, MSG_KEX_DH_GEX_REPLY, 
_KexDHGex
@@ -483,6 +484,7 @@
         client_conn.close()
         server_conn.close()
 
+    @unittest.skipUnless(curve25519_available, 'Curve25519 not available')
     @asynctest
     def test_curve25519dh_errors(self):
         """Unit test error conditions in Curve25519DH key exchange"""
@@ -514,6 +516,7 @@
         client_conn.close()
         server_conn.close()
 
+    @unittest.skipUnless(curve448_available, 'Curve448 not available')
     @asynctest
     def test_curve448dh_errors(self):
         """Unit test error conditions in Curve448DH key exchange"""
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/asyncssh-1.16.0/tests/test_public_key.py 
new/asyncssh-1.16.1/tests/test_public_key.py
--- old/asyncssh-1.16.0/tests/test_public_key.py        2019-03-03 
06:11:20.000000000 +0100
+++ new/asyncssh-1.16.1/tests/test_public_key.py        2019-03-30 
22:01:08.000000000 +0100
@@ -996,26 +996,26 @@
             ('Invalid PEM PKCS#8 PBES2 PBKDF2 PRF',
              b'-----BEGIN ENCRYPTED PRIVATE KEY-----\n' +
              binascii.b2a_base64(der_encode(
-                 ((_ES2, ((_ES2_PBKDF2, (b'', 0, None)),
+                 ((_ES2, ((_ES2_PBKDF2, (b'', 1, None)),
                           (_ES2_AES128, None))), b''))) +
              b'-----END ENCRYPTED PRIVATE KEY-----'),
             ('Unknown PEM PKCS#8 PBES2 PBKDF2 PRF',
              b'-----BEGIN ENCRYPTED PRIVATE KEY-----\n' +
              binascii.b2a_base64(der_encode(
-                 ((_ES2, ((_ES2_PBKDF2, (b'', 0,
+                 ((_ES2, ((_ES2_PBKDF2, (b'', 1,
                                          (ObjectIdentifier('1.1'), None))),
                           (_ES2_AES128, None))), b''))) +
              b'-----END ENCRYPTED PRIVATE KEY-----'),
             ('Invalid PEM PKCS#8 PBES2 encryption parameters',
              b'-----BEGIN ENCRYPTED PRIVATE KEY-----\n' +
              binascii.b2a_base64(der_encode(
-                 ((_ES2, ((_ES2_PBKDF2, (b'', 0)),
+                 ((_ES2, ((_ES2_PBKDF2, (b'', 1)),
                           (_ES2_AES128, None))), b''))) +
              b'-----END ENCRYPTED PRIVATE KEY-----'),
             ('Invalid length PEM PKCS#8 PBES2 IV',
              b'-----BEGIN ENCRYPTED PRIVATE KEY-----\n' +
              binascii.b2a_base64(der_encode(
-                 ((_ES2, ((_ES2_PBKDF2, (b'', 0)),
+                 ((_ES2, ((_ES2_PBKDF2, (b'', 1)),
                           (_ES2_AES128, b''))), b''))) +
              b'-----END ENCRYPTED PRIVATE KEY-----'),
             ('Invalid OpenSSH cipher',
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/asyncssh-1.16.0/tests/test_sftp.py 
new/asyncssh-1.16.1/tests/test_sftp.py
--- old/asyncssh-1.16.0/tests/test_sftp.py      2018-11-27 05:17:29.000000000 
+0100
+++ new/asyncssh-1.16.1/tests/test_sftp.py      2019-03-30 22:01:08.000000000 
+0100
@@ -145,6 +145,16 @@
             yield from super()._process_packet(pkttype, pktid, packet)
 
 
+class _CheckPropSFTPServer(SFTPServer):
+    """Return an FTP server which checks channel properties"""
+
+    def listdir(self, path):
+        """List the contents of a directory"""
+
+        if self.channel.get_connection() == self.connection: # pragma: no 
branch
+            return [SFTPName(k.encode()) for k in self.env.keys()]
+
+
 class _ChrootSFTPServer(SFTPServer):
     """Return an FTP server with a changed root"""
 
@@ -533,13 +543,14 @@
         """Test copying a file over SFTP"""
 
         for method in ('get', 'put', 'copy'):
-            with self.subTest(method=method):
-                try:
-                    self._create_file('src')
-                    yield from getattr(sftp, method)('src', 'dst')
-                    self._check_file('src', 'dst')
-                finally:
-                    remove('src dst')
+            for src in ('src', b'src', Path('src')):
+                with self.subTest(method=method, src=type(src)):
+                    try:
+                        self._create_file('src')
+                        yield from getattr(sftp, method)(src, 'dst')
+                        self._check_file('src', 'dst')
+                    finally:
+                        remove('src dst')
 
     @sftp_test
     def test_copy_progress(self, sftp):
@@ -766,30 +777,56 @@
     def test_glob(self, sftp):
         """Test a glob pattern match over SFTP"""
 
+        # pylint: disable=bad-whitespace
+
+        glob_tests = (
+            ('file*',                    ['file1', 'filedir']),
+            ('./file*',                  ['./file1', './filedir']),
+            (b'file*',                   [b'file1', b'filedir']),
+            (['file*'],                  ['file1', 'filedir']),
+            (['', 'file*'],              ['file1', 'filedir']),
+            (['file*/*2'],               ['filedir/file2', 
'filedir/filedir2']),
+            (['file*/*[3-9]'],           ['filedir/file3']),
+            (['**/file[12]'],            ['file1', 'filedir/file2']),
+            (['**/file*/'],              ['filedir', 'filedir/filedir2']),
+            ('filedir/file2',            ['filedir/file2']),
+            ('./filedir/file2',          ['./filedir/file2']),
+            ('filedir/file*',            ['filedir/file2', 'filedir/file3',
+                                          'filedir/filedir2']),
+            ('./filedir/file*',          ['./filedir/file2', './filedir/file3',
+                                          './filedir/filedir2']),
+            ('./filedir/filedir2/file*', ['./filedir/filedir2/file4',
+                                          './filedir/filedir2/file5']),
+            ('filedir/filedir2/file*',   ['filedir/filedir2/file4',
+                                          'filedir/filedir2/file5']),
+            ('./filedir/*/file4',        ['./filedir/filedir2/file4']),
+            ('filedir/*/file4',          ['filedir/filedir2/file4']),
+            ('./*/filedir2/file4',       ['./filedir/filedir2/file4']),
+            ('*/filedir2/file4',         ['filedir/filedir2/file4']),
+            ('*/filedir2/file*4',        ['filedir/filedir2/file4']),
+            ('./filedir/filedir*/file*', ['./filedir/filedir2/file4',
+                                          './filedir/filedir2/file5']),
+            ('filedir/filedir*/file*',   ['filedir/filedir2/file4',
+                                          'filedir/filedir2/file5']),
+            ('./**/filedir2/file4',      ['./filedir/filedir2/file4']),
+            ('**/filedir2/file4',        ['filedir/filedir2/file4']))
+
+        # pylint: enable=bad-whitespace
+
         try:
             os.mkdir('filedir')
             self._create_file('file1')
             self._create_file('filedir/file2')
             self._create_file('filedir/file3')
+            os.mkdir('filedir/filedir2')
+            self._create_file('filedir/filedir2/file4')
+            self._create_file('filedir/filedir2/file5')
+
+            for pattern, matches in glob_tests:
+                with self.subTest(pattern=pattern):
+                    self.assertEqual(sorted((yield from sftp.glob(pattern))),
+                                     matches)
 
-            self.assertEqual(sorted((yield from sftp.glob('file*'))),
-                             ['file1', 'filedir'])
-            self.assertEqual(sorted((yield from sftp.glob('./file*'))),
-                             ['./file1', './filedir'])
-            self.assertEqual(sorted((yield from sftp.glob(b'file*'))),
-                             [b'file1', b'filedir'])
-            self.assertEqual(sorted((yield from sftp.glob(['file*']))),
-                             ['file1', 'filedir'])
-            self.assertEqual(sorted((yield from sftp.glob(['', 'file*']))),
-                             ['file1', 'filedir'])
-            self.assertEqual(sorted((yield from sftp.glob(['file*/*2']))),
-                             ['filedir/file2'])
-            self.assertEqual(sorted((yield from sftp.glob(['file*/*[3-9]']))),
-                             ['filedir/file3'])
-            self.assertEqual(sorted((yield from sftp.glob(['**/file[12]']))),
-                             ['file1', 'filedir/file2'])
-            self.assertEqual(sorted((yield from sftp.glob(['**/file*/']))),
-                             ['filedir'])
             self.assertEqual((yield from sftp.glob([b'fil*1', 'fil*dir'])),
                              [b'file1', 'filedir'])
         finally:
@@ -1290,6 +1327,23 @@
 
             remove('file')
 
+    @sftp_test
+    def test_open_read_parallel(self, sftp):
+        """Test reading data from a file using parallel I/O"""
+
+        f = None
+
+        try:
+            self._create_file('file', 40*1024*'\0')
+
+            f = yield from sftp.open('file')
+            self.assertEqual(len((yield from f.read(64*1024))), 40*1024)
+        finally:
+            if f: # pragma: no branch
+                yield from f.close()
+
+            remove('file')
+
     def test_open_read_out_of_order(self):
         """Test parallel read with out-of-order responses"""
 
@@ -2247,6 +2301,31 @@
         asyncssh.set_sftp_log_level('WARNING')
 
 
+class _TestSFTPServerProperties(_CheckSFTP):
+    """Unit test for checking SFTP server properties"""
+
+    @classmethod
+    @asyncio.coroutine
+    def start_server(cls):
+        """Start an SFTP server which checks channel properties"""
+
+        return (yield from 
cls.create_server(sftp_factory=_CheckPropSFTPServer))
+
+    @asynctest
+    def test_properties(self):
+        """Test SFTP server channel properties"""
+
+        with (yield from self.connect()) as conn:
+            with (yield from conn.start_sftp_client(env={'A': 1,
+                                                         'B': 2})) as sftp:
+                files = yield from sftp.listdir()
+                self.assertEqual(sorted(files), ['A', 'B'])
+
+            yield from sftp.wait_closed() # pragma: no branch
+
+        yield from conn.wait_closed()
+
+
 class _TestSFTPChroot(_CheckSFTP):
     """Unit test for SFTP server with changed root"""
 
@@ -2681,12 +2760,15 @@
     def test_get(self):
         """Test getting a file over SCP"""
 
-        try:
-            self._create_file('src')
-            yield from scp((self._scp_server, 'src'), 'dst')
-            self._check_file('src', 'dst')
-        finally:
-            remove('src dst')
+        for src in ('src', b'src', Path('src')):
+            for dst in ('dst', b'dst', Path('dst')):
+                with self.subTest(src=type(src), dst=type(dst)):
+                    try:
+                        self._create_file('src')
+                        yield from scp((self._scp_server, src), dst)
+                        self._check_file('src', 'dst')
+                    finally:
+                        remove('src dst')
 
     @asynctest
     def test_get_bytes_path(self):


Reply via email to