action-hero icon indicating copy to clipboard operation
action-hero copied to clipboard

test_on_multiple_mixed_existing_files fails on Windows Python 3.7+

Open jayvdb opened this issue 2 years ago • 0 comments

Only Python 3.7+ are available in Windows Store atm, and 3.7, 3.8 and 3.10 all have same error.

I dont see any Windows specific notes in https://docs.python.org/3/library/tempfile.html#tempfile.mkstemp , however there is one in https://docs.python.org/3/library/os.html#os.remove .

_________ TestEnsureFileAction.test_on_multiple_mixed_existing_files __________

self = <tests.test_path.TestEnsureFileAction testMethod=test_on_multiple_mixed_existing_files>

    def test_on_multiple_mixed_existing_files(self):
        self.parser.add_argument("--path", nargs="+", action=EnsureFileAction)
        with tempfile.TemporaryDirectory() as parent_directory:
            # Specify few new temporary files
            file1 = tempfile.mkstemp(dir=parent_directory)[1]
            file2 = tempfile.mkstemp(dir=parent_directory)[1]

            # files deleted immediately to confirm they do not exist
            file3 = tempfile.mkstemp(dir=parent_directory)[1]
>           os.remove(file3)
E           PermissionError: [WinError 32] The process cannot access the file because it is being used by another process: 'C:\\Users\\61412\\AppData\\Local\\Temp\\tmpfhz9tczn\\tmp2a11n1sq'

tests\test_path.py:186: PermissionError

During handling of the above exception, another exception occurred:

path = 'C:\\Users\\61412\\AppData\\Local\\Temp\\tmpfhz9tczn'
onerror = <function TemporaryDirectory._rmtree.<locals>.onerror at 0x000001FEB85130A0>

    def _rmtree_unsafe(path, onerror):
        try:
            with os.scandir(path) as scandir_it:
                entries = list(scandir_it)
        except OSError:
            onerror(os.scandir, path, sys.exc_info())
            entries = []
        for entry in entries:
            fullname = entry.path
            if _rmtree_isdir(entry):
                try:
                    if entry.is_symlink():
                        # This can only happen if someone replaces
                        # a directory with a symlink after the call to
                        # os.scandir or entry.is_dir above.
                        raise OSError("Cannot call rmtree on a symbolic link")
                except OSError:
                    onerror(os.path.islink, fullname, sys.exc_info())
                    continue
                _rmtree_unsafe(fullname, onerror)
            else:
                try:
>                   os.unlink(fullname)
E                   PermissionError: [WinError 32] The process cannot access the file because it is being used by another process: 'C:\\Users\\61412\\AppData\\Local\\Temp\\tmpfhz9tczn\\tmp2a11n1sq'

C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.10_3.10.1520.0_x64__qbz5n2kfra8p0\lib\shutil.py:617: PermissionError

During handling of the above exception, another exception occurred:

func = <built-in function unlink>
path = 'C:\\Users\\61412\\AppData\\Local\\Temp\\tmpfhz9tczn\\tmp2a11n1sq'
exc_info = (<class 'PermissionError'>, PermissionError(13, 'The process cannot access the file because it is being used by another process'), <traceback object at 0x000001FEB8A34D00>)

    def onerror(func, path, exc_info):
        if issubclass(exc_info[0], PermissionError):
            def resetperms(path):
                try:
                    _os.chflags(path, 0)
                except AttributeError:
                    pass
                _os.chmod(path, 0o700)

            try:
                if path != name:
                    resetperms(_os.path.dirname(path))
                resetperms(path)

                try:
>                   _os.unlink(path)
E                   PermissionError: [WinError 32] The process cannot access the file because it is being used by another process: 'C:\\Users\\61412\\AppData\\Local\\Temp\\tmpfhz9tczn\\tmp2a11n1sq'

C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.10_3.10.1520.0_x64__qbz5n2kfra8p0\lib\tempfile.py:820: PermissionError

During handling of the above exception, another exception occurred:

self = <tests.test_path.TestEnsureFileAction testMethod=test_on_multiple_mixed_existing_files>

    def test_on_multiple_mixed_existing_files(self):
        self.parser.add_argument("--path", nargs="+", action=EnsureFileAction)
>       with tempfile.TemporaryDirectory() as parent_directory:

tests\test_path.py:179:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.10_3.10.1520.0_x64__qbz5n2kfra8p0\lib\tempfile.py:846: in __exit__
    self.cleanup()
C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.10_3.10.1520.0_x64__qbz5n2kfra8p0\lib\tempfile.py:850: in cleanup
    self._rmtree(self.name, ignore_errors=self._ignore_cleanup_errors)
