diff --git a/CHANGELOG.md b/CHANGELOG.md index 267c942b..a68141bb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -38,6 +38,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ### Fixed +- Fixed `ResourceLocked` error translation on Windows [#484](https://github.com/PyFilesystem/pyfilesystem2/issues/484). - Fixed `MemoryFS.move` and `MemoryFS.movedir` not updating the name of moved resources, causing `MemoryFS.scandir` to use the old name. ([#510](https://github.com/PyFilesystem/pyfilesystem2/pull/510)). diff --git a/fs/error_tools.py b/fs/error_tools.py index bdb3818c..c45db2b5 100644 --- a/fs/error_tools.py +++ b/fs/error_tools.py @@ -84,7 +84,11 @@ def __exit__( _errno = exc_value.errno fserror = os_errors.get(_errno, errors.OperationFailed) if _errno == errno.EACCES and sys.platform == "win32": - if getattr(exc_value, "args", None) == 32: # pragma: no cover + windows_error = getattr(exc_value, "winerror", 0) + exception_args = getattr(exc_value, "args", None) or (0,) + if ( + windows_error == 32 or exception_args[0] == errno.EACCES + ): # pragma: no cover fserror = errors.ResourceLocked reraise(fserror, fserror(self._path, exc=exc_value), traceback) diff --git a/tests/test_error_tools.py b/tests/test_error_tools.py index 4f6aa324..d3d706c5 100644 --- a/tests/test_error_tools.py +++ b/tests/test_error_tools.py @@ -1,6 +1,7 @@ from __future__ import unicode_literals import errno +import sys import unittest import fs.errors @@ -23,3 +24,14 @@ def test_convert_enametoolong(self): raise exception self.assertEqual(ctx.exception.exc, exception) self.assertEqual(ctx.exception.path, "/tmp/test") + + @unittest.skipIf(sys.platform != "win32", "requires Windows") + def test_convert_resourcelocked_windows(self): + # errno should be ignored on Windows so we pass in a bogus number. + exception = OSError(123456, "resource locked", None, 32) + with self.assertRaises(fs.errors.ResourceLocked) as ctx: + with convert_os_errors("stat", "/tmp/test"): + raise exception + + self.assertEqual(ctx.exception.exc, exception) + self.assertEqual(ctx.exception.path, "/tmp/test")