Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package python-aioftp for openSUSE:Factory 
checked in at 2022-08-19 17:56:28
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-aioftp (Old)
 and      /work/SRC/openSUSE:Factory/.python-aioftp.new.2083 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-aioftp"

Fri Aug 19 17:56:28 2022 rev:6 rq:998097 version:0.21.3

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-aioftp/python-aioftp.changes      
2021-11-08 17:25:00.220725594 +0100
+++ /work/SRC/openSUSE:Factory/.python-aioftp.new.2083/python-aioftp.changes    
2022-08-19 17:59:10.536439527 +0200
@@ -1,0 +2,24 @@
+Thu Aug 18 10:42:42 UTC 2022 - Ben Greiner <c...@bnavigator.de>
+
+- Update to 0.21.3
+  * server/LIST: prevent broken links are listed, but can't be used
+    with stat
+  * server: make User.get_permissions async
+- Release 0.21.2
+  + tests: remove exception representation check
+- Release 0.21.1
+  * tests: replace more specific ConnectionRefusedError with
+    OSError for compatibility with FreeBSD (#152)
+- Release 0.21.0
+  * server: support PASV response with custom address (#150)
+- Release 0.20.1
+  * server: fix real directory resolve for windows (#147)
+- Release 0.20.0
+  * add client argument to set priority of custom list parser
+    (parse_list_line_custom_first) (#145)
+  * do not ignore failed parsing of list response (#144)
+- Enforce legacy pytest-asyncio mode
+  * gh#aio-libs/aioftp#155
+  * works around gh#pytest-dev/pytest-asyncio#390
+
+-------------------------------------------------------------------

Old:
----
  aioftp-0.19.0.tar.gz

New:
----
  aioftp-0.21.3.tar.gz

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

Other differences:
------------------
++++++ python-aioftp.spec ++++++
--- /var/tmp/diff_new_pack.c3UP6P/_old  2022-08-19 17:59:10.916440323 +0200
+++ /var/tmp/diff_new_pack.c3UP6P/_new  2022-08-19 17:59:10.920440332 +0200
@@ -1,7 +1,7 @@
 #
 # spec file for package python-aioftp
 #
-# Copyright (c) 2021 SUSE LLC
+# Copyright (c) 2022 SUSE LLC
 #
 # All modifications and additions to the file contributed by third parties
 # remain the property of their copyright owners, unless otherwise agreed
@@ -16,11 +16,10 @@
 #
 
 
-%{?!python_module:%define python_module() python-%{**} python3-%{**}}
+%{?!python_module:%define python_module() python3-%{**}}
 %define         skip_python2 1
-%define         skip_python36 1
 Name:           python-aioftp
-Version:        0.19.0
+Version:        0.21.3
 Release:        0
 Summary:        FTP client/server for asyncio
 License:        Apache-2.0
@@ -34,7 +33,6 @@
 # SECTION test requirements
 BuildRequires:  %{python_module async_timeout}
 BuildRequires:  %{python_module pytest-asyncio}
-BuildRequires:  %{python_module pytest-cov}
 BuildRequires:  %{python_module pytest}
 BuildRequires:  %{python_module siosocks >= 0.2.0}
 BuildRequires:  %{python_module trustme}
@@ -55,12 +53,12 @@
 %python_expand %fdupes %{buildroot}%{$python_sitelib}
 
 %check
-%pytest -k 'not test_server_side_throttle'
+%pytest --asyncio-mode=legacy
 
 %files %{python_files}
 %doc README.rst
 %license license.txt
-%{python_sitelib}/aioftp*.egg-info
+%{python_sitelib}/aioftp-%{version}*-info
 %{python_sitelib}/aioftp
 
 %changelog

++++++ aioftp-0.19.0.tar.gz -> aioftp-0.21.3.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/aioftp-0.19.0/PKG-INFO new/aioftp-0.21.3/PKG-INFO
--- old/aioftp-0.19.0/PKG-INFO  2021-10-26 21:52:54.011503000 +0200
+++ new/aioftp-0.21.3/PKG-INFO  2022-07-15 00:08:37.528395400 +0200
@@ -1,6 +1,6 @@
 Metadata-Version: 2.1
 Name: aioftp
-Version: 0.19.0
+Version: 0.21.3
 Summary: ftp client/server for asyncio
 Home-page: https://github.com/aio-libs/aioftp
 Author: pohmelie
@@ -26,11 +26,7 @@
 
 .. image:: 
https://github.com/aio-libs/aioftp/actions/workflows/ci.yml/badge.svg?branch=master
    :target: https://github.com/aio-libs/aioftp/actions/workflows/ci.yml
-   :alt: Github actions tests for master branch
-
-.. image:: 
https://github.com/aio-libs/aioftp/actions/workflows/cd.yml/badge.svg?branch=master
-   :target: https://github.com/aio-libs/aioftp/actions/workflows/cd.yml
-   :alt: Github actions deploy to pypi for master branch
+   :alt: Github actions ci for master branch
 
 .. image:: https://codecov.io/gh/aio-libs/aioftp/branch/master/graph/badge.svg
     :target: https://codecov.io/gh/aio-libs/aioftp
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/aioftp-0.19.0/README.rst new/aioftp-0.21.3/README.rst
--- old/aioftp-0.19.0/README.rst        2021-10-26 21:52:45.000000000 +0200
+++ new/aioftp-0.21.3/README.rst        2022-07-15 00:08:30.000000000 +0200
@@ -8,11 +8,7 @@
 
 .. image:: 
https://github.com/aio-libs/aioftp/actions/workflows/ci.yml/badge.svg?branch=master
    :target: https://github.com/aio-libs/aioftp/actions/workflows/ci.yml
-   :alt: Github actions tests for master branch
-
-.. image:: 
https://github.com/aio-libs/aioftp/actions/workflows/cd.yml/badge.svg?branch=master
-   :target: https://github.com/aio-libs/aioftp/actions/workflows/cd.yml
-   :alt: Github actions deploy to pypi for master branch
+   :alt: Github actions ci for master branch
 
 .. image:: https://codecov.io/gh/aio-libs/aioftp/branch/master/graph/badge.svg
     :target: https://codecov.io/gh/aio-libs/aioftp
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/aioftp-0.19.0/aioftp/__init__.py 
new/aioftp-0.21.3/aioftp/__init__.py
--- old/aioftp-0.19.0/aioftp/__init__.py        2021-10-26 21:52:45.000000000 
+0200
+++ new/aioftp-0.21.3/aioftp/__init__.py        2022-07-15 00:08:30.000000000 
+0200
@@ -7,7 +7,7 @@
 from .pathio import *
 from .server import *
 
-__version__ = "0.19.0"
+__version__ = "0.21.3"
 version = tuple(map(int, __version__.split(".")))
 
 __all__ = (
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/aioftp-0.19.0/aioftp/client.py 
new/aioftp-0.21.3/aioftp/client.py
--- old/aioftp-0.19.0/aioftp/client.py  2021-10-26 21:52:45.000000000 +0200
+++ new/aioftp-0.21.3/aioftp/client.py  2022-07-15 00:08:30.000000000 +0200
@@ -109,10 +109,16 @@
     def __init__(self, *,
                  socket_timeout=None,
                  connection_timeout=None,
-                 read_speed_limit=None, write_speed_limit=None,
-                 path_timeout=None, path_io_factory=pathio.PathIO,
-                 encoding="utf-8", ssl=None, parse_list_line_custom=None,
-                 passive_commands=("epsv", "pasv"), **siosocks_asyncio_kwargs):
+                 read_speed_limit=None,
+                 write_speed_limit=None,
+                 path_timeout=None,
+                 path_io_factory=pathio.PathIO,
+                 encoding="utf-8",
+                 ssl=None,
+                 parse_list_line_custom=None,
+                 parse_list_line_custom_first=True,
+                 passive_commands=("epsv", "pasv"),
+                 **siosocks_asyncio_kwargs):
         self.socket_timeout = socket_timeout
         self.connection_timeout = connection_timeout
         self.throttle = StreamThrottle.from_limits(
@@ -125,6 +131,7 @@
         self.stream = None
         self.ssl = ssl
         self.parse_list_line_custom = parse_list_line_custom
+        self.parse_list_line_custom_first = parse_list_line_custom_first
         self._passive_commands = passive_commands
         self._open_connection = partial(open_connection, ssl=self.ssl,
                                         **siosocks_asyncio_kwargs)
@@ -520,11 +527,14 @@
         :rtype: (:py:class:`pathlib.PurePosixPath`, :py:class:`dict`)
         """
         ex = []
-        parsers = (
-            self.parse_list_line_custom,
+        parsers = [
             self.parse_list_line_unix,
             self.parse_list_line_windows,
-        )
+        ]
+        if self.parse_list_line_custom_first:
+            parsers = [self.parse_list_line_custom] + parsers
+        else:
+            parsers = parsers + [self.parse_list_line_custom]
         for parser in parsers:
             if parser is None:
                 continue
@@ -597,6 +607,9 @@
         dictionary with fields "modify", "type", "size". For more
         information see sources.
     :type parse_list_line_custom: callable
+    :param parse_list_line_custom_first: Should be custom parser tried first
+        or last
+    :type parse_list_line_custom_first: :py:class:`bool`
     :param **siosocks_asyncio_kwargs: siosocks key-word only arguments
     """
     async def connect(self, host, port=DEFAULT_PORT):
@@ -712,9 +725,10 @@
         """
         :py:func:`asyncio.coroutine`
 
-        List all files and directories in "path".
+        List all files and directories in "path". If "path" is a file,
+        then result will be empty
 
-        :param path: directory or file path
+        :param path: directory
         :type path: :py:class:`str` or :py:class:`pathlib.PurePosixPath`
 
         :param recursive: list recursively
@@ -781,11 +795,7 @@
                         else:
                             raise StopAsyncIteration
 
-                    try:
-                        name, info = cls.parse_line(line)
-                    except Exception:
-                        continue
-
+                    name, info = cls.parse_line(line)
                     stat = cls.path / name, info
                     if info["type"] == "dir" and recursive:
                         cls.directories.append(stat)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/aioftp-0.19.0/aioftp/server.py 
new/aioftp-0.21.3/aioftp/server.py
--- old/aioftp-0.19.0/aioftp/server.py  2021-10-26 21:52:45.000000000 +0200
+++ new/aioftp-0.21.3/aioftp/server.py  2022-07-15 00:08:30.000000000 +0200
@@ -139,7 +139,7 @@
         self.write_speed_limit_per_connection = \
             write_speed_limit_per_connection
 
-    def get_permissions(self, path):
+    async def get_permissions(self, path):
         """
         Return nearest parent permission for `path`.
 
@@ -536,7 +536,9 @@
         @functools.wraps(f)
         async def wrapper(cls, connection, rest, *args):
             real_path, virtual_path = cls.get_paths(connection, rest)
-            current_permission = connection.user.get_permissions(virtual_path)
+            current_permission = await connection.user.get_permissions(
+                virtual_path,
+            )
             for permission in self.permissions:
                 if not getattr(current_permission, permission):
                     connection.response("550", "permission denied")
@@ -619,6 +621,11 @@
         connection in bytes per second
     :type write_speed_limit_per_connection: :py:class:`int` or :py:class:`None`
 
+    :param ipv4_pasv_forced_response_address: external IPv4 address for passive
+        connections
+    :type ipv4_pasv_forced_response_address: :py:class:`str` or
+        :py:class:`None`
+
     :param data_ports: port numbers that are available for passive connections
     :type data_ports: :py:class:`collections.Iterable` or :py:class:`None`
 
@@ -644,6 +651,7 @@
                  write_speed_limit=None,
                  read_speed_limit_per_connection=None,
                  write_speed_limit_per_connection=None,
+                 ipv4_pasv_forced_response_address=None,
                  data_ports=None,
                  encoding="utf-8",
                  ssl=None):
@@ -653,6 +661,8 @@
         self.wait_future_timeout = wait_future_timeout
         self.path_io_factory = pathio.PathIONursery(path_io_factory)
         self.path_timeout = path_timeout
+        self.ipv4_pasv_forced_response_address = \
+            ipv4_pasv_forced_response_address
         if data_ports is not None:
             self.available_data_ports = asyncio.PriorityQueue()
             for data_port in data_ports:
@@ -988,7 +998,8 @@
             if tasks_to_wait:
                 await asyncio.wait(tasks_to_wait)
 
-    def get_paths(self, connection, path):
+    @staticmethod
+    def get_paths(connection, path):
         """
         Return *real* and *virtual* paths, resolves ".." with "up" action.
         *Real* path is path for path_io, when *virtual* deals with
@@ -1014,6 +1025,12 @@
                 resolved_virtual_path /= part
         base_path = connection.user.base_path
         real_path = base_path / resolved_virtual_path.relative_to("/")
+        # replace with `is_relative_to` check after 3.9+ requirements lands
+        try:
+            real_path.relative_to(base_path)
+        except ValueError:
+            real_path = base_path
+            resolved_virtual_path = pathlib.PurePosixPath("/")
         return real_path, resolved_virtual_path
 
     async def greeting(self, connection, rest):
@@ -1227,6 +1244,9 @@
             del connection.data_connection
             async with stream:
                 async for path in connection.path_io.list(real_path):
+                    if not (await connection.path_io.exists(path)):
+                        logger.warning("path %r does not exists", path)
+                        continue
                     s = await self.build_list_string(connection, path)
                     b = (s + END_OF_LINE).encode(encoding=self.encoding)
                     await stream.write(b)
@@ -1441,6 +1461,11 @@
         for sock in connection.passive_server.sockets:
             if sock.family == socket.AF_INET:
                 host, port = sock.getsockname()
+                # If the FTP server is behind NAT, the server needs to report
+                # its external IP instead of the internal IP so that the client
+                # is able to connect to the server.
+                if self.ipv4_pasv_forced_response_address:
+                    host = self.ipv4_pasv_forced_response_address
                 break
         else:
             connection.response("503", ["this server started in ipv6 mode"])
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/aioftp-0.19.0/aioftp.egg-info/PKG-INFO 
new/aioftp-0.21.3/aioftp.egg-info/PKG-INFO
--- old/aioftp-0.19.0/aioftp.egg-info/PKG-INFO  2021-10-26 21:52:53.000000000 
+0200
+++ new/aioftp-0.21.3/aioftp.egg-info/PKG-INFO  2022-07-15 00:08:37.000000000 
+0200
@@ -1,6 +1,6 @@
 Metadata-Version: 2.1
 Name: aioftp
-Version: 0.19.0
+Version: 0.21.3
 Summary: ftp client/server for asyncio
 Home-page: https://github.com/aio-libs/aioftp
 Author: pohmelie
@@ -26,11 +26,7 @@
 
 .. image:: 
https://github.com/aio-libs/aioftp/actions/workflows/ci.yml/badge.svg?branch=master
    :target: https://github.com/aio-libs/aioftp/actions/workflows/ci.yml
-   :alt: Github actions tests for master branch
-
-.. image:: 
https://github.com/aio-libs/aioftp/actions/workflows/cd.yml/badge.svg?branch=master
-   :target: https://github.com/aio-libs/aioftp/actions/workflows/cd.yml
-   :alt: Github actions deploy to pypi for master branch
+   :alt: Github actions ci for master branch
 
 .. image:: https://codecov.io/gh/aio-libs/aioftp/branch/master/graph/badge.svg
     :target: https://codecov.io/gh/aio-libs/aioftp
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/aioftp-0.19.0/doc-requirements.txt 
new/aioftp-0.21.3/doc-requirements.txt
--- old/aioftp-0.19.0/doc-requirements.txt      2021-10-26 21:52:45.000000000 
+0200
+++ new/aioftp-0.21.3/doc-requirements.txt      2022-07-15 00:08:30.000000000 
+0200
@@ -1,2 +1,3 @@
 sphinx
 alabaster
+docutils < 0.18.0
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/aioftp-0.19.0/history.rst 
new/aioftp-0.21.3/history.rst
--- old/aioftp-0.19.0/history.rst       2021-10-26 21:52:45.000000000 +0200
+++ new/aioftp-0.21.3/history.rst       2022-07-15 00:08:30.000000000 +0200
@@ -1,6 +1,37 @@
 x.x.x (xx-xx-xxxx)
 ------------------
 
+0.21.3 (15-07-2022)
+-------------------
+- server/`LIST`: prevent broken links are listed, but can't be used with `stat`
+- server: make `User.get_permissions` async
+
+0.21.2 (22-04-2022)
+-------------------
+- tests: remove exception representation check
+
+0.21.1 (20-04-2022)
+-------------------
+- tests: replace more specific `ConnectionRefusedError` with `OSError` for 
compatibility with FreeBSD (#152)
+Thanks to `AMDmi3 https://github.com/AMDmi3`_
+
+0.21.0 (18-03-2022)
+------------------
+- server: support PASV response with custom address (#150)
+Thanks to `janneronkko https://github.com/janneronkko`_
+
+0.20.1 (15-02-2022)
+------------------
+- server: fix real directory resolve for windows (#147)
+Thanks to `ported-pw https://github.com/ported-pw`_
+
+0.20.0 (27-12-2021)
+------------------
+
+- add client argument to set priority of custom list parser 
(`parse_list_line_custom_first`) (#145)
+- do not ignore failed parsing of list response (#144)
+Thanks to `spolloni https://github.com/spolloni`_
+
 0.19.0 (08-10-2021)
 ------------------
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/aioftp-0.19.0/tests/test_connection.py 
new/aioftp-0.21.3/tests/test_connection.py
--- old/aioftp-0.19.0/tests/test_connection.py  2021-10-26 21:52:45.000000000 
+0200
+++ new/aioftp-0.21.3/tests/test_connection.py  2022-07-15 00:08:30.000000000 
+0200
@@ -1,4 +1,5 @@
 import asyncio
+import ipaddress
 
 import pytest
 
@@ -119,6 +120,39 @@
         assert pair.server.available_data_ports.qsize() == 0
 
 
+@pytest.mark.asyncio
+async def test_pasv_connection_pasv_forced_response_address(pair_factory,
+                                                            Server,
+                                                            unused_tcp_port):
+    def ipv4_used():
+        try:
+            ipaddress.IPv4Address(pair.host)
+            return True
+        except ValueError:
+            return False
+
+    async with pair_factory(
+        server=Server(ipv4_pasv_forced_response_address='127.0.0.2'),
+    ) as pair:
+        assert pair.server.ipv4_pasv_forced_response_address == '127.0.0.2'
+
+        if ipv4_used():
+            # The connection fails here because the server starts to listen for
+            # the passive connections on the host (IPv4 address) that is used
+            # by the control channel. In reality, if the server is behind NAT,
+            # the server is reached with the defined external IPv4 address,
+            # i.e. we can check that the connection to
+            # pair.server.ipv4_pasv_forced_response_address failed to know that
+            # the server returned correct external IP
+            with pytest.raises(OSError):
+                await pair.client.get_passive_connection(commands=['pasv'])
+
+        # With epsv the connection should open as that does not use the
+        # external IPv4 address but just tells the client the port to connect
+        # to
+        await pair.client.get_passive_connection(commands=['epsv'])
+
+
 @pytest.mark.parametrize("method", ["epsv", "pasv"])
 @pytest.mark.asyncio
 async def test_pasv_connection_no_free_port(pair_factory, Server,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/aioftp-0.19.0/tests/test_extra.py 
new/aioftp-0.21.3/tests/test_extra.py
--- old/aioftp-0.19.0/tests/test_extra.py       2021-10-26 21:52:45.000000000 
+0200
+++ new/aioftp-0.21.3/tests/test_extra.py       2022-07-15 00:08:30.000000000 
+0200
@@ -31,7 +31,7 @@
 
 @pytest.mark.asyncio
 async def test_no_server(unused_tcp_port):
-    with pytest.raises(ConnectionRefusedError):
+    with pytest.raises(OSError):
         async with aioftp.Client.context("127.0.0.1", unused_tcp_port):
             pass
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/aioftp-0.19.0/tests/test_file.py 
new/aioftp-0.21.3/tests/test_file.py
--- old/aioftp-0.19.0/tests/test_file.py        2021-10-26 21:52:45.000000000 
+0200
+++ new/aioftp-0.21.3/tests/test_file.py        2022-07-15 00:08:30.000000000 
+0200
@@ -26,6 +26,14 @@
 
 
 @pytest.mark.asyncio
+async def test_mlsd_file(pair_factory):
+    async with pair_factory() as pair:
+        await pair.make_server_files("foo/bar.txt")
+        result = await pair.client.list("foo/bar.txt")
+        assert len(result) == 0
+
+
+@pytest.mark.asyncio
 async def test_file_download(pair_factory):
     async with pair_factory() as pair:
         await pair.make_server_files("foo", size=1, atom=b"foobar")
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/aioftp-0.19.0/tests/test_list_fallback.py 
new/aioftp-0.21.3/tests/test_list_fallback.py
--- old/aioftp-0.19.0/tests/test_list_fallback.py       2021-10-26 
21:52:45.000000000 +0200
+++ new/aioftp-0.21.3/tests/test_list_fallback.py       2022-07-15 
00:08:30.000000000 +0200
@@ -26,6 +26,8 @@
         assert len(files) == 1
         assert path == pathlib.PurePosixPath("bar/foo")
         assert stat["type"] == "file"
+        result = await pair.client.list("bar/foo")
+        assert len(result) == 0
 
 
 async def implemented_badly(connection, rest):
@@ -108,6 +110,33 @@
         pair.server.commands_mapping["mlst"] = not_implemented
         pair.server.commands_mapping["mlsd"] = not_implemented
         pair.server.build_list_string = builder
+        await pair.client.make_directory("bar")
+        (path, stat), *_ = files = await pair.client.list()
+        assert len(files) == 1
+        assert path == pathlib.PurePosixPath("bar")
+        assert stat == meta
+
+
+@pytest.mark.asyncio
+async def test_client_list_override_with_custom_last(pair_factory, Client):
+    meta = {"type": "file", "works": True}
+
+    def parser(b):
+        import pickle
+        return pickle.loads(bytes.fromhex(b.decode().rstrip("\r\n")))
+
+    async def builder(_, path):
+        import pickle
+        return pickle.dumps((path, meta)).hex()
+
+    client = Client(
+        parse_list_line_custom=parser,
+        parse_list_line_custom_first=False,
+    )
+    async with pair_factory(client) as pair:
+        pair.server.commands_mapping["mlst"] = not_implemented
+        pair.server.commands_mapping["mlsd"] = not_implemented
+        pair.server.build_list_string = builder
         await pair.client.make_directory("bar")
         (path, stat), *_ = files = await pair.client.list()
         assert len(files) == 1
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/aioftp-0.19.0/tests/test_simple_functions.py 
new/aioftp-0.21.3/tests/test_simple_functions.py
--- old/aioftp-0.19.0/tests/test_simple_functions.py    2021-10-26 
21:52:45.000000000 +0200
+++ new/aioftp-0.21.3/tests/test_simple_functions.py    2022-07-15 
00:08:30.000000000 +0200
@@ -230,3 +230,17 @@
     b = aioftp.Server.build_list_mtime
     assert b(now, now) == "Jan  1 00:00"
     assert b(past, now) == "Jan  1  2001"
+
+
+def test_get_paths_windows_traverse():
+    base_path = pathlib.PureWindowsPath("C:\\ftp")
+    user = aioftp.User()
+    user.base_path = base_path
+    connection = aioftp.Connection(current_directory=base_path, user=user)
+    virtual_path = pathlib.PurePosixPath("/foo/C:\\windows")
+    real_path, resolved_virtual_path = aioftp.Server.get_paths(
+        connection,
+        virtual_path,
+    )
+    assert real_path == base_path
+    assert resolved_virtual_path == pathlib.PurePosixPath("/")

Reply via email to