C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.10_3.10.1520.0_x64__qbz5n2kfra8p0\lib\tempfile.py:832: in _rmtree
    _shutil.rmtree(name, onerror=onerror)
C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.10_3.10.1520.0_x64__qbz5n2kfra8p0\lib\shutil.py:749: in rmtree
    return _rmtree_unsafe(path, onerror)
C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.10_3.10.1520.0_x64__qbz5n2kfra8p0\lib\shutil.py:619: in _rmtree_unsafe
    onerror(os.unlink, fullname, sys.exc_info())
C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.10_3.10.1520.0_x64__qbz5n2kfra8p0\lib\tempfile.py:823: in onerror
    cls._rmtree(path, ignore_errors=ignore_errors)
C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.10_3.10.1520.0_x64__qbz5n2kfra8p0\lib\tempfile.py:832: in _rmtree
    _shutil.rmtree(name, onerror=onerror)
C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.10_3.10.1520.0_x64__qbz5n2kfra8p0\lib\shutil.py:749: in rmtree
    return _rmtree_unsafe(path, onerror)
C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.10_3.10.1520.0_x64__qbz5n2kfra8p0\lib\shutil.py:600: in _rmtree_unsafe
    onerror(os.scandir, path, sys.exc_info())
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

path = 'C:\\Users\\61412\\AppData\\Local\\Temp\\tmpfhz9tczn\\tmp2a11n1sq'
onerror = <function TemporaryDirectory._rmtree.<locals>.onerror at 0x000001FEB8511D80>

    def _rmtree_unsafe(path, onerror):
        try:
>           with os.scandir(path) as scandir_it:
E           NotADirectoryError: [WinError 267] The directory name is invalid: 'C:\\Users\\61412\\AppData\\Local\\Temp\\tmpfhz9tczn\\tmp2a11n1sq'

C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.10_3.10.1520.0_x64__qbz5n2kfra8p0\lib\shutil.py:597: NotADirectoryError

The test itself passes if I apply the following patch

diff --git a/tests/test_path.py b/tests/test_path.py
index 7e70d80..903e6e4 100644
--- a/tests/test_path.py
+++ b/tests/test_path.py
@@ -181,11 +181,10 @@ class TestEnsureFileAction(ActionHeroTestCase):
             file1 = tempfile.mkstemp(dir=parent_directory)[1]
             file2 = tempfile.mkstemp(dir=parent_directory)[1]

-            # files deleted immediately to confirm they do not exist
-            file3 = tempfile.mkstemp(dir=parent_directory)[1]
-            os.remove(file3)
-            file4 = tempfile.mkstemp(dir=parent_directory)[1]
-            os.remove(file4)
+            # Specify two temporary files that do not exist
+            file3 = tempfile.mktemp(dir=parent_directory)
+            file4 = tempfile.mktemp(dir=parent_directory)
+            self.assertNotEqual(file3, file4)

             mixed_files = [file1, file2, file3, file4]

@@ -200,7 +199,8 @@ class TestEnsureFileAction(ActionHeroTestCase):
             self.assertNotIn(False, [os.path.isfile(f) for f in mixed_files])

             # Tear down temporary files
-            [os.remove(f) for f in mixed_files]
+            if os.name != "nt":
+                [os.remove(f) for f in [file1, file2]]


 class TestPathIsValidAction(ActionHeroTestCase):

But, then the tempfile cleanup fails

tests\test_path.py F                                                     [100%]

================================== FAILURES ===================================
_________ TestEnsureFileAction.test_on_multiple_mixed_existing_files __________

path = 'C:\\Users\\61412\\AppData\\Local\\Temp\\tmp6v8sp0pt'
onerror = <function TemporaryDirectory._rmtree.<locals>.onerror at 0x000001E378A9CE50>

    def _rmtree_unsafe(path, onerror):
        try:
            with os.scandir(path) as scandir_it:
                entries = list(scandir_it)
        except OSError:
            onerror(os.scandir, path, sys.exc_info())
            entries = []
        for entry in entries:
            fullname = entry.path
            if _rmtree_isdir(entry):
                try:
                    if entry.is_symlink():
                        # This can only happen if someone replaces
                        # a directory with a symlink after the call to
                        # os.scandir or entry.is_dir above.
                        raise OSError("Cannot call rmtree on a symbolic link")
                except OSError:
                    onerror(os.path.islink, fullname, sys.exc_info())
                    continue
                _rmtree_unsafe(fullname, onerror)
            else:
                try:
>                   os.unlink(fullname)
E                   PermissionError: [WinError 32] The process cannot access the file because it is being used by another process: 'C:\\Users\\61412\\AppData\\Local\\Temp\\tmp6v8sp0pt\\tmpd9uaoh03'

C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.10_3.10.1520.0_x64__qbz5n2kfra8p0\lib\shutil.py:617: PermissionError

During handling of the above exception, another exception occurred:

func = <built-in function unlink>
path = 'C:\\Users\\61412\\AppData\\Local\\Temp\\tmp6v8sp0pt\\tmpd9uaoh03'
exc_info = (<class 'PermissionError'>, PermissionError(13, 'The process cannot access the file because it is being used by another process'), <traceback object at 0x000001E378AAA7C0>)

    def onerror(func, path, exc_info):
        if issubclass(exc_info[0], PermissionError):
            def resetperms(path):
                try:
                    _os.chflags(path, 0)
                except AttributeError:
                    pass
                _os.chmod(path, 0o700)

            try:
                if path != name:
                    resetperms(_os.path.dirname(path))
                resetperms(path)

                try:
>                   _os.unlink(path)
E                   PermissionError: [WinError 32] The process cannot access the file because it is being used by another process: 'C:\\Users\\61412\\AppData\\Local\\Temp\\tmp6v8sp0pt\\tmpd9uaoh03'

C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.10_3.10.1520.0_x64__qbz5n2kfra8p0\lib\tempfile.py:820: PermissionError

During handling of the above exception, another exception occurred:

self = <tests.test_path.TestEnsureFileAction testMethod=test_on_multiple_mixed_existing_files>

    def test_on_multiple_mixed_existing_files(self):
        self.parser.add_argument("--path", nargs="+", action=EnsureFileAction)
>       with tempfile.TemporaryDirectory() as parent_directory:

tests\test_path.py:179:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.10_3.10.1520.0_x64__qbz5n2kfra8p0\lib\tempfile.py:846: in __exit__
    self.cleanup()
C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.10_3.10.1520.0_x64__qbz5n2kfra8p0\lib\tempfile.py:850: in cleanup
    self._rmtree(self.name, ignore_errors=self._ignore_cleanup_errors)
C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.10_3.10.1520.0_x64__qbz5n2kfra8p0\lib\tempfile.py:832: in _rmtree
    _shutil.rmtree(name, onerror=onerror)
C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.10_3.10.1520.0_x64__qbz5n2kfra8p0\lib\shutil.py:749: in rmtree
    return _rmtree_unsafe(path, onerror)
C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.10_3.10.1520.0_x64__qbz5n2kfra8p0\lib\shutil.py:619: in _rmtree_unsafe
    onerror(os.unlink, fullname, sys.exc_info())
C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.10_3.10.1520.0_x64__qbz5n2kfra8p0\lib\tempfile.py:823: in onerror
    cls._rmtree(path, ignore_errors=ignore_errors)
C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.10_3.10.1520.0_x64__qbz5n2kfra8p0\lib\tempfile.py:832: in _rmtree
    _shutil.rmtree(name, onerror=onerror)
C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.10_3.10.1520.0_x64__qbz5n2kfra8p0\lib\shutil.py:749: in rmtree
    return _rmtree_unsafe(path, onerror)
C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.10_3.10.1520.0_x64__qbz5n2kfra8p0\lib\shutil.py:600: in _rmtree_unsafe
    onerror(os.scandir, path, sys.exc_info())
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

path = 'C:\\Users\\61412\\AppData\\Local\\Temp\\tmp6v8sp0pt\\tmpd9uaoh03'
onerror = <function TemporaryDirectory._rmtree.<locals>.onerror at 0x000001E378A9CEE0>

    def _rmtree_unsafe(path, onerror):
        try:
>           with os.scandir(path) as scandir_it:
E           NotADirectoryError: [WinError 267] The directory name is invalid: 'C:\\Users\\61412\\AppData\\Local\\Temp\\tmp6v8sp0pt\\tmpd9uaoh03'

C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.10_3.10.1520.0_x64__qbz5n2kfra8p0\lib\shutil.py:597: NotADirectoryError
=========================== short test summary info ===========================
FAILED tests/test_path.py::TestEnsureFileAction::test_on_multiple_mixed_existing_files
!!!!!!!!!!!!!!!!!!!!!!!!!! stopping after 1 failures !!!!!!!!!!!!!!!!!!!!!!!!!!
====================== 1 failed, 363 deselected in 0.57s ======================

As a result, I think it is easier to skip this test on Windows.

jayvdb avatar Jul 25 '22 04:07 jayvdb